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