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