rustc_expand/
base.rs

1use std::any::Any;
2use std::default::Default;
3use std::iter;
4use std::path::Component::Prefix;
5use std::path::{Path, PathBuf};
6use std::rc::Rc;
7use std::sync::Arc;
8
9use rustc_ast::attr::{AttributeExt, MarkedAttrs};
10use rustc_ast::token::MetaVarKind;
11use rustc_ast::tokenstream::TokenStream;
12use rustc_ast::visit::{AssocCtxt, Visitor};
13use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind};
14use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
15use rustc_data_structures::sync;
16use rustc_errors::{BufferedEarlyLint, DiagCtxtHandle, ErrorGuaranteed, PResult};
17use rustc_feature::Features;
18use rustc_hir as hir;
19use rustc_hir::attrs::{AttributeKind, CfgEntry, Deprecation};
20use rustc_hir::def::MacroKinds;
21use rustc_hir::{Stability, find_attr};
22use rustc_lint_defs::RegisteredTools;
23use rustc_parse::MACRO_ARGUMENTS;
24use rustc_parse::parser::{ForceCollect, Parser};
25use rustc_session::config::CollapseMacroDebuginfo;
26use rustc_session::parse::ParseSess;
27use rustc_session::{Limit, Session};
28use rustc_span::def_id::{CrateNum, DefId, LocalDefId};
29use rustc_span::edition::Edition;
30use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId, MacroKind};
31use rustc_span::source_map::SourceMap;
32use rustc_span::{DUMMY_SP, FileName, Ident, Span, Symbol, kw, sym};
33use smallvec::{SmallVec, smallvec};
34use thin_vec::ThinVec;
35
36use crate::base::ast::MetaItemInner;
37use crate::errors;
38use crate::expand::{self, AstFragment, Invocation};
39use crate::mbe::macro_rules::ParserAnyMacro;
40use crate::module::DirOwnership;
41use crate::stats::MacroStat;
42
43// When adding new variants, make sure to
44// adjust the `visit_*` / `flat_map_*` calls in `InvocationCollector`
45// to use `assign_id!`
46#[derive(Debug, Clone)]
47pub enum Annotatable {
48    Item(Box<ast::Item>),
49    AssocItem(Box<ast::AssocItem>, AssocCtxt),
50    ForeignItem(Box<ast::ForeignItem>),
51    Stmt(Box<ast::Stmt>),
52    Expr(Box<ast::Expr>),
53    Arm(ast::Arm),
54    ExprField(ast::ExprField),
55    PatField(ast::PatField),
56    GenericParam(ast::GenericParam),
57    Param(ast::Param),
58    FieldDef(ast::FieldDef),
59    Variant(ast::Variant),
60    WherePredicate(ast::WherePredicate),
61    Crate(ast::Crate),
62}
63
64impl Annotatable {
65    pub fn span(&self) -> Span {
66        match self {
67            Annotatable::Item(item) => item.span,
68            Annotatable::AssocItem(assoc_item, _) => assoc_item.span,
69            Annotatable::ForeignItem(foreign_item) => foreign_item.span,
70            Annotatable::Stmt(stmt) => stmt.span,
71            Annotatable::Expr(expr) => expr.span,
72            Annotatable::Arm(arm) => arm.span,
73            Annotatable::ExprField(field) => field.span,
74            Annotatable::PatField(fp) => fp.pat.span,
75            Annotatable::GenericParam(gp) => gp.ident.span,
76            Annotatable::Param(p) => p.span,
77            Annotatable::FieldDef(sf) => sf.span,
78            Annotatable::Variant(v) => v.span,
79            Annotatable::WherePredicate(wp) => wp.span,
80            Annotatable::Crate(c) => c.spans.inner_span,
81        }
82    }
83
84    pub fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
85        match self {
86            Annotatable::Item(item) => item.visit_attrs(f),
87            Annotatable::AssocItem(assoc_item, _) => assoc_item.visit_attrs(f),
88            Annotatable::ForeignItem(foreign_item) => foreign_item.visit_attrs(f),
89            Annotatable::Stmt(stmt) => stmt.visit_attrs(f),
90            Annotatable::Expr(expr) => expr.visit_attrs(f),
91            Annotatable::Arm(arm) => arm.visit_attrs(f),
92            Annotatable::ExprField(field) => field.visit_attrs(f),
93            Annotatable::PatField(fp) => fp.visit_attrs(f),
94            Annotatable::GenericParam(gp) => gp.visit_attrs(f),
95            Annotatable::Param(p) => p.visit_attrs(f),
96            Annotatable::FieldDef(sf) => sf.visit_attrs(f),
97            Annotatable::Variant(v) => v.visit_attrs(f),
98            Annotatable::WherePredicate(wp) => wp.visit_attrs(f),
99            Annotatable::Crate(c) => c.visit_attrs(f),
100        }
101    }
102
103    pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) -> V::Result {
104        match self {
105            Annotatable::Item(item) => visitor.visit_item(item),
106            Annotatable::AssocItem(item, ctxt) => visitor.visit_assoc_item(item, *ctxt),
107            Annotatable::ForeignItem(foreign_item) => visitor.visit_foreign_item(foreign_item),
108            Annotatable::Stmt(stmt) => visitor.visit_stmt(stmt),
109            Annotatable::Expr(expr) => visitor.visit_expr(expr),
110            Annotatable::Arm(arm) => visitor.visit_arm(arm),
111            Annotatable::ExprField(field) => visitor.visit_expr_field(field),
112            Annotatable::PatField(fp) => visitor.visit_pat_field(fp),
113            Annotatable::GenericParam(gp) => visitor.visit_generic_param(gp),
114            Annotatable::Param(p) => visitor.visit_param(p),
115            Annotatable::FieldDef(sf) => visitor.visit_field_def(sf),
116            Annotatable::Variant(v) => visitor.visit_variant(v),
117            Annotatable::WherePredicate(wp) => visitor.visit_where_predicate(wp),
118            Annotatable::Crate(c) => visitor.visit_crate(c),
119        }
120    }
121
122    pub fn to_tokens(&self) -> TokenStream {
123        match self {
124            Annotatable::Item(node) => TokenStream::from_ast(node),
125            Annotatable::AssocItem(node, _) => TokenStream::from_ast(node),
126            Annotatable::ForeignItem(node) => TokenStream::from_ast(node),
127            Annotatable::Stmt(node) => {
128                assert!(!matches!(node.kind, ast::StmtKind::Empty));
129                TokenStream::from_ast(node)
130            }
131            Annotatable::Expr(node) => TokenStream::from_ast(node),
132            Annotatable::Arm(..)
133            | Annotatable::ExprField(..)
134            | Annotatable::PatField(..)
135            | Annotatable::GenericParam(..)
136            | Annotatable::Param(..)
137            | Annotatable::FieldDef(..)
138            | Annotatable::Variant(..)
139            | Annotatable::WherePredicate(..)
140            | Annotatable::Crate(..) => panic!("unexpected annotatable"),
141        }
142    }
143
144    pub fn expect_item(self) -> Box<ast::Item> {
145        match self {
146            Annotatable::Item(i) => i,
147            _ => panic!("expected Item"),
148        }
149    }
150
151    pub fn expect_trait_item(self) -> Box<ast::AssocItem> {
152        match self {
153            Annotatable::AssocItem(i, AssocCtxt::Trait) => i,
154            _ => panic!("expected Item"),
155        }
156    }
157
158    pub fn expect_impl_item(self) -> Box<ast::AssocItem> {
159        match self {
160            Annotatable::AssocItem(i, AssocCtxt::Impl { .. }) => i,
161            _ => panic!("expected Item"),
162        }
163    }
164
165    pub fn expect_foreign_item(self) -> Box<ast::ForeignItem> {
166        match self {
167            Annotatable::ForeignItem(i) => i,
168            _ => panic!("expected foreign item"),
169        }
170    }
171
172    pub fn expect_stmt(self) -> ast::Stmt {
173        match self {
174            Annotatable::Stmt(stmt) => *stmt,
175            _ => panic!("expected statement"),
176        }
177    }
178
179    pub fn expect_expr(self) -> Box<ast::Expr> {
180        match self {
181            Annotatable::Expr(expr) => expr,
182            _ => panic!("expected expression"),
183        }
184    }
185
186    pub fn expect_arm(self) -> ast::Arm {
187        match self {
188            Annotatable::Arm(arm) => arm,
189            _ => panic!("expected match arm"),
190        }
191    }
192
193    pub fn expect_expr_field(self) -> ast::ExprField {
194        match self {
195            Annotatable::ExprField(field) => field,
196            _ => panic!("expected field"),
197        }
198    }
199
200    pub fn expect_pat_field(self) -> ast::PatField {
201        match self {
202            Annotatable::PatField(fp) => fp,
203            _ => panic!("expected field pattern"),
204        }
205    }
206
207    pub fn expect_generic_param(self) -> ast::GenericParam {
208        match self {
209            Annotatable::GenericParam(gp) => gp,
210            _ => panic!("expected generic parameter"),
211        }
212    }
213
214    pub fn expect_param(self) -> ast::Param {
215        match self {
216            Annotatable::Param(param) => param,
217            _ => panic!("expected parameter"),
218        }
219    }
220
221    pub fn expect_field_def(self) -> ast::FieldDef {
222        match self {
223            Annotatable::FieldDef(sf) => sf,
224            _ => panic!("expected struct field"),
225        }
226    }
227
228    pub fn expect_variant(self) -> ast::Variant {
229        match self {
230            Annotatable::Variant(v) => v,
231            _ => panic!("expected variant"),
232        }
233    }
234
235    pub fn expect_where_predicate(self) -> ast::WherePredicate {
236        match self {
237            Annotatable::WherePredicate(wp) => wp,
238            _ => panic!("expected where predicate"),
239        }
240    }
241
242    pub fn expect_crate(self) -> ast::Crate {
243        match self {
244            Annotatable::Crate(krate) => krate,
245            _ => panic!("expected krate"),
246        }
247    }
248}
249
250/// Result of an expansion that may need to be retried.
251/// Consider using this for non-`MultiItemModifier` expanders as well.
252pub enum ExpandResult<T, U> {
253    /// Expansion produced a result (possibly dummy).
254    Ready(T),
255    /// Expansion could not produce a result and needs to be retried.
256    Retry(U),
257}
258
259impl<T, U> ExpandResult<T, U> {
260    pub fn map<E, F: FnOnce(T) -> E>(self, f: F) -> ExpandResult<E, U> {
261        match self {
262            ExpandResult::Ready(t) => ExpandResult::Ready(f(t)),
263            ExpandResult::Retry(u) => ExpandResult::Retry(u),
264        }
265    }
266}
267
268impl<'cx> MacroExpanderResult<'cx> {
269    /// Creates a [`MacroExpanderResult::Ready`] from a [`TokenStream`].
270    ///
271    /// The `TokenStream` is forwarded without any expansion.
272    pub fn from_tts(
273        cx: &'cx mut ExtCtxt<'_>,
274        tts: TokenStream,
275        site_span: Span,
276        arm_span: Span,
277        macro_ident: Ident,
278    ) -> Self {
279        // Emit the SEMICOLON_IN_EXPRESSIONS_FROM_MACROS deprecation lint.
280        let is_local = true;
281
282        let parser = ParserAnyMacro::from_tts(cx, tts, site_span, arm_span, is_local, macro_ident);
283        ExpandResult::Ready(Box::new(parser))
284    }
285}
286
287pub trait MultiItemModifier {
288    /// `meta_item` is the attribute, and `item` is the item being modified.
289    fn expand(
290        &self,
291        ecx: &mut ExtCtxt<'_>,
292        span: Span,
293        meta_item: &ast::MetaItem,
294        item: Annotatable,
295        is_derive_const: bool,
296    ) -> ExpandResult<Vec<Annotatable>, Annotatable>;
297}
298
299impl<F> MultiItemModifier for F
300where
301    F: Fn(&mut ExtCtxt<'_>, Span, &ast::MetaItem, Annotatable) -> Vec<Annotatable>,
302{
303    fn expand(
304        &self,
305        ecx: &mut ExtCtxt<'_>,
306        span: Span,
307        meta_item: &ast::MetaItem,
308        item: Annotatable,
309        _is_derive_const: bool,
310    ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
311        ExpandResult::Ready(self(ecx, span, meta_item, item))
312    }
313}
314
315pub trait BangProcMacro {
316    fn expand<'cx>(
317        &self,
318        ecx: &'cx mut ExtCtxt<'_>,
319        span: Span,
320        ts: TokenStream,
321    ) -> Result<TokenStream, ErrorGuaranteed>;
322}
323
324impl<F> BangProcMacro for F
325where
326    F: Fn(TokenStream) -> TokenStream,
327{
328    fn expand<'cx>(
329        &self,
330        _ecx: &'cx mut ExtCtxt<'_>,
331        _span: Span,
332        ts: TokenStream,
333    ) -> Result<TokenStream, ErrorGuaranteed> {
334        // FIXME setup implicit context in TLS before calling self.
335        Ok(self(ts))
336    }
337}
338
339pub trait AttrProcMacro {
340    fn expand<'cx>(
341        &self,
342        ecx: &'cx mut ExtCtxt<'_>,
343        span: Span,
344        annotation: TokenStream,
345        annotated: TokenStream,
346    ) -> Result<TokenStream, ErrorGuaranteed>;
347}
348
349impl<F> AttrProcMacro for F
350where
351    F: Fn(TokenStream, TokenStream) -> TokenStream,
352{
353    fn expand<'cx>(
354        &self,
355        _ecx: &'cx mut ExtCtxt<'_>,
356        _span: Span,
357        annotation: TokenStream,
358        annotated: TokenStream,
359    ) -> Result<TokenStream, ErrorGuaranteed> {
360        // FIXME setup implicit context in TLS before calling self.
361        Ok(self(annotation, annotated))
362    }
363}
364
365/// Represents a thing that maps token trees to Macro Results
366pub trait TTMacroExpander: Any {
367    fn expand<'cx>(
368        &self,
369        ecx: &'cx mut ExtCtxt<'_>,
370        span: Span,
371        input: TokenStream,
372    ) -> MacroExpanderResult<'cx>;
373}
374
375pub type MacroExpanderResult<'cx> = ExpandResult<Box<dyn MacResult + 'cx>, ()>;
376
377pub type MacroExpanderFn =
378    for<'cx> fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> MacroExpanderResult<'cx>;
379
380impl<F: 'static> TTMacroExpander for F
381where
382    F: for<'cx> Fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> MacroExpanderResult<'cx>,
383{
384    fn expand<'cx>(
385        &self,
386        ecx: &'cx mut ExtCtxt<'_>,
387        span: Span,
388        input: TokenStream,
389    ) -> MacroExpanderResult<'cx> {
390        self(ecx, span, input)
391    }
392}
393
394pub trait GlobDelegationExpander {
395    fn expand(&self, ecx: &mut ExtCtxt<'_>) -> ExpandResult<Vec<(Ident, Option<Ident>)>, ()>;
396}
397
398// Use a macro because forwarding to a simple function has type system issues
399macro_rules! make_stmts_default {
400    ($me:expr) => {
401        $me.make_expr().map(|e| {
402            smallvec![ast::Stmt {
403                id: ast::DUMMY_NODE_ID,
404                span: e.span,
405                kind: ast::StmtKind::Expr(e),
406            }]
407        })
408    };
409}
410
411/// The result of a macro expansion. The return values of the various
412/// methods are spliced into the AST at the callsite of the macro.
413pub trait MacResult {
414    /// Creates an expression.
415    fn make_expr(self: Box<Self>) -> Option<Box<ast::Expr>> {
416        None
417    }
418
419    /// Creates zero or more items.
420    fn make_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::Item>; 1]>> {
421        None
422    }
423
424    /// Creates zero or more impl items.
425    fn make_impl_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::AssocItem>; 1]>> {
426        None
427    }
428
429    /// Creates zero or more impl items.
430    fn make_trait_impl_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::AssocItem>; 1]>> {
431        None
432    }
433
434    /// Creates zero or more trait items.
435    fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::AssocItem>; 1]>> {
436        None
437    }
438
439    /// Creates zero or more items in an `extern {}` block
440    fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::ForeignItem>; 1]>> {
441        None
442    }
443
444    /// Creates a pattern.
445    fn make_pat(self: Box<Self>) -> Option<Box<ast::Pat>> {
446        None
447    }
448
449    /// Creates zero or more statements.
450    ///
451    /// By default this attempts to create an expression statement,
452    /// returning None if that fails.
453    fn make_stmts(self: Box<Self>) -> Option<SmallVec<[ast::Stmt; 1]>> {
454        make_stmts_default!(self)
455    }
456
457    fn make_ty(self: Box<Self>) -> Option<Box<ast::Ty>> {
458        None
459    }
460
461    fn make_arms(self: Box<Self>) -> Option<SmallVec<[ast::Arm; 1]>> {
462        None
463    }
464
465    fn make_expr_fields(self: Box<Self>) -> Option<SmallVec<[ast::ExprField; 1]>> {
466        None
467    }
468
469    fn make_pat_fields(self: Box<Self>) -> Option<SmallVec<[ast::PatField; 1]>> {
470        None
471    }
472
473    fn make_generic_params(self: Box<Self>) -> Option<SmallVec<[ast::GenericParam; 1]>> {
474        None
475    }
476
477    fn make_params(self: Box<Self>) -> Option<SmallVec<[ast::Param; 1]>> {
478        None
479    }
480
481    fn make_field_defs(self: Box<Self>) -> Option<SmallVec<[ast::FieldDef; 1]>> {
482        None
483    }
484
485    fn make_variants(self: Box<Self>) -> Option<SmallVec<[ast::Variant; 1]>> {
486        None
487    }
488
489    fn make_where_predicates(self: Box<Self>) -> Option<SmallVec<[ast::WherePredicate; 1]>> {
490        None
491    }
492
493    fn make_crate(self: Box<Self>) -> Option<ast::Crate> {
494        // Fn-like macros cannot produce a crate.
495        unreachable!()
496    }
497}
498
499macro_rules! make_MacEager {
500    ( $( $fld:ident: $t:ty, )* ) => {
501        /// `MacResult` implementation for the common case where you've already
502        /// built each form of AST that you might return.
503        #[derive(Default)]
504        pub struct MacEager {
505            $(
506                pub $fld: Option<$t>,
507            )*
508        }
509
510        impl MacEager {
511            $(
512                pub fn $fld(v: $t) -> Box<dyn MacResult> {
513                    Box::new(MacEager {
514                        $fld: Some(v),
515                        ..Default::default()
516                    })
517                }
518            )*
519        }
520    }
521}
522
523make_MacEager! {
524    expr: Box<ast::Expr>,
525    pat: Box<ast::Pat>,
526    items: SmallVec<[Box<ast::Item>; 1]>,
527    impl_items: SmallVec<[Box<ast::AssocItem>; 1]>,
528    trait_items: SmallVec<[Box<ast::AssocItem>; 1]>,
529    foreign_items: SmallVec<[Box<ast::ForeignItem>; 1]>,
530    stmts: SmallVec<[ast::Stmt; 1]>,
531    ty: Box<ast::Ty>,
532}
533
534impl MacResult for MacEager {
535    fn make_expr(self: Box<Self>) -> Option<Box<ast::Expr>> {
536        self.expr
537    }
538
539    fn make_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::Item>; 1]>> {
540        self.items
541    }
542
543    fn make_impl_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::AssocItem>; 1]>> {
544        self.impl_items
545    }
546
547    fn make_trait_impl_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::AssocItem>; 1]>> {
548        self.impl_items
549    }
550
551    fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::AssocItem>; 1]>> {
552        self.trait_items
553    }
554
555    fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::ForeignItem>; 1]>> {
556        self.foreign_items
557    }
558
559    fn make_stmts(self: Box<Self>) -> Option<SmallVec<[ast::Stmt; 1]>> {
560        match self.stmts.as_ref().map_or(0, |s| s.len()) {
561            0 => make_stmts_default!(self),
562            _ => self.stmts,
563        }
564    }
565
566    fn make_pat(self: Box<Self>) -> Option<Box<ast::Pat>> {
567        if let Some(p) = self.pat {
568            return Some(p);
569        }
570        if let Some(e) = self.expr {
571            if matches!(e.kind, ast::ExprKind::Lit(_) | ast::ExprKind::IncludedBytes(_)) {
572                return Some(Box::new(ast::Pat {
573                    id: ast::DUMMY_NODE_ID,
574                    span: e.span,
575                    kind: PatKind::Expr(e),
576                    tokens: None,
577                }));
578            }
579        }
580        None
581    }
582
583    fn make_ty(self: Box<Self>) -> Option<Box<ast::Ty>> {
584        self.ty
585    }
586}
587
588/// Fill-in macro expansion result, to allow compilation to continue
589/// after hitting errors.
590#[derive(Copy, Clone)]
591pub struct DummyResult {
592    guar: Option<ErrorGuaranteed>,
593    span: Span,
594}
595
596impl DummyResult {
597    /// Creates a default MacResult that can be anything.
598    ///
599    /// Use this as a return value after hitting any errors and
600    /// calling `span_err`.
601    pub fn any(span: Span, guar: ErrorGuaranteed) -> Box<dyn MacResult + 'static> {
602        Box::new(DummyResult { guar: Some(guar), span })
603    }
604
605    /// Same as `any`, but must be a valid fragment, not error.
606    pub fn any_valid(span: Span) -> Box<dyn MacResult + 'static> {
607        Box::new(DummyResult { guar: None, span })
608    }
609
610    /// A plain dummy expression.
611    pub fn raw_expr(sp: Span, guar: Option<ErrorGuaranteed>) -> Box<ast::Expr> {
612        Box::new(ast::Expr {
613            id: ast::DUMMY_NODE_ID,
614            kind: if let Some(guar) = guar {
615                ast::ExprKind::Err(guar)
616            } else {
617                ast::ExprKind::Tup(ThinVec::new())
618            },
619            span: sp,
620            attrs: ast::AttrVec::new(),
621            tokens: None,
622        })
623    }
624}
625
626impl MacResult for DummyResult {
627    fn make_expr(self: Box<DummyResult>) -> Option<Box<ast::Expr>> {
628        Some(DummyResult::raw_expr(self.span, self.guar))
629    }
630
631    fn make_pat(self: Box<DummyResult>) -> Option<Box<ast::Pat>> {
632        Some(Box::new(ast::Pat {
633            id: ast::DUMMY_NODE_ID,
634            kind: PatKind::Wild,
635            span: self.span,
636            tokens: None,
637        }))
638    }
639
640    fn make_items(self: Box<DummyResult>) -> Option<SmallVec<[Box<ast::Item>; 1]>> {
641        Some(SmallVec::new())
642    }
643
644    fn make_impl_items(self: Box<DummyResult>) -> Option<SmallVec<[Box<ast::AssocItem>; 1]>> {
645        Some(SmallVec::new())
646    }
647
648    fn make_trait_impl_items(self: Box<DummyResult>) -> Option<SmallVec<[Box<ast::AssocItem>; 1]>> {
649        Some(SmallVec::new())
650    }
651
652    fn make_trait_items(self: Box<DummyResult>) -> Option<SmallVec<[Box<ast::AssocItem>; 1]>> {
653        Some(SmallVec::new())
654    }
655
656    fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::ForeignItem>; 1]>> {
657        Some(SmallVec::new())
658    }
659
660    fn make_stmts(self: Box<DummyResult>) -> Option<SmallVec<[ast::Stmt; 1]>> {
661        Some(smallvec![ast::Stmt {
662            id: ast::DUMMY_NODE_ID,
663            kind: ast::StmtKind::Expr(DummyResult::raw_expr(self.span, self.guar)),
664            span: self.span,
665        }])
666    }
667
668    fn make_ty(self: Box<DummyResult>) -> Option<Box<ast::Ty>> {
669        // FIXME(nnethercote): you might expect `ast::TyKind::Dummy` to be used here, but some
670        // values produced here end up being lowered to HIR, which `ast::TyKind::Dummy` does not
671        // support, so we use an empty tuple instead.
672        Some(Box::new(ast::Ty {
673            id: ast::DUMMY_NODE_ID,
674            kind: ast::TyKind::Tup(ThinVec::new()),
675            span: self.span,
676            tokens: None,
677        }))
678    }
679
680    fn make_arms(self: Box<DummyResult>) -> Option<SmallVec<[ast::Arm; 1]>> {
681        Some(SmallVec::new())
682    }
683
684    fn make_expr_fields(self: Box<DummyResult>) -> Option<SmallVec<[ast::ExprField; 1]>> {
685        Some(SmallVec::new())
686    }
687
688    fn make_pat_fields(self: Box<DummyResult>) -> Option<SmallVec<[ast::PatField; 1]>> {
689        Some(SmallVec::new())
690    }
691
692    fn make_generic_params(self: Box<DummyResult>) -> Option<SmallVec<[ast::GenericParam; 1]>> {
693        Some(SmallVec::new())
694    }
695
696    fn make_params(self: Box<DummyResult>) -> Option<SmallVec<[ast::Param; 1]>> {
697        Some(SmallVec::new())
698    }
699
700    fn make_field_defs(self: Box<DummyResult>) -> Option<SmallVec<[ast::FieldDef; 1]>> {
701        Some(SmallVec::new())
702    }
703
704    fn make_variants(self: Box<DummyResult>) -> Option<SmallVec<[ast::Variant; 1]>> {
705        Some(SmallVec::new())
706    }
707
708    fn make_crate(self: Box<DummyResult>) -> Option<ast::Crate> {
709        Some(ast::Crate {
710            attrs: Default::default(),
711            items: Default::default(),
712            spans: Default::default(),
713            id: ast::DUMMY_NODE_ID,
714            is_placeholder: Default::default(),
715        })
716    }
717}
718
719/// A syntax extension kind.
720#[derive(Clone)]
721pub enum SyntaxExtensionKind {
722    /// A `macro_rules!` macro that can work as any `MacroKind`
723    MacroRules(Arc<crate::MacroRulesMacroExpander>),
724
725    /// A token-based function-like macro.
726    Bang(
727        /// An expander with signature TokenStream -> TokenStream.
728        Arc<dyn BangProcMacro + sync::DynSync + sync::DynSend>,
729    ),
730
731    /// An AST-based function-like macro.
732    LegacyBang(
733        /// An expander with signature TokenStream -> AST.
734        Arc<dyn TTMacroExpander + sync::DynSync + sync::DynSend>,
735    ),
736
737    /// A token-based attribute macro.
738    Attr(
739        /// An expander with signature (TokenStream, TokenStream) -> TokenStream.
740        /// The first TokenStream is the attribute itself, the second is the annotated item.
741        /// The produced TokenStream replaces the input TokenStream.
742        Arc<dyn AttrProcMacro + sync::DynSync + sync::DynSend>,
743    ),
744
745    /// An AST-based attribute macro.
746    LegacyAttr(
747        /// An expander with signature (AST, AST) -> AST.
748        /// The first AST fragment is the attribute itself, the second is the annotated item.
749        /// The produced AST fragment replaces the input AST fragment.
750        Arc<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
751    ),
752
753    /// A trivial attribute "macro" that does nothing,
754    /// only keeps the attribute and marks it as inert,
755    /// thus making it ineligible for further expansion.
756    /// E.g. `#[default]`, `#[rustfmt::skip]`.
757    NonMacroAttr,
758
759    /// A token-based derive macro.
760    Derive(
761        /// An expander with signature TokenStream -> TokenStream.
762        /// The produced TokenStream is appended to the input TokenStream.
763        ///
764        /// FIXME: The text above describes how this should work. Currently it
765        /// is handled identically to `LegacyDerive`. It should be migrated to
766        /// a token-based representation like `Bang` and `Attr`, instead of
767        /// using `MultiItemModifier`.
768        Arc<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
769    ),
770
771    /// An AST-based derive macro.
772    LegacyDerive(
773        /// An expander with signature AST -> AST.
774        /// The produced AST fragment is appended to the input AST fragment.
775        Arc<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
776    ),
777
778    /// A glob delegation.
779    ///
780    /// This is for delegated function implementations, and has nothing to do with glob imports.
781    GlobDelegation(Arc<dyn GlobDelegationExpander + sync::DynSync + sync::DynSend>),
782}
783
784impl SyntaxExtensionKind {
785    /// Returns `Some(expander)` for a macro usable as a `LegacyBang`; otherwise returns `None`
786    ///
787    /// This includes a `MacroRules` with function-like rules.
788    pub fn as_legacy_bang(&self) -> Option<&(dyn TTMacroExpander + sync::DynSync + sync::DynSend)> {
789        match self {
790            SyntaxExtensionKind::LegacyBang(exp) => Some(exp.as_ref()),
791            SyntaxExtensionKind::MacroRules(exp) if exp.kinds().contains(MacroKinds::BANG) => {
792                Some(exp.as_ref())
793            }
794            _ => None,
795        }
796    }
797
798    /// Returns `Some(expander)` for a macro usable as an `Attr`; otherwise returns `None`
799    ///
800    /// This includes a `MacroRules` with `attr` rules.
801    pub fn as_attr(&self) -> Option<&(dyn AttrProcMacro + sync::DynSync + sync::DynSend)> {
802        match self {
803            SyntaxExtensionKind::Attr(exp) => Some(exp.as_ref()),
804            SyntaxExtensionKind::MacroRules(exp) if exp.kinds().contains(MacroKinds::ATTR) => {
805                Some(exp.as_ref())
806            }
807            _ => None,
808        }
809    }
810}
811
812/// A struct representing a macro definition in "lowered" form ready for expansion.
813pub struct SyntaxExtension {
814    /// A syntax extension kind.
815    pub kind: SyntaxExtensionKind,
816    /// Span of the macro definition.
817    pub span: Span,
818    /// List of unstable features that are treated as stable inside this macro.
819    pub allow_internal_unstable: Option<Arc<[Symbol]>>,
820    /// The macro's stability info.
821    pub stability: Option<Stability>,
822    /// The macro's deprecation info.
823    pub deprecation: Option<Deprecation>,
824    /// Names of helper attributes registered by this macro.
825    pub helper_attrs: Vec<Symbol>,
826    /// Edition of the crate in which this macro is defined.
827    pub edition: Edition,
828    /// Built-in macros have a couple of special properties like availability
829    /// in `#[no_implicit_prelude]` modules, so we have to keep this flag.
830    pub builtin_name: Option<Symbol>,
831    /// Suppresses the `unsafe_code` lint for code produced by this macro.
832    pub allow_internal_unsafe: bool,
833    /// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`) for this macro.
834    pub local_inner_macros: bool,
835    /// Should debuginfo for the macro be collapsed to the outermost expansion site (in other
836    /// words, was the macro definition annotated with `#[collapse_debuginfo]`)?
837    pub collapse_debuginfo: bool,
838}
839
840impl SyntaxExtension {
841    /// Returns which kinds of macro call this syntax extension.
842    pub fn macro_kinds(&self) -> MacroKinds {
843        match self.kind {
844            SyntaxExtensionKind::Bang(..)
845            | SyntaxExtensionKind::LegacyBang(..)
846            | SyntaxExtensionKind::GlobDelegation(..) => MacroKinds::BANG,
847            SyntaxExtensionKind::Attr(..)
848            | SyntaxExtensionKind::LegacyAttr(..)
849            | SyntaxExtensionKind::NonMacroAttr => MacroKinds::ATTR,
850            SyntaxExtensionKind::Derive(..) | SyntaxExtensionKind::LegacyDerive(..) => {
851                MacroKinds::DERIVE
852            }
853            SyntaxExtensionKind::MacroRules(ref m) => m.kinds(),
854        }
855    }
856
857    /// Constructs a syntax extension with default properties.
858    pub fn default(kind: SyntaxExtensionKind, edition: Edition) -> SyntaxExtension {
859        SyntaxExtension {
860            span: DUMMY_SP,
861            allow_internal_unstable: None,
862            stability: None,
863            deprecation: None,
864            helper_attrs: Vec::new(),
865            edition,
866            builtin_name: None,
867            kind,
868            allow_internal_unsafe: false,
869            local_inner_macros: false,
870            collapse_debuginfo: false,
871        }
872    }
873
874    fn collapse_debuginfo_by_name(
875        attr: &impl AttributeExt,
876    ) -> Result<CollapseMacroDebuginfo, Span> {
877        let list = attr.meta_item_list();
878        let Some([MetaItemInner::MetaItem(item)]) = list.as_deref() else {
879            return Err(attr.span());
880        };
881        if !item.is_word() {
882            return Err(item.span);
883        }
884
885        match item.name() {
886            Some(sym::no) => Ok(CollapseMacroDebuginfo::No),
887            Some(sym::external) => Ok(CollapseMacroDebuginfo::External),
888            Some(sym::yes) => Ok(CollapseMacroDebuginfo::Yes),
889            _ => Err(item.path.span),
890        }
891    }
892
893    /// if-ext - if macro from different crate (related to callsite code)
894    /// | cmd \ attr    | no  | (unspecified) | external | yes |
895    /// | no            | no  | no            | no       | no  |
896    /// | (unspecified) | no  | if-ext        | if-ext   | yes |
897    /// | external      | no  | if-ext        | if-ext   | yes |
898    /// | yes           | yes | yes           | yes      | yes |
899    fn get_collapse_debuginfo(sess: &Session, attrs: &[hir::Attribute], ext: bool) -> bool {
900        let flag = sess.opts.cg.collapse_macro_debuginfo;
901        let attr = ast::attr::find_by_name(attrs, sym::collapse_debuginfo)
902            .and_then(|attr| {
903                Self::collapse_debuginfo_by_name(attr)
904                    .map_err(|span| {
905                        sess.dcx().emit_err(errors::CollapseMacroDebuginfoIllegal { span })
906                    })
907                    .ok()
908            })
909            .unwrap_or_else(|| {
910                if find_attr!(attrs, AttributeKind::RustcBuiltinMacro { .. }) {
911                    CollapseMacroDebuginfo::Yes
912                } else {
913                    CollapseMacroDebuginfo::Unspecified
914                }
915            });
916        #[rustfmt::skip]
917        let collapse_table = [
918            [false, false, false, false],
919            [false, ext,   ext,   true],
920            [false, ext,   ext,   true],
921            [true,  true,  true,  true],
922        ];
923        collapse_table[flag as usize][attr as usize]
924    }
925
926    /// Constructs a syntax extension with the given properties
927    /// and other properties converted from attributes.
928    pub fn new(
929        sess: &Session,
930        kind: SyntaxExtensionKind,
931        span: Span,
932        helper_attrs: Vec<Symbol>,
933        edition: Edition,
934        name: Symbol,
935        attrs: &[hir::Attribute],
936        is_local: bool,
937    ) -> SyntaxExtension {
938        let allow_internal_unstable =
939            find_attr!(attrs, AttributeKind::AllowInternalUnstable(i, _) => i)
940                .map(|i| i.as_slice())
941                .unwrap_or_default();
942        let allow_internal_unsafe = find_attr!(attrs, AttributeKind::AllowInternalUnsafe(_));
943
944        let local_inner_macros = ast::attr::find_by_name(attrs, sym::macro_export)
945            .and_then(|macro_export| macro_export.meta_item_list())
946            .is_some_and(|l| ast::attr::list_contains_name(&l, sym::local_inner_macros));
947        let collapse_debuginfo = Self::get_collapse_debuginfo(sess, attrs, !is_local);
948        tracing::debug!(?name, ?local_inner_macros, ?collapse_debuginfo, ?allow_internal_unsafe);
949
950        let (builtin_name, helper_attrs) = match find_attr!(attrs, AttributeKind::RustcBuiltinMacro { builtin_name, helper_attrs, .. } => (builtin_name, helper_attrs))
951        {
952            // Override `helper_attrs` passed above if it's a built-in macro,
953            // marking `proc_macro_derive` macros as built-in is not a realistic use case.
954            Some((Some(name), helper_attrs)) => {
955                (Some(*name), helper_attrs.iter().copied().collect())
956            }
957            Some((None, _)) => (Some(name), Vec::new()),
958
959            // Not a built-in macro
960            None => (None, helper_attrs),
961        };
962
963        let stability = find_attr!(attrs, AttributeKind::Stability { stability, .. } => *stability);
964
965        // FIXME(jdonszelmann): make it impossible to miss the or_else in the typesystem
966        if let Some(sp) = find_attr!(attrs, AttributeKind::ConstStability { span, .. } => *span) {
967            sess.dcx().emit_err(errors::MacroConstStability {
968                span: sp,
969                head_span: sess.source_map().guess_head_span(span),
970            });
971        }
972        if let Some(sp) = find_attr!(attrs, AttributeKind::BodyStability{ span, .. } => *span) {
973            sess.dcx().emit_err(errors::MacroBodyStability {
974                span: sp,
975                head_span: sess.source_map().guess_head_span(span),
976            });
977        }
978
979        SyntaxExtension {
980            kind,
981            span,
982            allow_internal_unstable: (!allow_internal_unstable.is_empty())
983                // FIXME(jdonszelmann): avoid the into_iter/collect?
984                .then(|| allow_internal_unstable.iter().map(|i| i.0).collect::<Vec<_>>().into()),
985            stability,
986            deprecation: find_attr!(
987                attrs,
988                AttributeKind::Deprecation { deprecation, .. } => *deprecation
989            ),
990            helper_attrs,
991            edition,
992            builtin_name,
993            allow_internal_unsafe,
994            local_inner_macros,
995            collapse_debuginfo,
996        }
997    }
998
999    /// A dummy bang macro `foo!()`.
1000    pub fn dummy_bang(edition: Edition) -> SyntaxExtension {
1001        fn expander<'cx>(
1002            cx: &'cx mut ExtCtxt<'_>,
1003            span: Span,
1004            _: TokenStream,
1005        ) -> MacroExpanderResult<'cx> {
1006            ExpandResult::Ready(DummyResult::any(
1007                span,
1008                cx.dcx().span_delayed_bug(span, "expanded a dummy bang macro"),
1009            ))
1010        }
1011        SyntaxExtension::default(SyntaxExtensionKind::LegacyBang(Arc::new(expander)), edition)
1012    }
1013
1014    /// A dummy derive macro `#[derive(Foo)]`.
1015    pub fn dummy_derive(edition: Edition) -> SyntaxExtension {
1016        fn expander(
1017            _: &mut ExtCtxt<'_>,
1018            _: Span,
1019            _: &ast::MetaItem,
1020            _: Annotatable,
1021        ) -> Vec<Annotatable> {
1022            Vec::new()
1023        }
1024        SyntaxExtension::default(SyntaxExtensionKind::Derive(Arc::new(expander)), edition)
1025    }
1026
1027    pub fn non_macro_attr(edition: Edition) -> SyntaxExtension {
1028        SyntaxExtension::default(SyntaxExtensionKind::NonMacroAttr, edition)
1029    }
1030
1031    pub fn glob_delegation(
1032        trait_def_id: DefId,
1033        impl_def_id: LocalDefId,
1034        edition: Edition,
1035    ) -> SyntaxExtension {
1036        struct GlobDelegationExpanderImpl {
1037            trait_def_id: DefId,
1038            impl_def_id: LocalDefId,
1039        }
1040        impl GlobDelegationExpander for GlobDelegationExpanderImpl {
1041            fn expand(
1042                &self,
1043                ecx: &mut ExtCtxt<'_>,
1044            ) -> ExpandResult<Vec<(Ident, Option<Ident>)>, ()> {
1045                match ecx.resolver.glob_delegation_suffixes(self.trait_def_id, self.impl_def_id) {
1046                    Ok(suffixes) => ExpandResult::Ready(suffixes),
1047                    Err(Indeterminate) if ecx.force_mode => ExpandResult::Ready(Vec::new()),
1048                    Err(Indeterminate) => ExpandResult::Retry(()),
1049                }
1050            }
1051        }
1052
1053        let expander = GlobDelegationExpanderImpl { trait_def_id, impl_def_id };
1054        SyntaxExtension::default(SyntaxExtensionKind::GlobDelegation(Arc::new(expander)), edition)
1055    }
1056
1057    pub fn expn_data(
1058        &self,
1059        parent: LocalExpnId,
1060        call_site: Span,
1061        descr: Symbol,
1062        kind: MacroKind,
1063        macro_def_id: Option<DefId>,
1064        parent_module: Option<DefId>,
1065    ) -> ExpnData {
1066        ExpnData::new(
1067            ExpnKind::Macro(kind, descr),
1068            parent.to_expn_id(),
1069            call_site,
1070            self.span,
1071            self.allow_internal_unstable.clone(),
1072            self.edition,
1073            macro_def_id,
1074            parent_module,
1075            self.allow_internal_unsafe,
1076            self.local_inner_macros,
1077            self.collapse_debuginfo,
1078            self.builtin_name.is_some(),
1079        )
1080    }
1081}
1082
1083/// Error type that denotes indeterminacy.
1084pub struct Indeterminate;
1085
1086pub struct DeriveResolution {
1087    pub path: ast::Path,
1088    pub item: Annotatable,
1089    pub exts: Option<Arc<SyntaxExtension>>,
1090    pub is_const: bool,
1091}
1092
1093pub trait ResolverExpand {
1094    fn next_node_id(&mut self) -> NodeId;
1095    fn invocation_parent(&self, id: LocalExpnId) -> LocalDefId;
1096
1097    fn resolve_dollar_crates(&self);
1098    fn visit_ast_fragment_with_placeholders(
1099        &mut self,
1100        expn_id: LocalExpnId,
1101        fragment: &AstFragment,
1102    );
1103    fn register_builtin_macro(&mut self, name: Symbol, ext: SyntaxExtensionKind);
1104
1105    fn expansion_for_ast_pass(
1106        &mut self,
1107        call_site: Span,
1108        pass: AstPass,
1109        features: &[Symbol],
1110        parent_module_id: Option<NodeId>,
1111    ) -> LocalExpnId;
1112
1113    fn resolve_imports(&mut self);
1114
1115    fn resolve_macro_invocation(
1116        &mut self,
1117        invoc: &Invocation,
1118        eager_expansion_root: LocalExpnId,
1119        force: bool,
1120    ) -> Result<Arc<SyntaxExtension>, Indeterminate>;
1121
1122    fn record_macro_rule_usage(&mut self, mac_id: NodeId, rule_index: usize);
1123
1124    fn check_unused_macros(&mut self);
1125
1126    // Resolver interfaces for specific built-in macros.
1127    /// Does `#[derive(...)]` attribute with the given `ExpnId` have built-in `Copy` inside it?
1128    fn has_derive_copy(&self, expn_id: LocalExpnId) -> bool;
1129    /// Resolve paths inside the `#[derive(...)]` attribute with the given `ExpnId`.
1130    fn resolve_derives(
1131        &mut self,
1132        expn_id: LocalExpnId,
1133        force: bool,
1134        derive_paths: &dyn Fn() -> Vec<DeriveResolution>,
1135    ) -> Result<(), Indeterminate>;
1136    /// Take resolutions for paths inside the `#[derive(...)]` attribute with the given `ExpnId`
1137    /// back from resolver.
1138    fn take_derive_resolutions(&mut self, expn_id: LocalExpnId) -> Option<Vec<DeriveResolution>>;
1139    /// Path resolution logic for `#[cfg_accessible(path)]`.
1140    fn cfg_accessible(
1141        &mut self,
1142        expn_id: LocalExpnId,
1143        path: &ast::Path,
1144    ) -> Result<bool, Indeterminate>;
1145    fn macro_accessible(
1146        &mut self,
1147        expn_id: LocalExpnId,
1148        path: &ast::Path,
1149    ) -> Result<bool, Indeterminate>;
1150
1151    /// Decodes the proc-macro quoted span in the specified crate, with the specified id.
1152    /// No caching is performed.
1153    fn get_proc_macro_quoted_span(&self, krate: CrateNum, id: usize) -> Span;
1154
1155    /// The order of items in the HIR is unrelated to the order of
1156    /// items in the AST. However, we generate proc macro harnesses
1157    /// based on the AST order, and later refer to these harnesses
1158    /// from the HIR. This field keeps track of the order in which
1159    /// we generated proc macros harnesses, so that we can map
1160    /// HIR proc macros items back to their harness items.
1161    fn declare_proc_macro(&mut self, id: NodeId);
1162
1163    fn append_stripped_cfg_item(
1164        &mut self,
1165        parent_node: NodeId,
1166        ident: Ident,
1167        cfg: CfgEntry,
1168        cfg_span: Span,
1169    );
1170
1171    /// Tools registered with `#![register_tool]` and used by tool attributes and lints.
1172    fn registered_tools(&self) -> &RegisteredTools;
1173
1174    /// Mark this invocation id as a glob delegation.
1175    fn register_glob_delegation(&mut self, invoc_id: LocalExpnId);
1176
1177    /// Names of specific methods to which glob delegation expands.
1178    fn glob_delegation_suffixes(
1179        &self,
1180        trait_def_id: DefId,
1181        impl_def_id: LocalDefId,
1182    ) -> Result<Vec<(Ident, Option<Ident>)>, Indeterminate>;
1183
1184    /// Record the name of an opaque `Ty::ImplTrait` pre-expansion so that it can be used
1185    /// to generate an item name later that does not reference placeholder macros.
1186    fn insert_impl_trait_name(&mut self, id: NodeId, name: Symbol);
1187}
1188
1189pub trait LintStoreExpand {
1190    fn pre_expansion_lint(
1191        &self,
1192        sess: &Session,
1193        features: &Features,
1194        registered_tools: &RegisteredTools,
1195        node_id: NodeId,
1196        attrs: &[Attribute],
1197        items: &[Box<Item>],
1198        name: Symbol,
1199    );
1200}
1201
1202type LintStoreExpandDyn<'a> = Option<&'a (dyn LintStoreExpand + 'a)>;
1203
1204#[derive(Debug, Clone, Default)]
1205pub struct ModuleData {
1206    /// Path to the module starting from the crate name, like `my_crate::foo::bar`.
1207    pub mod_path: Vec<Ident>,
1208    /// Stack of paths to files loaded by out-of-line module items,
1209    /// used to detect and report recursive module inclusions.
1210    pub file_path_stack: Vec<PathBuf>,
1211    /// Directory to search child module files in,
1212    /// often (but not necessarily) the parent of the top file path on the `file_path_stack`.
1213    pub dir_path: PathBuf,
1214}
1215
1216impl ModuleData {
1217    pub fn with_dir_path(&self, dir_path: PathBuf) -> ModuleData {
1218        ModuleData {
1219            mod_path: self.mod_path.clone(),
1220            file_path_stack: self.file_path_stack.clone(),
1221            dir_path,
1222        }
1223    }
1224}
1225
1226#[derive(Clone)]
1227pub struct ExpansionData {
1228    pub id: LocalExpnId,
1229    pub depth: usize,
1230    pub module: Rc<ModuleData>,
1231    pub dir_ownership: DirOwnership,
1232    /// Some parent node that is close to this macro call
1233    pub lint_node_id: NodeId,
1234    pub is_trailing_mac: bool,
1235}
1236
1237/// One of these is made during expansion and incrementally updated as we go;
1238/// when a macro expansion occurs, the resulting nodes have the `backtrace()
1239/// -> expn_data` of their expansion context stored into their span.
1240pub struct ExtCtxt<'a> {
1241    pub sess: &'a Session,
1242    pub ecfg: expand::ExpansionConfig<'a>,
1243    pub num_standard_library_imports: usize,
1244    pub reduced_recursion_limit: Option<(Limit, ErrorGuaranteed)>,
1245    pub root_path: PathBuf,
1246    pub resolver: &'a mut dyn ResolverExpand,
1247    pub current_expansion: ExpansionData,
1248    /// Error recovery mode entered when expansion is stuck
1249    /// (or during eager expansion, but that's a hack).
1250    pub force_mode: bool,
1251    pub expansions: FxIndexMap<Span, Vec<String>>,
1252    /// Used for running pre-expansion lints on freshly loaded modules.
1253    pub(super) lint_store: LintStoreExpandDyn<'a>,
1254    /// Used for storing lints generated during expansion, like `NAMED_ARGUMENTS_USED_POSITIONALLY`
1255    pub buffered_early_lint: Vec<BufferedEarlyLint>,
1256    /// When we 'expand' an inert attribute, we leave it
1257    /// in the AST, but insert it here so that we know
1258    /// not to expand it again.
1259    pub(super) expanded_inert_attrs: MarkedAttrs,
1260    /// `-Zmacro-stats` data.
1261    pub macro_stats: FxHashMap<(Symbol, MacroKind), MacroStat>,
1262    pub nb_macro_errors: usize,
1263}
1264
1265impl<'a> ExtCtxt<'a> {
1266    pub fn new(
1267        sess: &'a Session,
1268        ecfg: expand::ExpansionConfig<'a>,
1269        resolver: &'a mut dyn ResolverExpand,
1270        lint_store: LintStoreExpandDyn<'a>,
1271    ) -> ExtCtxt<'a> {
1272        ExtCtxt {
1273            sess,
1274            ecfg,
1275            num_standard_library_imports: 0,
1276            reduced_recursion_limit: None,
1277            resolver,
1278            lint_store,
1279            root_path: PathBuf::new(),
1280            current_expansion: ExpansionData {
1281                id: LocalExpnId::ROOT,
1282                depth: 0,
1283                module: Default::default(),
1284                dir_ownership: DirOwnership::Owned { relative: None },
1285                lint_node_id: ast::CRATE_NODE_ID,
1286                is_trailing_mac: false,
1287            },
1288            force_mode: false,
1289            expansions: FxIndexMap::default(),
1290            expanded_inert_attrs: MarkedAttrs::new(),
1291            buffered_early_lint: vec![],
1292            macro_stats: Default::default(),
1293            nb_macro_errors: 0,
1294        }
1295    }
1296
1297    pub fn dcx(&self) -> DiagCtxtHandle<'a> {
1298        self.sess.dcx()
1299    }
1300
1301    /// Returns a `Folder` for deeply expanding all macros in an AST node.
1302    pub fn expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> {
1303        expand::MacroExpander::new(self, false)
1304    }
1305
1306    /// Returns a `Folder` that deeply expands all macros and assigns all `NodeId`s in an AST node.
1307    /// Once `NodeId`s are assigned, the node may not be expanded, removed, or otherwise modified.
1308    pub fn monotonic_expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> {
1309        expand::MacroExpander::new(self, true)
1310    }
1311    pub fn new_parser_from_tts(&self, stream: TokenStream) -> Parser<'a> {
1312        Parser::new(&self.sess.psess, stream, MACRO_ARGUMENTS)
1313    }
1314    pub fn source_map(&self) -> &'a SourceMap {
1315        self.sess.psess.source_map()
1316    }
1317    pub fn psess(&self) -> &'a ParseSess {
1318        &self.sess.psess
1319    }
1320    pub fn call_site(&self) -> Span {
1321        self.current_expansion.id.expn_data().call_site
1322    }
1323
1324    /// Returns the current expansion kind's description.
1325    pub(crate) fn expansion_descr(&self) -> String {
1326        let expn_data = self.current_expansion.id.expn_data();
1327        expn_data.kind.descr()
1328    }
1329
1330    /// Equivalent of `Span::def_site` from the proc macro API,
1331    /// except that the location is taken from the span passed as an argument.
1332    pub fn with_def_site_ctxt(&self, span: Span) -> Span {
1333        span.with_def_site_ctxt(self.current_expansion.id.to_expn_id())
1334    }
1335
1336    /// Equivalent of `Span::call_site` from the proc macro API,
1337    /// except that the location is taken from the span passed as an argument.
1338    pub fn with_call_site_ctxt(&self, span: Span) -> Span {
1339        span.with_call_site_ctxt(self.current_expansion.id.to_expn_id())
1340    }
1341
1342    /// Equivalent of `Span::mixed_site` from the proc macro API,
1343    /// except that the location is taken from the span passed as an argument.
1344    pub fn with_mixed_site_ctxt(&self, span: Span) -> Span {
1345        span.with_mixed_site_ctxt(self.current_expansion.id.to_expn_id())
1346    }
1347
1348    /// Returns span for the macro which originally caused the current expansion to happen.
1349    ///
1350    /// Stops backtracing at include! boundary.
1351    pub fn expansion_cause(&self) -> Option<Span> {
1352        self.current_expansion.id.expansion_cause()
1353    }
1354
1355    /// This method increases the internal macro errors count and then call `trace_macros_diag`.
1356    pub fn macro_error_and_trace_macros_diag(&mut self) {
1357        self.nb_macro_errors += 1;
1358        self.trace_macros_diag();
1359    }
1360
1361    pub fn trace_macros_diag(&mut self) {
1362        for (span, notes) in self.expansions.iter() {
1363            let mut db = self.dcx().create_note(errors::TraceMacro { span: *span });
1364            for note in notes {
1365                // FIXME: make this translatable
1366                #[allow(rustc::untranslatable_diagnostic)]
1367                db.note(note.clone());
1368            }
1369            db.emit();
1370        }
1371        // Fixme: does this result in errors?
1372        self.expansions.clear();
1373    }
1374    pub fn trace_macros(&self) -> bool {
1375        self.ecfg.trace_mac
1376    }
1377    pub fn set_trace_macros(&mut self, x: bool) {
1378        self.ecfg.trace_mac = x
1379    }
1380    pub fn std_path(&self, components: &[Symbol]) -> Vec<Ident> {
1381        let def_site = self.with_def_site_ctxt(DUMMY_SP);
1382        iter::once(Ident::new(kw::DollarCrate, def_site))
1383            .chain(components.iter().map(|&s| Ident::with_dummy_span(s)))
1384            .collect()
1385    }
1386    pub fn def_site_path(&self, components: &[Symbol]) -> Vec<Ident> {
1387        let def_site = self.with_def_site_ctxt(DUMMY_SP);
1388        components.iter().map(|&s| Ident::new(s, def_site)).collect()
1389    }
1390
1391    pub fn check_unused_macros(&mut self) {
1392        self.resolver.check_unused_macros();
1393    }
1394}
1395
1396/// Resolves a `path` mentioned inside Rust code, returning an absolute path.
1397///
1398/// This unifies the logic used for resolving `include_X!`.
1399pub fn resolve_path(sess: &Session, path: impl Into<PathBuf>, span: Span) -> PResult<'_, PathBuf> {
1400    let path = path.into();
1401
1402    // Relative paths are resolved relative to the file in which they are found
1403    // after macro expansion (that is, they are unhygienic).
1404    if !path.is_absolute() {
1405        let callsite = span.source_callsite();
1406        let source_map = sess.source_map();
1407        let Some(mut base_path) = source_map.span_to_filename(callsite).into_local_path() else {
1408            return Err(sess.dcx().create_err(errors::ResolveRelativePath {
1409                span,
1410                path: source_map
1411                    .filename_for_diagnostics(&source_map.span_to_filename(callsite))
1412                    .to_string(),
1413            }));
1414        };
1415        base_path.pop();
1416        base_path.push(path);
1417        Ok(base_path)
1418    } else {
1419        // This ensures that Windows verbatim paths are fixed if mixed path separators are used,
1420        // which can happen when `concat!` is used to join paths.
1421        match path.components().next() {
1422            Some(Prefix(prefix)) if prefix.kind().is_verbatim() => Ok(path.components().collect()),
1423            _ => Ok(path),
1424        }
1425    }
1426}
1427
1428/// If this item looks like a specific enums from `rental`, emit a fatal error.
1429/// See #73345 and #83125 for more details.
1430/// FIXME(#73933): Remove this eventually.
1431fn pretty_printing_compatibility_hack(item: &Item, psess: &ParseSess) {
1432    if let ast::ItemKind::Enum(ident, _, enum_def) = &item.kind
1433        && ident.name == sym::ProceduralMasqueradeDummyType
1434        && let [variant] = &*enum_def.variants
1435        && variant.ident.name == sym::Input
1436        && let FileName::Real(real) = psess.source_map().span_to_filename(ident.span)
1437        && let Some(c) = real
1438            .local_path()
1439            .unwrap_or(Path::new(""))
1440            .components()
1441            .flat_map(|c| c.as_os_str().to_str())
1442            .find(|c| c.starts_with("rental") || c.starts_with("allsorts-rental"))
1443    {
1444        let crate_matches = if c.starts_with("allsorts-rental") {
1445            true
1446        } else {
1447            let mut version = c.trim_start_matches("rental-").split('.');
1448            version.next() == Some("0")
1449                && version.next() == Some("5")
1450                && version.next().and_then(|c| c.parse::<u32>().ok()).is_some_and(|v| v < 6)
1451        };
1452
1453        if crate_matches {
1454            psess.dcx().emit_fatal(errors::ProcMacroBackCompat {
1455                crate_name: "rental".to_string(),
1456                fixed_version: "0.5.6".to_string(),
1457            });
1458        }
1459    }
1460}
1461
1462pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, psess: &ParseSess) {
1463    let item = match ann {
1464        Annotatable::Item(item) => item,
1465        Annotatable::Stmt(stmt) => match &stmt.kind {
1466            ast::StmtKind::Item(item) => item,
1467            _ => return,
1468        },
1469        _ => return,
1470    };
1471    pretty_printing_compatibility_hack(item, psess)
1472}
1473
1474pub(crate) fn stream_pretty_printing_compatibility_hack(
1475    kind: MetaVarKind,
1476    stream: &TokenStream,
1477    psess: &ParseSess,
1478) {
1479    let item = match kind {
1480        MetaVarKind::Item => {
1481            let mut parser = Parser::new(psess, stream.clone(), None);
1482            // No need to collect tokens for this simple check.
1483            parser
1484                .parse_item(ForceCollect::No)
1485                .expect("failed to reparse item")
1486                .expect("an actual item")
1487        }
1488        MetaVarKind::Stmt => {
1489            let mut parser = Parser::new(psess, stream.clone(), None);
1490            // No need to collect tokens for this simple check.
1491            let stmt = parser
1492                .parse_stmt(ForceCollect::No)
1493                .expect("failed to reparse")
1494                .expect("an actual stmt");
1495            match &stmt.kind {
1496                ast::StmtKind::Item(item) => item.clone(),
1497                _ => return,
1498            }
1499        }
1500        _ => return,
1501    };
1502    pretty_printing_compatibility_hack(&item, psess)
1503}