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