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