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