1use std::default::Default;
2use std::iter;
3use std::path::Component::Prefix;
4use std::path::{Path, PathBuf};
5use std::rc::Rc;
6use std::sync::Arc;
7
8use rustc_ast::attr::{AttributeExt, MarkedAttrs};
9use rustc_ast::ptr::P;
10use rustc_ast::token::Nonterminal;
11use rustc_ast::tokenstream::TokenStream;
12use rustc_ast::visit::{AssocCtxt, Visitor};
13use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind};
14use rustc_attr_parsing::{self as attr, Deprecation, Stability};
15use rustc_data_structures::fx::FxIndexMap;
16use rustc_data_structures::sync;
17use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, PResult};
18use rustc_feature::Features;
19use rustc_lint_defs::{BufferedEarlyLint, RegisteredTools};
20use rustc_parse::MACRO_ARGUMENTS;
21use rustc_parse::parser::Parser;
22use rustc_session::config::CollapseMacroDebuginfo;
23use rustc_session::parse::ParseSess;
24use rustc_session::{Limit, Session};
25use rustc_span::def_id::{CrateNum, DefId, LocalDefId};
26use rustc_span::edition::Edition;
27use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId, MacroKind};
28use rustc_span::source_map::SourceMap;
29use rustc_span::{DUMMY_SP, FileName, Ident, Span, Symbol, kw, sym};
30use smallvec::{SmallVec, smallvec};
31use thin_vec::ThinVec;
32
33use crate::base::ast::MetaItemInner;
34use crate::errors;
35use crate::expand::{self, AstFragment, Invocation};
36use crate::module::DirOwnership;
37
38#[derive(Debug, Clone)]
42pub enum Annotatable {
43 Item(P<ast::Item>),
44 AssocItem(P<ast::AssocItem>, AssocCtxt),
45 ForeignItem(P<ast::ForeignItem>),
46 Stmt(P<ast::Stmt>),
47 Expr(P<ast::Expr>),
48 Arm(ast::Arm),
49 ExprField(ast::ExprField),
50 PatField(ast::PatField),
51 GenericParam(ast::GenericParam),
52 Param(ast::Param),
53 FieldDef(ast::FieldDef),
54 Variant(ast::Variant),
55 Crate(ast::Crate),
56}
57
58impl Annotatable {
59 pub fn span(&self) -> Span {
60 match self {
61 Annotatable::Item(item) => item.span,
62 Annotatable::AssocItem(assoc_item, _) => assoc_item.span,
63 Annotatable::ForeignItem(foreign_item) => foreign_item.span,
64 Annotatable::Stmt(stmt) => stmt.span,
65 Annotatable::Expr(expr) => expr.span,
66 Annotatable::Arm(arm) => arm.span,
67 Annotatable::ExprField(field) => field.span,
68 Annotatable::PatField(fp) => fp.pat.span,
69 Annotatable::GenericParam(gp) => gp.ident.span,
70 Annotatable::Param(p) => p.span,
71 Annotatable::FieldDef(sf) => sf.span,
72 Annotatable::Variant(v) => v.span,
73 Annotatable::Crate(c) => c.spans.inner_span,
74 }
75 }
76
77 pub fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
78 match self {
79 Annotatable::Item(item) => item.visit_attrs(f),
80 Annotatable::AssocItem(assoc_item, _) => assoc_item.visit_attrs(f),
81 Annotatable::ForeignItem(foreign_item) => foreign_item.visit_attrs(f),
82 Annotatable::Stmt(stmt) => stmt.visit_attrs(f),
83 Annotatable::Expr(expr) => expr.visit_attrs(f),
84 Annotatable::Arm(arm) => arm.visit_attrs(f),
85 Annotatable::ExprField(field) => field.visit_attrs(f),
86 Annotatable::PatField(fp) => fp.visit_attrs(f),
87 Annotatable::GenericParam(gp) => gp.visit_attrs(f),
88 Annotatable::Param(p) => p.visit_attrs(f),
89 Annotatable::FieldDef(sf) => sf.visit_attrs(f),
90 Annotatable::Variant(v) => v.visit_attrs(f),
91 Annotatable::Crate(c) => c.visit_attrs(f),
92 }
93 }
94
95 pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) -> V::Result {
96 match self {
97 Annotatable::Item(item) => visitor.visit_item(item),
98 Annotatable::AssocItem(item, ctxt) => visitor.visit_assoc_item(item, *ctxt),
99 Annotatable::ForeignItem(foreign_item) => visitor.visit_foreign_item(foreign_item),
100 Annotatable::Stmt(stmt) => visitor.visit_stmt(stmt),
101 Annotatable::Expr(expr) => visitor.visit_expr(expr),
102 Annotatable::Arm(arm) => visitor.visit_arm(arm),
103 Annotatable::ExprField(field) => visitor.visit_expr_field(field),
104 Annotatable::PatField(fp) => visitor.visit_pat_field(fp),
105 Annotatable::GenericParam(gp) => visitor.visit_generic_param(gp),
106 Annotatable::Param(p) => visitor.visit_param(p),
107 Annotatable::FieldDef(sf) => visitor.visit_field_def(sf),
108 Annotatable::Variant(v) => visitor.visit_variant(v),
109 Annotatable::Crate(c) => visitor.visit_crate(c),
110 }
111 }
112
113 pub fn to_tokens(&self) -> TokenStream {
114 match self {
115 Annotatable::Item(node) => TokenStream::from_ast(node),
116 Annotatable::AssocItem(node, _) => TokenStream::from_ast(node),
117 Annotatable::ForeignItem(node) => TokenStream::from_ast(node),
118 Annotatable::Stmt(node) => {
119 assert!(!matches!(node.kind, ast::StmtKind::Empty));
120 TokenStream::from_ast(node)
121 }
122 Annotatable::Expr(node) => TokenStream::from_ast(node),
123 Annotatable::Arm(..)
124 | Annotatable::ExprField(..)
125 | Annotatable::PatField(..)
126 | Annotatable::GenericParam(..)
127 | Annotatable::Param(..)
128 | Annotatable::FieldDef(..)
129 | Annotatable::Variant(..)
130 | Annotatable::Crate(..) => panic!("unexpected annotatable"),
131 }
132 }
133
134 pub fn expect_item(self) -> P<ast::Item> {
135 match self {
136 Annotatable::Item(i) => i,
137 _ => panic!("expected Item"),
138 }
139 }
140
141 pub fn expect_trait_item(self) -> P<ast::AssocItem> {
142 match self {
143 Annotatable::AssocItem(i, AssocCtxt::Trait) => i,
144 _ => panic!("expected Item"),
145 }
146 }
147
148 pub fn expect_impl_item(self) -> P<ast::AssocItem> {
149 match self {
150 Annotatable::AssocItem(i, AssocCtxt::Impl) => i,
151 _ => panic!("expected Item"),
152 }
153 }
154
155 pub fn expect_foreign_item(self) -> P<ast::ForeignItem> {
156 match self {
157 Annotatable::ForeignItem(i) => i,
158 _ => panic!("expected foreign item"),
159 }
160 }
161
162 pub fn expect_stmt(self) -> ast::Stmt {
163 match self {
164 Annotatable::Stmt(stmt) => stmt.into_inner(),
165 _ => panic!("expected statement"),
166 }
167 }
168
169 pub fn expect_expr(self) -> P<ast::Expr> {
170 match self {
171 Annotatable::Expr(expr) => expr,
172 _ => panic!("expected expression"),
173 }
174 }
175
176 pub fn expect_arm(self) -> ast::Arm {
177 match self {
178 Annotatable::Arm(arm) => arm,
179 _ => panic!("expected match arm"),
180 }
181 }
182
183 pub fn expect_expr_field(self) -> ast::ExprField {
184 match self {
185 Annotatable::ExprField(field) => field,
186 _ => panic!("expected field"),
187 }
188 }
189
190 pub fn expect_pat_field(self) -> ast::PatField {
191 match self {
192 Annotatable::PatField(fp) => fp,
193 _ => panic!("expected field pattern"),
194 }
195 }
196
197 pub fn expect_generic_param(self) -> ast::GenericParam {
198 match self {
199 Annotatable::GenericParam(gp) => gp,
200 _ => panic!("expected generic parameter"),
201 }
202 }
203
204 pub fn expect_param(self) -> ast::Param {
205 match self {
206 Annotatable::Param(param) => param,
207 _ => panic!("expected parameter"),
208 }
209 }
210
211 pub fn expect_field_def(self) -> ast::FieldDef {
212 match self {
213 Annotatable::FieldDef(sf) => sf,
214 _ => panic!("expected struct field"),
215 }
216 }
217
218 pub fn expect_variant(self) -> ast::Variant {
219 match self {
220 Annotatable::Variant(v) => v,
221 _ => panic!("expected variant"),
222 }
223 }
224
225 pub fn expect_crate(self) -> ast::Crate {
226 match self {
227 Annotatable::Crate(krate) => krate,
228 _ => panic!("expected krate"),
229 }
230 }
231}
232
233pub enum ExpandResult<T, U> {
236 Ready(T),
238 Retry(U),
240}
241
242impl<T, U> ExpandResult<T, U> {
243 pub fn map<E, F: FnOnce(T) -> E>(self, f: F) -> ExpandResult<E, U> {
244 match self {
245 ExpandResult::Ready(t) => ExpandResult::Ready(f(t)),
246 ExpandResult::Retry(u) => ExpandResult::Retry(u),
247 }
248 }
249}
250
251pub trait MultiItemModifier {
252 fn expand(
254 &self,
255 ecx: &mut ExtCtxt<'_>,
256 span: Span,
257 meta_item: &ast::MetaItem,
258 item: Annotatable,
259 is_derive_const: bool,
260 ) -> ExpandResult<Vec<Annotatable>, Annotatable>;
261}
262
263impl<F> MultiItemModifier for F
264where
265 F: Fn(&mut ExtCtxt<'_>, Span, &ast::MetaItem, Annotatable) -> Vec<Annotatable>,
266{
267 fn expand(
268 &self,
269 ecx: &mut ExtCtxt<'_>,
270 span: Span,
271 meta_item: &ast::MetaItem,
272 item: Annotatable,
273 _is_derive_const: bool,
274 ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
275 ExpandResult::Ready(self(ecx, span, meta_item, item))
276 }
277}
278
279pub trait BangProcMacro {
280 fn expand<'cx>(
281 &self,
282 ecx: &'cx mut ExtCtxt<'_>,
283 span: Span,
284 ts: TokenStream,
285 ) -> Result<TokenStream, ErrorGuaranteed>;
286}
287
288impl<F> BangProcMacro for F
289where
290 F: Fn(TokenStream) -> TokenStream,
291{
292 fn expand<'cx>(
293 &self,
294 _ecx: &'cx mut ExtCtxt<'_>,
295 _span: Span,
296 ts: TokenStream,
297 ) -> Result<TokenStream, ErrorGuaranteed> {
298 Ok(self(ts))
300 }
301}
302
303pub trait AttrProcMacro {
304 fn expand<'cx>(
305 &self,
306 ecx: &'cx mut ExtCtxt<'_>,
307 span: Span,
308 annotation: TokenStream,
309 annotated: TokenStream,
310 ) -> Result<TokenStream, ErrorGuaranteed>;
311}
312
313impl<F> AttrProcMacro for F
314where
315 F: Fn(TokenStream, TokenStream) -> TokenStream,
316{
317 fn expand<'cx>(
318 &self,
319 _ecx: &'cx mut ExtCtxt<'_>,
320 _span: Span,
321 annotation: TokenStream,
322 annotated: TokenStream,
323 ) -> Result<TokenStream, ErrorGuaranteed> {
324 Ok(self(annotation, annotated))
326 }
327}
328
329pub trait TTMacroExpander {
331 fn expand<'cx>(
332 &self,
333 ecx: &'cx mut ExtCtxt<'_>,
334 span: Span,
335 input: TokenStream,
336 ) -> MacroExpanderResult<'cx>;
337}
338
339pub type MacroExpanderResult<'cx> = ExpandResult<Box<dyn MacResult + 'cx>, ()>;
340
341pub type MacroExpanderFn =
342 for<'cx> fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> MacroExpanderResult<'cx>;
343
344impl<F> TTMacroExpander for F
345where
346 F: for<'cx> Fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> MacroExpanderResult<'cx>,
347{
348 fn expand<'cx>(
349 &self,
350 ecx: &'cx mut ExtCtxt<'_>,
351 span: Span,
352 input: TokenStream,
353 ) -> MacroExpanderResult<'cx> {
354 self(ecx, span, input)
355 }
356}
357
358pub trait GlobDelegationExpander {
359 fn expand(&self, ecx: &mut ExtCtxt<'_>) -> ExpandResult<Vec<(Ident, Option<Ident>)>, ()>;
360}
361
362macro_rules! make_stmts_default {
364 ($me:expr) => {
365 $me.make_expr().map(|e| {
366 smallvec![ast::Stmt {
367 id: ast::DUMMY_NODE_ID,
368 span: e.span,
369 kind: ast::StmtKind::Expr(e),
370 }]
371 })
372 };
373}
374
375pub trait MacResult {
378 fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
380 None
381 }
382
383 fn make_items(self: Box<Self>) -> Option<SmallVec<[P<ast::Item>; 1]>> {
385 None
386 }
387
388 fn make_impl_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
390 None
391 }
392
393 fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
395 None
396 }
397
398 fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[P<ast::ForeignItem>; 1]>> {
400 None
401 }
402
403 fn make_pat(self: Box<Self>) -> Option<P<ast::Pat>> {
405 None
406 }
407
408 fn make_stmts(self: Box<Self>) -> Option<SmallVec<[ast::Stmt; 1]>> {
413 make_stmts_default!(self)
414 }
415
416 fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
417 None
418 }
419
420 fn make_arms(self: Box<Self>) -> Option<SmallVec<[ast::Arm; 1]>> {
421 None
422 }
423
424 fn make_expr_fields(self: Box<Self>) -> Option<SmallVec<[ast::ExprField; 1]>> {
425 None
426 }
427
428 fn make_pat_fields(self: Box<Self>) -> Option<SmallVec<[ast::PatField; 1]>> {
429 None
430 }
431
432 fn make_generic_params(self: Box<Self>) -> Option<SmallVec<[ast::GenericParam; 1]>> {
433 None
434 }
435
436 fn make_params(self: Box<Self>) -> Option<SmallVec<[ast::Param; 1]>> {
437 None
438 }
439
440 fn make_field_defs(self: Box<Self>) -> Option<SmallVec<[ast::FieldDef; 1]>> {
441 None
442 }
443
444 fn make_variants(self: Box<Self>) -> Option<SmallVec<[ast::Variant; 1]>> {
445 None
446 }
447
448 fn make_crate(self: Box<Self>) -> Option<ast::Crate> {
449 unreachable!()
451 }
452}
453
454macro_rules! make_MacEager {
455 ( $( $fld:ident: $t:ty, )* ) => {
456 #[derive(Default)]
459 pub struct MacEager {
460 $(
461 pub $fld: Option<$t>,
462 )*
463 }
464
465 impl MacEager {
466 $(
467 pub fn $fld(v: $t) -> Box<dyn MacResult> {
468 Box::new(MacEager {
469 $fld: Some(v),
470 ..Default::default()
471 })
472 }
473 )*
474 }
475 }
476}
477
478make_MacEager! {
479 expr: P<ast::Expr>,
480 pat: P<ast::Pat>,
481 items: SmallVec<[P<ast::Item>; 1]>,
482 impl_items: SmallVec<[P<ast::AssocItem>; 1]>,
483 trait_items: SmallVec<[P<ast::AssocItem>; 1]>,
484 foreign_items: SmallVec<[P<ast::ForeignItem>; 1]>,
485 stmts: SmallVec<[ast::Stmt; 1]>,
486 ty: P<ast::Ty>,
487}
488
489impl MacResult for MacEager {
490 fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
491 self.expr
492 }
493
494 fn make_items(self: Box<Self>) -> Option<SmallVec<[P<ast::Item>; 1]>> {
495 self.items
496 }
497
498 fn make_impl_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
499 self.impl_items
500 }
501
502 fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
503 self.trait_items
504 }
505
506 fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[P<ast::ForeignItem>; 1]>> {
507 self.foreign_items
508 }
509
510 fn make_stmts(self: Box<Self>) -> Option<SmallVec<[ast::Stmt; 1]>> {
511 match self.stmts.as_ref().map_or(0, |s| s.len()) {
512 0 => make_stmts_default!(self),
513 _ => self.stmts,
514 }
515 }
516
517 fn make_pat(self: Box<Self>) -> Option<P<ast::Pat>> {
518 if let Some(p) = self.pat {
519 return Some(p);
520 }
521 if let Some(e) = self.expr {
522 if matches!(e.kind, ast::ExprKind::Lit(_) | ast::ExprKind::IncludedBytes(_)) {
523 return Some(P(ast::Pat {
524 id: ast::DUMMY_NODE_ID,
525 span: e.span,
526 kind: PatKind::Expr(e),
527 tokens: None,
528 }));
529 }
530 }
531 None
532 }
533
534 fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
535 self.ty
536 }
537}
538
539#[derive(Copy, Clone)]
542pub struct DummyResult {
543 guar: Option<ErrorGuaranteed>,
544 span: Span,
545}
546
547impl DummyResult {
548 pub fn any(span: Span, guar: ErrorGuaranteed) -> Box<dyn MacResult + 'static> {
553 Box::new(DummyResult { guar: Some(guar), span })
554 }
555
556 pub fn any_valid(span: Span) -> Box<dyn MacResult + 'static> {
558 Box::new(DummyResult { guar: None, span })
559 }
560
561 pub fn raw_expr(sp: Span, guar: Option<ErrorGuaranteed>) -> P<ast::Expr> {
563 P(ast::Expr {
564 id: ast::DUMMY_NODE_ID,
565 kind: if let Some(guar) = guar {
566 ast::ExprKind::Err(guar)
567 } else {
568 ast::ExprKind::Tup(ThinVec::new())
569 },
570 span: sp,
571 attrs: ast::AttrVec::new(),
572 tokens: None,
573 })
574 }
575}
576
577impl MacResult for DummyResult {
578 fn make_expr(self: Box<DummyResult>) -> Option<P<ast::Expr>> {
579 Some(DummyResult::raw_expr(self.span, self.guar))
580 }
581
582 fn make_pat(self: Box<DummyResult>) -> Option<P<ast::Pat>> {
583 Some(P(ast::Pat {
584 id: ast::DUMMY_NODE_ID,
585 kind: PatKind::Wild,
586 span: self.span,
587 tokens: None,
588 }))
589 }
590
591 fn make_items(self: Box<DummyResult>) -> Option<SmallVec<[P<ast::Item>; 1]>> {
592 Some(SmallVec::new())
593 }
594
595 fn make_impl_items(self: Box<DummyResult>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
596 Some(SmallVec::new())
597 }
598
599 fn make_trait_items(self: Box<DummyResult>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
600 Some(SmallVec::new())
601 }
602
603 fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[P<ast::ForeignItem>; 1]>> {
604 Some(SmallVec::new())
605 }
606
607 fn make_stmts(self: Box<DummyResult>) -> Option<SmallVec<[ast::Stmt; 1]>> {
608 Some(smallvec![ast::Stmt {
609 id: ast::DUMMY_NODE_ID,
610 kind: ast::StmtKind::Expr(DummyResult::raw_expr(self.span, self.guar)),
611 span: self.span,
612 }])
613 }
614
615 fn make_ty(self: Box<DummyResult>) -> Option<P<ast::Ty>> {
616 Some(P(ast::Ty {
620 id: ast::DUMMY_NODE_ID,
621 kind: ast::TyKind::Tup(ThinVec::new()),
622 span: self.span,
623 tokens: None,
624 }))
625 }
626
627 fn make_arms(self: Box<DummyResult>) -> Option<SmallVec<[ast::Arm; 1]>> {
628 Some(SmallVec::new())
629 }
630
631 fn make_expr_fields(self: Box<DummyResult>) -> Option<SmallVec<[ast::ExprField; 1]>> {
632 Some(SmallVec::new())
633 }
634
635 fn make_pat_fields(self: Box<DummyResult>) -> Option<SmallVec<[ast::PatField; 1]>> {
636 Some(SmallVec::new())
637 }
638
639 fn make_generic_params(self: Box<DummyResult>) -> Option<SmallVec<[ast::GenericParam; 1]>> {
640 Some(SmallVec::new())
641 }
642
643 fn make_params(self: Box<DummyResult>) -> Option<SmallVec<[ast::Param; 1]>> {
644 Some(SmallVec::new())
645 }
646
647 fn make_field_defs(self: Box<DummyResult>) -> Option<SmallVec<[ast::FieldDef; 1]>> {
648 Some(SmallVec::new())
649 }
650
651 fn make_variants(self: Box<DummyResult>) -> Option<SmallVec<[ast::Variant; 1]>> {
652 Some(SmallVec::new())
653 }
654
655 fn make_crate(self: Box<DummyResult>) -> Option<ast::Crate> {
656 Some(ast::Crate {
657 attrs: Default::default(),
658 items: Default::default(),
659 spans: Default::default(),
660 id: ast::DUMMY_NODE_ID,
661 is_placeholder: Default::default(),
662 })
663 }
664}
665
666pub enum SyntaxExtensionKind {
668 Bang(
670 Box<dyn BangProcMacro + sync::DynSync + sync::DynSend>,
672 ),
673
674 LegacyBang(
676 Box<dyn TTMacroExpander + sync::DynSync + sync::DynSend>,
678 ),
679
680 Attr(
682 Box<dyn AttrProcMacro + sync::DynSync + sync::DynSend>,
686 ),
687
688 LegacyAttr(
690 Box<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
694 ),
695
696 NonMacroAttr,
700
701 Derive(
703 Box<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
711 ),
712
713 LegacyDerive(
715 Box<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
718 ),
719
720 GlobDelegation(Box<dyn GlobDelegationExpander + sync::DynSync + sync::DynSend>),
722}
723
724pub struct SyntaxExtension {
726 pub kind: SyntaxExtensionKind,
728 pub span: Span,
730 pub allow_internal_unstable: Option<Arc<[Symbol]>>,
732 pub stability: Option<Stability>,
734 pub deprecation: Option<Deprecation>,
736 pub helper_attrs: Vec<Symbol>,
738 pub edition: Edition,
740 pub builtin_name: Option<Symbol>,
743 pub allow_internal_unsafe: bool,
745 pub local_inner_macros: bool,
747 pub collapse_debuginfo: bool,
750}
751
752impl SyntaxExtension {
753 pub fn macro_kind(&self) -> MacroKind {
755 match self.kind {
756 SyntaxExtensionKind::Bang(..)
757 | SyntaxExtensionKind::LegacyBang(..)
758 | SyntaxExtensionKind::GlobDelegation(..) => MacroKind::Bang,
759 SyntaxExtensionKind::Attr(..)
760 | SyntaxExtensionKind::LegacyAttr(..)
761 | SyntaxExtensionKind::NonMacroAttr => MacroKind::Attr,
762 SyntaxExtensionKind::Derive(..) | SyntaxExtensionKind::LegacyDerive(..) => {
763 MacroKind::Derive
764 }
765 }
766 }
767
768 pub fn default(kind: SyntaxExtensionKind, edition: Edition) -> SyntaxExtension {
770 SyntaxExtension {
771 span: DUMMY_SP,
772 allow_internal_unstable: None,
773 stability: None,
774 deprecation: None,
775 helper_attrs: Vec::new(),
776 edition,
777 builtin_name: None,
778 kind,
779 allow_internal_unsafe: false,
780 local_inner_macros: false,
781 collapse_debuginfo: false,
782 }
783 }
784
785 fn collapse_debuginfo_by_name(
786 attr: &impl AttributeExt,
787 ) -> Result<CollapseMacroDebuginfo, Span> {
788 let list = attr.meta_item_list();
789 let Some([MetaItemInner::MetaItem(item)]) = list.as_deref() else {
790 return Err(attr.span());
791 };
792 if !item.is_word() {
793 return Err(item.span);
794 }
795
796 match item.name_or_empty() {
797 sym::no => Ok(CollapseMacroDebuginfo::No),
798 sym::external => Ok(CollapseMacroDebuginfo::External),
799 sym::yes => Ok(CollapseMacroDebuginfo::Yes),
800 _ => Err(item.path.span),
801 }
802 }
803
804 fn get_collapse_debuginfo(sess: &Session, attrs: &[impl AttributeExt], ext: bool) -> bool {
811 let flag = sess.opts.cg.collapse_macro_debuginfo;
812 let attr = ast::attr::find_by_name(attrs, sym::collapse_debuginfo)
813 .and_then(|attr| {
814 Self::collapse_debuginfo_by_name(attr)
815 .map_err(|span| {
816 sess.dcx().emit_err(errors::CollapseMacroDebuginfoIllegal { span })
817 })
818 .ok()
819 })
820 .unwrap_or_else(|| {
821 if ast::attr::contains_name(attrs, sym::rustc_builtin_macro) {
822 CollapseMacroDebuginfo::Yes
823 } else {
824 CollapseMacroDebuginfo::Unspecified
825 }
826 });
827 #[rustfmt::skip]
828 let collapse_table = [
829 [false, false, false, false],
830 [false, ext, ext, true],
831 [false, ext, ext, true],
832 [true, true, true, true],
833 ];
834 collapse_table[flag as usize][attr as usize]
835 }
836
837 pub fn new(
840 sess: &Session,
841 features: &Features,
842 kind: SyntaxExtensionKind,
843 span: Span,
844 helper_attrs: Vec<Symbol>,
845 edition: Edition,
846 name: Symbol,
847 attrs: &[impl AttributeExt],
848 is_local: bool,
849 ) -> SyntaxExtension {
850 let allow_internal_unstable =
851 rustc_attr_parsing::allow_internal_unstable(sess, attrs).collect::<Vec<Symbol>>();
852
853 let allow_internal_unsafe = ast::attr::contains_name(attrs, sym::allow_internal_unsafe);
854 let local_inner_macros = ast::attr::find_by_name(attrs, sym::macro_export)
855 .and_then(|macro_export| macro_export.meta_item_list())
856 .is_some_and(|l| ast::attr::list_contains_name(&l, sym::local_inner_macros));
857 let collapse_debuginfo = Self::get_collapse_debuginfo(sess, attrs, !is_local);
858 tracing::debug!(?name, ?local_inner_macros, ?collapse_debuginfo, ?allow_internal_unsafe);
859
860 let (builtin_name, helper_attrs) = ast::attr::find_by_name(attrs, sym::rustc_builtin_macro)
861 .map(|attr| {
862 parse_macro_name_and_helper_attrs(sess.dcx(), attr, "built-in").map_or_else(
865 || (Some(name), Vec::new()),
866 |(name, helper_attrs)| (Some(name), helper_attrs),
867 )
868 })
869 .unwrap_or_else(|| (None, helper_attrs));
870 let stability = attr::find_stability(sess, attrs, span);
871 let const_stability = attr::find_const_stability(sess, attrs, span);
872 let body_stability = attr::find_body_stability(sess, attrs);
873 if let Some((_, sp)) = const_stability {
874 sess.dcx().emit_err(errors::MacroConstStability {
875 span: sp,
876 head_span: sess.source_map().guess_head_span(span),
877 });
878 }
879 if let Some((_, sp)) = body_stability {
880 sess.dcx().emit_err(errors::MacroBodyStability {
881 span: sp,
882 head_span: sess.source_map().guess_head_span(span),
883 });
884 }
885
886 SyntaxExtension {
887 kind,
888 span,
889 allow_internal_unstable: (!allow_internal_unstable.is_empty())
890 .then(|| allow_internal_unstable.into()),
891 stability: stability.map(|(s, _)| s),
892 deprecation: attr::find_deprecation(sess, features, attrs).map(|(d, _)| d),
893 helper_attrs,
894 edition,
895 builtin_name,
896 allow_internal_unsafe,
897 local_inner_macros,
898 collapse_debuginfo,
899 }
900 }
901
902 pub fn dummy_bang(edition: Edition) -> SyntaxExtension {
904 fn expander<'cx>(
905 cx: &'cx mut ExtCtxt<'_>,
906 span: Span,
907 _: TokenStream,
908 ) -> MacroExpanderResult<'cx> {
909 ExpandResult::Ready(DummyResult::any(
910 span,
911 cx.dcx().span_delayed_bug(span, "expanded a dummy bang macro"),
912 ))
913 }
914 SyntaxExtension::default(SyntaxExtensionKind::LegacyBang(Box::new(expander)), edition)
915 }
916
917 pub fn dummy_derive(edition: Edition) -> SyntaxExtension {
919 fn expander(
920 _: &mut ExtCtxt<'_>,
921 _: Span,
922 _: &ast::MetaItem,
923 _: Annotatable,
924 ) -> Vec<Annotatable> {
925 Vec::new()
926 }
927 SyntaxExtension::default(SyntaxExtensionKind::Derive(Box::new(expander)), edition)
928 }
929
930 pub fn non_macro_attr(edition: Edition) -> SyntaxExtension {
931 SyntaxExtension::default(SyntaxExtensionKind::NonMacroAttr, edition)
932 }
933
934 pub fn glob_delegation(
935 trait_def_id: DefId,
936 impl_def_id: LocalDefId,
937 edition: Edition,
938 ) -> SyntaxExtension {
939 struct GlobDelegationExpanderImpl {
940 trait_def_id: DefId,
941 impl_def_id: LocalDefId,
942 }
943 impl GlobDelegationExpander for GlobDelegationExpanderImpl {
944 fn expand(
945 &self,
946 ecx: &mut ExtCtxt<'_>,
947 ) -> ExpandResult<Vec<(Ident, Option<Ident>)>, ()> {
948 match ecx.resolver.glob_delegation_suffixes(self.trait_def_id, self.impl_def_id) {
949 Ok(suffixes) => ExpandResult::Ready(suffixes),
950 Err(Indeterminate) if ecx.force_mode => ExpandResult::Ready(Vec::new()),
951 Err(Indeterminate) => ExpandResult::Retry(()),
952 }
953 }
954 }
955
956 let expander = GlobDelegationExpanderImpl { trait_def_id, impl_def_id };
957 SyntaxExtension::default(SyntaxExtensionKind::GlobDelegation(Box::new(expander)), edition)
958 }
959
960 pub fn expn_data(
961 &self,
962 parent: LocalExpnId,
963 call_site: Span,
964 descr: Symbol,
965 macro_def_id: Option<DefId>,
966 parent_module: Option<DefId>,
967 ) -> ExpnData {
968 ExpnData::new(
969 ExpnKind::Macro(self.macro_kind(), descr),
970 parent.to_expn_id(),
971 call_site,
972 self.span,
973 self.allow_internal_unstable.clone(),
974 self.edition,
975 macro_def_id,
976 parent_module,
977 self.allow_internal_unsafe,
978 self.local_inner_macros,
979 self.collapse_debuginfo,
980 )
981 }
982}
983
984pub struct Indeterminate;
986
987pub struct DeriveResolution {
988 pub path: ast::Path,
989 pub item: Annotatable,
990 pub exts: Option<Arc<SyntaxExtension>>,
991 pub is_const: bool,
992}
993
994pub trait ResolverExpand {
995 fn next_node_id(&mut self) -> NodeId;
996 fn invocation_parent(&self, id: LocalExpnId) -> LocalDefId;
997
998 fn resolve_dollar_crates(&mut self);
999 fn visit_ast_fragment_with_placeholders(
1000 &mut self,
1001 expn_id: LocalExpnId,
1002 fragment: &AstFragment,
1003 );
1004 fn register_builtin_macro(&mut self, name: Symbol, ext: SyntaxExtensionKind);
1005
1006 fn expansion_for_ast_pass(
1007 &mut self,
1008 call_site: Span,
1009 pass: AstPass,
1010 features: &[Symbol],
1011 parent_module_id: Option<NodeId>,
1012 ) -> LocalExpnId;
1013
1014 fn resolve_imports(&mut self);
1015
1016 fn resolve_macro_invocation(
1017 &mut self,
1018 invoc: &Invocation,
1019 eager_expansion_root: LocalExpnId,
1020 force: bool,
1021 ) -> Result<Arc<SyntaxExtension>, Indeterminate>;
1022
1023 fn record_macro_rule_usage(&mut self, mac_id: NodeId, rule_index: usize);
1024
1025 fn check_unused_macros(&mut self);
1026
1027 fn has_derive_copy(&self, expn_id: LocalExpnId) -> bool;
1030 fn resolve_derives(
1032 &mut self,
1033 expn_id: LocalExpnId,
1034 force: bool,
1035 derive_paths: &dyn Fn() -> Vec<DeriveResolution>,
1036 ) -> Result<(), Indeterminate>;
1037 fn take_derive_resolutions(&mut self, expn_id: LocalExpnId) -> Option<Vec<DeriveResolution>>;
1040 fn cfg_accessible(
1042 &mut self,
1043 expn_id: LocalExpnId,
1044 path: &ast::Path,
1045 ) -> Result<bool, Indeterminate>;
1046 fn macro_accessible(
1047 &mut self,
1048 expn_id: LocalExpnId,
1049 path: &ast::Path,
1050 ) -> Result<bool, Indeterminate>;
1051
1052 fn get_proc_macro_quoted_span(&self, krate: CrateNum, id: usize) -> Span;
1055
1056 fn declare_proc_macro(&mut self, id: NodeId);
1063
1064 fn append_stripped_cfg_item(&mut self, parent_node: NodeId, name: Ident, cfg: ast::MetaItem);
1065
1066 fn registered_tools(&self) -> &RegisteredTools;
1068
1069 fn register_glob_delegation(&mut self, invoc_id: LocalExpnId);
1071
1072 fn glob_delegation_suffixes(
1074 &mut self,
1075 trait_def_id: DefId,
1076 impl_def_id: LocalDefId,
1077 ) -> Result<Vec<(Ident, Option<Ident>)>, Indeterminate>;
1078}
1079
1080pub trait LintStoreExpand {
1081 fn pre_expansion_lint(
1082 &self,
1083 sess: &Session,
1084 features: &Features,
1085 registered_tools: &RegisteredTools,
1086 node_id: NodeId,
1087 attrs: &[Attribute],
1088 items: &[P<Item>],
1089 name: Symbol,
1090 );
1091}
1092
1093type LintStoreExpandDyn<'a> = Option<&'a (dyn LintStoreExpand + 'a)>;
1094
1095#[derive(Debug, Clone, Default)]
1096pub struct ModuleData {
1097 pub mod_path: Vec<Ident>,
1099 pub file_path_stack: Vec<PathBuf>,
1102 pub dir_path: PathBuf,
1105}
1106
1107impl ModuleData {
1108 pub fn with_dir_path(&self, dir_path: PathBuf) -> ModuleData {
1109 ModuleData {
1110 mod_path: self.mod_path.clone(),
1111 file_path_stack: self.file_path_stack.clone(),
1112 dir_path,
1113 }
1114 }
1115}
1116
1117#[derive(Clone)]
1118pub struct ExpansionData {
1119 pub id: LocalExpnId,
1120 pub depth: usize,
1121 pub module: Rc<ModuleData>,
1122 pub dir_ownership: DirOwnership,
1123 pub lint_node_id: NodeId,
1125 pub is_trailing_mac: bool,
1126}
1127
1128pub struct ExtCtxt<'a> {
1132 pub sess: &'a Session,
1133 pub ecfg: expand::ExpansionConfig<'a>,
1134 pub num_standard_library_imports: usize,
1135 pub reduced_recursion_limit: Option<(Limit, ErrorGuaranteed)>,
1136 pub root_path: PathBuf,
1137 pub resolver: &'a mut dyn ResolverExpand,
1138 pub current_expansion: ExpansionData,
1139 pub force_mode: bool,
1142 pub expansions: FxIndexMap<Span, Vec<String>>,
1143 pub(super) lint_store: LintStoreExpandDyn<'a>,
1145 pub buffered_early_lint: Vec<BufferedEarlyLint>,
1147 pub(super) expanded_inert_attrs: MarkedAttrs,
1151}
1152
1153impl<'a> ExtCtxt<'a> {
1154 pub fn new(
1155 sess: &'a Session,
1156 ecfg: expand::ExpansionConfig<'a>,
1157 resolver: &'a mut dyn ResolverExpand,
1158 lint_store: LintStoreExpandDyn<'a>,
1159 ) -> ExtCtxt<'a> {
1160 ExtCtxt {
1161 sess,
1162 ecfg,
1163 num_standard_library_imports: 0,
1164 reduced_recursion_limit: None,
1165 resolver,
1166 lint_store,
1167 root_path: PathBuf::new(),
1168 current_expansion: ExpansionData {
1169 id: LocalExpnId::ROOT,
1170 depth: 0,
1171 module: Default::default(),
1172 dir_ownership: DirOwnership::Owned { relative: None },
1173 lint_node_id: ast::CRATE_NODE_ID,
1174 is_trailing_mac: false,
1175 },
1176 force_mode: false,
1177 expansions: FxIndexMap::default(),
1178 expanded_inert_attrs: MarkedAttrs::new(),
1179 buffered_early_lint: vec![],
1180 }
1181 }
1182
1183 pub fn dcx(&self) -> DiagCtxtHandle<'a> {
1184 self.sess.dcx()
1185 }
1186
1187 pub fn expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> {
1189 expand::MacroExpander::new(self, false)
1190 }
1191
1192 pub fn monotonic_expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> {
1195 expand::MacroExpander::new(self, true)
1196 }
1197 pub fn new_parser_from_tts(&self, stream: TokenStream) -> Parser<'a> {
1198 Parser::new(&self.sess.psess, stream, MACRO_ARGUMENTS)
1199 }
1200 pub fn source_map(&self) -> &'a SourceMap {
1201 self.sess.psess.source_map()
1202 }
1203 pub fn psess(&self) -> &'a ParseSess {
1204 &self.sess.psess
1205 }
1206 pub fn call_site(&self) -> Span {
1207 self.current_expansion.id.expn_data().call_site
1208 }
1209
1210 pub(crate) fn expansion_descr(&self) -> String {
1212 let expn_data = self.current_expansion.id.expn_data();
1213 expn_data.kind.descr()
1214 }
1215
1216 pub fn with_def_site_ctxt(&self, span: Span) -> Span {
1219 span.with_def_site_ctxt(self.current_expansion.id.to_expn_id())
1220 }
1221
1222 pub fn with_call_site_ctxt(&self, span: Span) -> Span {
1225 span.with_call_site_ctxt(self.current_expansion.id.to_expn_id())
1226 }
1227
1228 pub fn with_mixed_site_ctxt(&self, span: Span) -> Span {
1231 span.with_mixed_site_ctxt(self.current_expansion.id.to_expn_id())
1232 }
1233
1234 pub fn expansion_cause(&self) -> Option<Span> {
1238 self.current_expansion.id.expansion_cause()
1239 }
1240
1241 pub fn trace_macros_diag(&mut self) {
1242 for (span, notes) in self.expansions.iter() {
1243 let mut db = self.dcx().create_note(errors::TraceMacro { span: *span });
1244 for note in notes {
1245 #[allow(rustc::untranslatable_diagnostic)]
1247 db.note(note.clone());
1248 }
1249 db.emit();
1250 }
1251 self.expansions.clear();
1253 }
1254 pub fn trace_macros(&self) -> bool {
1255 self.ecfg.trace_mac
1256 }
1257 pub fn set_trace_macros(&mut self, x: bool) {
1258 self.ecfg.trace_mac = x
1259 }
1260 pub fn std_path(&self, components: &[Symbol]) -> Vec<Ident> {
1261 let def_site = self.with_def_site_ctxt(DUMMY_SP);
1262 iter::once(Ident::new(kw::DollarCrate, def_site))
1263 .chain(components.iter().map(|&s| Ident::with_dummy_span(s)))
1264 .collect()
1265 }
1266 pub fn def_site_path(&self, components: &[Symbol]) -> Vec<Ident> {
1267 let def_site = self.with_def_site_ctxt(DUMMY_SP);
1268 components.iter().map(|&s| Ident::new(s, def_site)).collect()
1269 }
1270
1271 pub fn check_unused_macros(&mut self) {
1272 self.resolver.check_unused_macros();
1273 }
1274}
1275
1276pub fn resolve_path(sess: &Session, path: impl Into<PathBuf>, span: Span) -> PResult<'_, PathBuf> {
1280 let path = path.into();
1281
1282 if !path.is_absolute() {
1285 let callsite = span.source_callsite();
1286 let source_map = sess.source_map();
1287 let Some(mut base_path) = source_map.span_to_filename(callsite).into_local_path() else {
1288 return Err(sess.dcx().create_err(errors::ResolveRelativePath {
1289 span,
1290 path: source_map
1291 .filename_for_diagnostics(&source_map.span_to_filename(callsite))
1292 .to_string(),
1293 }));
1294 };
1295 base_path.pop();
1296 base_path.push(path);
1297 Ok(base_path)
1298 } else {
1299 match path.components().next() {
1302 Some(Prefix(prefix)) if prefix.kind().is_verbatim() => Ok(path.components().collect()),
1303 _ => Ok(path),
1304 }
1305 }
1306}
1307
1308pub fn parse_macro_name_and_helper_attrs(
1309 dcx: DiagCtxtHandle<'_>,
1310 attr: &impl AttributeExt,
1311 macro_type: &str,
1312) -> Option<(Symbol, Vec<Symbol>)> {
1313 let list = attr.meta_item_list()?;
1317 let ([trait_attr] | [trait_attr, _]) = list.as_slice() else {
1318 dcx.emit_err(errors::AttrNoArguments { span: attr.span() });
1319 return None;
1320 };
1321 let Some(trait_attr) = trait_attr.meta_item() else {
1322 dcx.emit_err(errors::NotAMetaItem { span: trait_attr.span() });
1323 return None;
1324 };
1325 let trait_ident = match trait_attr.ident() {
1326 Some(trait_ident) if trait_attr.is_word() => trait_ident,
1327 _ => {
1328 dcx.emit_err(errors::OnlyOneWord { span: trait_attr.span });
1329 return None;
1330 }
1331 };
1332
1333 if !trait_ident.name.can_be_raw() {
1334 dcx.emit_err(errors::CannotBeNameOfMacro {
1335 span: trait_attr.span,
1336 trait_ident,
1337 macro_type,
1338 });
1339 }
1340
1341 let attributes_attr = list.get(1);
1342 let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
1343 if !attr.has_name(sym::attributes) {
1344 dcx.emit_err(errors::ArgumentNotAttributes { span: attr.span() });
1345 }
1346 attr.meta_item_list()
1347 .unwrap_or_else(|| {
1348 dcx.emit_err(errors::AttributesWrongForm { span: attr.span() });
1349 &[]
1350 })
1351 .iter()
1352 .filter_map(|attr| {
1353 let Some(attr) = attr.meta_item() else {
1354 dcx.emit_err(errors::AttributeMetaItem { span: attr.span() });
1355 return None;
1356 };
1357
1358 let ident = match attr.ident() {
1359 Some(ident) if attr.is_word() => ident,
1360 _ => {
1361 dcx.emit_err(errors::AttributeSingleWord { span: attr.span });
1362 return None;
1363 }
1364 };
1365 if !ident.name.can_be_raw() {
1366 dcx.emit_err(errors::HelperAttributeNameInvalid {
1367 span: attr.span,
1368 name: ident,
1369 });
1370 }
1371
1372 Some(ident.name)
1373 })
1374 .collect()
1375 } else {
1376 Vec::new()
1377 };
1378
1379 Some((trait_ident.name, proc_attrs))
1380}
1381
1382fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) {
1386 let name = item.ident.name;
1387 if name == sym::ProceduralMasqueradeDummyType
1388 && let ast::ItemKind::Enum(enum_def, _) = &item.kind
1389 && let [variant] = &*enum_def.variants
1390 && variant.ident.name == sym::Input
1391 && let FileName::Real(real) = sess.source_map().span_to_filename(item.ident.span)
1392 && let Some(c) = real
1393 .local_path()
1394 .unwrap_or(Path::new(""))
1395 .components()
1396 .flat_map(|c| c.as_os_str().to_str())
1397 .find(|c| c.starts_with("rental") || c.starts_with("allsorts-rental"))
1398 {
1399 let crate_matches = if c.starts_with("allsorts-rental") {
1400 true
1401 } else {
1402 let mut version = c.trim_start_matches("rental-").split('.');
1403 version.next() == Some("0")
1404 && version.next() == Some("5")
1405 && version.next().and_then(|c| c.parse::<u32>().ok()).is_some_and(|v| v < 6)
1406 };
1407
1408 if crate_matches {
1409 sess.dcx().emit_fatal(errors::ProcMacroBackCompat {
1410 crate_name: "rental".to_string(),
1411 fixed_version: "0.5.6".to_string(),
1412 });
1413 }
1414 }
1415}
1416
1417pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, sess: &Session) {
1418 let item = match ann {
1419 Annotatable::Item(item) => item,
1420 Annotatable::Stmt(stmt) => match &stmt.kind {
1421 ast::StmtKind::Item(item) => item,
1422 _ => return,
1423 },
1424 _ => return,
1425 };
1426 pretty_printing_compatibility_hack(item, sess)
1427}
1428
1429pub(crate) fn nt_pretty_printing_compatibility_hack(nt: &Nonterminal, sess: &Session) {
1430 let item = match nt {
1431 Nonterminal::NtItem(item) => item,
1432 Nonterminal::NtStmt(stmt) => match &stmt.kind {
1433 ast::StmtKind::Item(item) => item,
1434 _ => return,
1435 },
1436 _ => return,
1437 };
1438 pretty_printing_compatibility_hack(item, sess)
1439}