rustc_expand/
base.rs

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