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