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