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