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