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