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
353pub type MacroExpanderResult<'cx> = ExpandResult<Box<dyn MacResult + 'cx>, ()>;
354
355pub type MacroExpanderFn =
356 for<'cx> fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> MacroExpanderResult<'cx>;
357
358impl<F> TTMacroExpander for F
359where
360 F: for<'cx> Fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> MacroExpanderResult<'cx>,
361{
362 fn expand<'cx>(
363 &self,
364 ecx: &'cx mut ExtCtxt<'_>,
365 span: Span,
366 input: TokenStream,
367 ) -> MacroExpanderResult<'cx> {
368 self(ecx, span, input)
369 }
370}
371
372pub trait GlobDelegationExpander {
373 fn expand(&self, ecx: &mut ExtCtxt<'_>) -> ExpandResult<Vec<(Ident, Option<Ident>)>, ()>;
374}
375
376macro_rules! make_stmts_default {
378 ($me:expr) => {
379 $me.make_expr().map(|e| {
380 smallvec![ast::Stmt {
381 id: ast::DUMMY_NODE_ID,
382 span: e.span,
383 kind: ast::StmtKind::Expr(e),
384 }]
385 })
386 };
387}
388
389pub trait MacResult {
392 fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
394 None
395 }
396
397 fn make_items(self: Box<Self>) -> Option<SmallVec<[P<ast::Item>; 1]>> {
399 None
400 }
401
402 fn make_impl_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
404 None
405 }
406
407 fn make_trait_impl_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
409 None
410 }
411
412 fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
414 None
415 }
416
417 fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[P<ast::ForeignItem>; 1]>> {
419 None
420 }
421
422 fn make_pat(self: Box<Self>) -> Option<P<ast::Pat>> {
424 None
425 }
426
427 fn make_stmts(self: Box<Self>) -> Option<SmallVec<[ast::Stmt; 1]>> {
432 make_stmts_default!(self)
433 }
434
435 fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
436 None
437 }
438
439 fn make_arms(self: Box<Self>) -> Option<SmallVec<[ast::Arm; 1]>> {
440 None
441 }
442
443 fn make_expr_fields(self: Box<Self>) -> Option<SmallVec<[ast::ExprField; 1]>> {
444 None
445 }
446
447 fn make_pat_fields(self: Box<Self>) -> Option<SmallVec<[ast::PatField; 1]>> {
448 None
449 }
450
451 fn make_generic_params(self: Box<Self>) -> Option<SmallVec<[ast::GenericParam; 1]>> {
452 None
453 }
454
455 fn make_params(self: Box<Self>) -> Option<SmallVec<[ast::Param; 1]>> {
456 None
457 }
458
459 fn make_field_defs(self: Box<Self>) -> Option<SmallVec<[ast::FieldDef; 1]>> {
460 None
461 }
462
463 fn make_variants(self: Box<Self>) -> Option<SmallVec<[ast::Variant; 1]>> {
464 None
465 }
466
467 fn make_where_predicates(self: Box<Self>) -> Option<SmallVec<[ast::WherePredicate; 1]>> {
468 None
469 }
470
471 fn make_crate(self: Box<Self>) -> Option<ast::Crate> {
472 unreachable!()
474 }
475}
476
477macro_rules! make_MacEager {
478 ( $( $fld:ident: $t:ty, )* ) => {
479 #[derive(Default)]
482 pub struct MacEager {
483 $(
484 pub $fld: Option<$t>,
485 )*
486 }
487
488 impl MacEager {
489 $(
490 pub fn $fld(v: $t) -> Box<dyn MacResult> {
491 Box::new(MacEager {
492 $fld: Some(v),
493 ..Default::default()
494 })
495 }
496 )*
497 }
498 }
499}
500
501make_MacEager! {
502 expr: P<ast::Expr>,
503 pat: P<ast::Pat>,
504 items: SmallVec<[P<ast::Item>; 1]>,
505 impl_items: SmallVec<[P<ast::AssocItem>; 1]>,
506 trait_items: SmallVec<[P<ast::AssocItem>; 1]>,
507 foreign_items: SmallVec<[P<ast::ForeignItem>; 1]>,
508 stmts: SmallVec<[ast::Stmt; 1]>,
509 ty: P<ast::Ty>,
510}
511
512impl MacResult for MacEager {
513 fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
514 self.expr
515 }
516
517 fn make_items(self: Box<Self>) -> Option<SmallVec<[P<ast::Item>; 1]>> {
518 self.items
519 }
520
521 fn make_impl_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
522 self.impl_items
523 }
524
525 fn make_trait_impl_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
526 self.impl_items
527 }
528
529 fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
530 self.trait_items
531 }
532
533 fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[P<ast::ForeignItem>; 1]>> {
534 self.foreign_items
535 }
536
537 fn make_stmts(self: Box<Self>) -> Option<SmallVec<[ast::Stmt; 1]>> {
538 match self.stmts.as_ref().map_or(0, |s| s.len()) {
539 0 => make_stmts_default!(self),
540 _ => self.stmts,
541 }
542 }
543
544 fn make_pat(self: Box<Self>) -> Option<P<ast::Pat>> {
545 if let Some(p) = self.pat {
546 return Some(p);
547 }
548 if let Some(e) = self.expr {
549 if matches!(e.kind, ast::ExprKind::Lit(_) | ast::ExprKind::IncludedBytes(_)) {
550 return Some(P(ast::Pat {
551 id: ast::DUMMY_NODE_ID,
552 span: e.span,
553 kind: PatKind::Expr(e),
554 tokens: None,
555 }));
556 }
557 }
558 None
559 }
560
561 fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
562 self.ty
563 }
564}
565
566#[derive(Copy, Clone)]
569pub struct DummyResult {
570 guar: Option<ErrorGuaranteed>,
571 span: Span,
572}
573
574impl DummyResult {
575 pub fn any(span: Span, guar: ErrorGuaranteed) -> Box<dyn MacResult + 'static> {
580 Box::new(DummyResult { guar: Some(guar), span })
581 }
582
583 pub fn any_valid(span: Span) -> Box<dyn MacResult + 'static> {
585 Box::new(DummyResult { guar: None, span })
586 }
587
588 pub fn raw_expr(sp: Span, guar: Option<ErrorGuaranteed>) -> P<ast::Expr> {
590 P(ast::Expr {
591 id: ast::DUMMY_NODE_ID,
592 kind: if let Some(guar) = guar {
593 ast::ExprKind::Err(guar)
594 } else {
595 ast::ExprKind::Tup(ThinVec::new())
596 },
597 span: sp,
598 attrs: ast::AttrVec::new(),
599 tokens: None,
600 })
601 }
602}
603
604impl MacResult for DummyResult {
605 fn make_expr(self: Box<DummyResult>) -> Option<P<ast::Expr>> {
606 Some(DummyResult::raw_expr(self.span, self.guar))
607 }
608
609 fn make_pat(self: Box<DummyResult>) -> Option<P<ast::Pat>> {
610 Some(P(ast::Pat {
611 id: ast::DUMMY_NODE_ID,
612 kind: PatKind::Wild,
613 span: self.span,
614 tokens: None,
615 }))
616 }
617
618 fn make_items(self: Box<DummyResult>) -> Option<SmallVec<[P<ast::Item>; 1]>> {
619 Some(SmallVec::new())
620 }
621
622 fn make_impl_items(self: Box<DummyResult>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
623 Some(SmallVec::new())
624 }
625
626 fn make_trait_impl_items(self: Box<DummyResult>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
627 Some(SmallVec::new())
628 }
629
630 fn make_trait_items(self: Box<DummyResult>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
631 Some(SmallVec::new())
632 }
633
634 fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[P<ast::ForeignItem>; 1]>> {
635 Some(SmallVec::new())
636 }
637
638 fn make_stmts(self: Box<DummyResult>) -> Option<SmallVec<[ast::Stmt; 1]>> {
639 Some(smallvec![ast::Stmt {
640 id: ast::DUMMY_NODE_ID,
641 kind: ast::StmtKind::Expr(DummyResult::raw_expr(self.span, self.guar)),
642 span: self.span,
643 }])
644 }
645
646 fn make_ty(self: Box<DummyResult>) -> Option<P<ast::Ty>> {
647 Some(P(ast::Ty {
651 id: ast::DUMMY_NODE_ID,
652 kind: ast::TyKind::Tup(ThinVec::new()),
653 span: self.span,
654 tokens: None,
655 }))
656 }
657
658 fn make_arms(self: Box<DummyResult>) -> Option<SmallVec<[ast::Arm; 1]>> {
659 Some(SmallVec::new())
660 }
661
662 fn make_expr_fields(self: Box<DummyResult>) -> Option<SmallVec<[ast::ExprField; 1]>> {
663 Some(SmallVec::new())
664 }
665
666 fn make_pat_fields(self: Box<DummyResult>) -> Option<SmallVec<[ast::PatField; 1]>> {
667 Some(SmallVec::new())
668 }
669
670 fn make_generic_params(self: Box<DummyResult>) -> Option<SmallVec<[ast::GenericParam; 1]>> {
671 Some(SmallVec::new())
672 }
673
674 fn make_params(self: Box<DummyResult>) -> Option<SmallVec<[ast::Param; 1]>> {
675 Some(SmallVec::new())
676 }
677
678 fn make_field_defs(self: Box<DummyResult>) -> Option<SmallVec<[ast::FieldDef; 1]>> {
679 Some(SmallVec::new())
680 }
681
682 fn make_variants(self: Box<DummyResult>) -> Option<SmallVec<[ast::Variant; 1]>> {
683 Some(SmallVec::new())
684 }
685
686 fn make_crate(self: Box<DummyResult>) -> Option<ast::Crate> {
687 Some(ast::Crate {
688 attrs: Default::default(),
689 items: Default::default(),
690 spans: Default::default(),
691 id: ast::DUMMY_NODE_ID,
692 is_placeholder: Default::default(),
693 })
694 }
695}
696
697#[derive(Clone)]
699pub enum SyntaxExtensionKind {
700 Bang(
702 Arc<dyn BangProcMacro + sync::DynSync + sync::DynSend>,
704 ),
705
706 LegacyBang(
708 Arc<dyn TTMacroExpander + sync::DynSync + sync::DynSend>,
710 ),
711
712 Attr(
714 Arc<dyn AttrProcMacro + sync::DynSync + sync::DynSend>,
718 ),
719
720 LegacyAttr(
722 Arc<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
726 ),
727
728 NonMacroAttr,
733
734 Derive(
736 Arc<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
744 ),
745
746 LegacyDerive(
748 Arc<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
751 ),
752
753 GlobDelegation(Arc<dyn GlobDelegationExpander + sync::DynSync + sync::DynSend>),
755}
756
757pub struct SyntaxExtension {
759 pub kind: SyntaxExtensionKind,
761 pub span: Span,
763 pub allow_internal_unstable: Option<Arc<[Symbol]>>,
765 pub stability: Option<Stability>,
767 pub deprecation: Option<Deprecation>,
769 pub helper_attrs: Vec<Symbol>,
771 pub edition: Edition,
773 pub builtin_name: Option<Symbol>,
776 pub allow_internal_unsafe: bool,
778 pub local_inner_macros: bool,
780 pub collapse_debuginfo: bool,
783}
784
785impl SyntaxExtension {
786 pub fn macro_kind(&self) -> MacroKind {
788 match self.kind {
789 SyntaxExtensionKind::Bang(..)
790 | SyntaxExtensionKind::LegacyBang(..)
791 | SyntaxExtensionKind::GlobDelegation(..) => MacroKind::Bang,
792 SyntaxExtensionKind::Attr(..)
793 | SyntaxExtensionKind::LegacyAttr(..)
794 | SyntaxExtensionKind::NonMacroAttr => MacroKind::Attr,
795 SyntaxExtensionKind::Derive(..) | SyntaxExtensionKind::LegacyDerive(..) => {
796 MacroKind::Derive
797 }
798 }
799 }
800
801 pub fn default(kind: SyntaxExtensionKind, edition: Edition) -> SyntaxExtension {
803 SyntaxExtension {
804 span: DUMMY_SP,
805 allow_internal_unstable: None,
806 stability: None,
807 deprecation: None,
808 helper_attrs: Vec::new(),
809 edition,
810 builtin_name: None,
811 kind,
812 allow_internal_unsafe: false,
813 local_inner_macros: false,
814 collapse_debuginfo: false,
815 }
816 }
817
818 fn collapse_debuginfo_by_name(
819 attr: &impl AttributeExt,
820 ) -> Result<CollapseMacroDebuginfo, Span> {
821 let list = attr.meta_item_list();
822 let Some([MetaItemInner::MetaItem(item)]) = list.as_deref() else {
823 return Err(attr.span());
824 };
825 if !item.is_word() {
826 return Err(item.span);
827 }
828
829 match item.name() {
830 Some(sym::no) => Ok(CollapseMacroDebuginfo::No),
831 Some(sym::external) => Ok(CollapseMacroDebuginfo::External),
832 Some(sym::yes) => Ok(CollapseMacroDebuginfo::Yes),
833 _ => Err(item.path.span),
834 }
835 }
836
837 fn get_collapse_debuginfo(sess: &Session, attrs: &[impl AttributeExt], ext: bool) -> bool {
844 let flag = sess.opts.cg.collapse_macro_debuginfo;
845 let attr = ast::attr::find_by_name(attrs, sym::collapse_debuginfo)
846 .and_then(|attr| {
847 Self::collapse_debuginfo_by_name(attr)
848 .map_err(|span| {
849 sess.dcx().emit_err(errors::CollapseMacroDebuginfoIllegal { span })
850 })
851 .ok()
852 })
853 .unwrap_or_else(|| {
854 if ast::attr::contains_name(attrs, sym::rustc_builtin_macro) {
855 CollapseMacroDebuginfo::Yes
856 } else {
857 CollapseMacroDebuginfo::Unspecified
858 }
859 });
860 #[rustfmt::skip]
861 let collapse_table = [
862 [false, false, false, false],
863 [false, ext, ext, true],
864 [false, ext, ext, true],
865 [true, true, true, true],
866 ];
867 collapse_table[flag as usize][attr as usize]
868 }
869
870 pub fn new(
873 sess: &Session,
874 kind: SyntaxExtensionKind,
875 span: Span,
876 helper_attrs: Vec<Symbol>,
877 edition: Edition,
878 name: Symbol,
879 attrs: &[hir::Attribute],
880 is_local: bool,
881 ) -> SyntaxExtension {
882 let allow_internal_unstable =
883 find_attr!(attrs, AttributeKind::AllowInternalUnstable(i) => i)
884 .map(|i| i.as_slice())
885 .unwrap_or_default();
886 let allow_internal_unsafe =
889 ast::attr::find_by_name(attrs, sym::allow_internal_unsafe).is_some();
890
891 let local_inner_macros = ast::attr::find_by_name(attrs, sym::macro_export)
892 .and_then(|macro_export| macro_export.meta_item_list())
893 .is_some_and(|l| ast::attr::list_contains_name(&l, sym::local_inner_macros));
894 let collapse_debuginfo = Self::get_collapse_debuginfo(sess, attrs, !is_local);
895 tracing::debug!(?name, ?local_inner_macros, ?collapse_debuginfo, ?allow_internal_unsafe);
896
897 let (builtin_name, helper_attrs) = ast::attr::find_by_name(attrs, sym::rustc_builtin_macro)
898 .map(|attr| {
899 parse_macro_name_and_helper_attrs(sess.dcx(), attr, "built-in").map_or_else(
902 || (Some(name), Vec::new()),
903 |(name, helper_attrs)| (Some(name), helper_attrs),
904 )
905 })
906 .unwrap_or_else(|| (None, helper_attrs));
907
908 let stability = find_attr!(attrs, AttributeKind::Stability { stability, .. } => *stability);
909
910 if let Some(sp) = find_attr!(attrs, AttributeKind::ConstStability { span, .. } => *span) {
912 sess.dcx().emit_err(errors::MacroConstStability {
913 span: sp,
914 head_span: sess.source_map().guess_head_span(span),
915 });
916 }
917 if let Some(sp) = find_attr!(attrs, AttributeKind::BodyStability{ span, .. } => *span) {
918 sess.dcx().emit_err(errors::MacroBodyStability {
919 span: sp,
920 head_span: sess.source_map().guess_head_span(span),
921 });
922 }
923
924 SyntaxExtension {
925 kind,
926 span,
927 allow_internal_unstable: (!allow_internal_unstable.is_empty())
928 .then(|| allow_internal_unstable.iter().map(|i| i.0).collect::<Vec<_>>().into()),
930 stability,
931 deprecation: find_attr!(
932 attrs,
933 AttributeKind::Deprecation { deprecation, .. } => *deprecation
934 ),
935 helper_attrs,
936 edition,
937 builtin_name,
938 allow_internal_unsafe,
939 local_inner_macros,
940 collapse_debuginfo,
941 }
942 }
943
944 pub fn dummy_bang(edition: Edition) -> SyntaxExtension {
946 fn expander<'cx>(
947 cx: &'cx mut ExtCtxt<'_>,
948 span: Span,
949 _: TokenStream,
950 ) -> MacroExpanderResult<'cx> {
951 ExpandResult::Ready(DummyResult::any(
952 span,
953 cx.dcx().span_delayed_bug(span, "expanded a dummy bang macro"),
954 ))
955 }
956 SyntaxExtension::default(SyntaxExtensionKind::LegacyBang(Arc::new(expander)), edition)
957 }
958
959 pub fn dummy_derive(edition: Edition) -> SyntaxExtension {
961 fn expander(
962 _: &mut ExtCtxt<'_>,
963 _: Span,
964 _: &ast::MetaItem,
965 _: Annotatable,
966 ) -> Vec<Annotatable> {
967 Vec::new()
968 }
969 SyntaxExtension::default(SyntaxExtensionKind::Derive(Arc::new(expander)), edition)
970 }
971
972 pub fn non_macro_attr(edition: Edition) -> SyntaxExtension {
973 SyntaxExtension::default(SyntaxExtensionKind::NonMacroAttr, edition)
974 }
975
976 pub fn glob_delegation(
977 trait_def_id: DefId,
978 impl_def_id: LocalDefId,
979 edition: Edition,
980 ) -> SyntaxExtension {
981 struct GlobDelegationExpanderImpl {
982 trait_def_id: DefId,
983 impl_def_id: LocalDefId,
984 }
985 impl GlobDelegationExpander for GlobDelegationExpanderImpl {
986 fn expand(
987 &self,
988 ecx: &mut ExtCtxt<'_>,
989 ) -> ExpandResult<Vec<(Ident, Option<Ident>)>, ()> {
990 match ecx.resolver.glob_delegation_suffixes(self.trait_def_id, self.impl_def_id) {
991 Ok(suffixes) => ExpandResult::Ready(suffixes),
992 Err(Indeterminate) if ecx.force_mode => ExpandResult::Ready(Vec::new()),
993 Err(Indeterminate) => ExpandResult::Retry(()),
994 }
995 }
996 }
997
998 let expander = GlobDelegationExpanderImpl { trait_def_id, impl_def_id };
999 SyntaxExtension::default(SyntaxExtensionKind::GlobDelegation(Arc::new(expander)), edition)
1000 }
1001
1002 pub fn expn_data(
1003 &self,
1004 parent: LocalExpnId,
1005 call_site: Span,
1006 descr: Symbol,
1007 macro_def_id: Option<DefId>,
1008 parent_module: Option<DefId>,
1009 ) -> ExpnData {
1010 ExpnData::new(
1011 ExpnKind::Macro(self.macro_kind(), descr),
1012 parent.to_expn_id(),
1013 call_site,
1014 self.span,
1015 self.allow_internal_unstable.clone(),
1016 self.edition,
1017 macro_def_id,
1018 parent_module,
1019 self.allow_internal_unsafe,
1020 self.local_inner_macros,
1021 self.collapse_debuginfo,
1022 self.builtin_name.is_some(),
1023 )
1024 }
1025}
1026
1027pub struct Indeterminate;
1029
1030pub struct DeriveResolution {
1031 pub path: ast::Path,
1032 pub item: Annotatable,
1033 pub exts: Option<Arc<SyntaxExtension>>,
1034 pub is_const: bool,
1035}
1036
1037pub trait ResolverExpand {
1038 fn next_node_id(&mut self) -> NodeId;
1039 fn invocation_parent(&self, id: LocalExpnId) -> LocalDefId;
1040
1041 fn resolve_dollar_crates(&mut self);
1042 fn visit_ast_fragment_with_placeholders(
1043 &mut self,
1044 expn_id: LocalExpnId,
1045 fragment: &AstFragment,
1046 );
1047 fn register_builtin_macro(&mut self, name: Symbol, ext: SyntaxExtensionKind);
1048
1049 fn expansion_for_ast_pass(
1050 &mut self,
1051 call_site: Span,
1052 pass: AstPass,
1053 features: &[Symbol],
1054 parent_module_id: Option<NodeId>,
1055 ) -> LocalExpnId;
1056
1057 fn resolve_imports(&mut self);
1058
1059 fn resolve_macro_invocation(
1060 &mut self,
1061 invoc: &Invocation,
1062 eager_expansion_root: LocalExpnId,
1063 force: bool,
1064 ) -> Result<Arc<SyntaxExtension>, Indeterminate>;
1065
1066 fn record_macro_rule_usage(&mut self, mac_id: NodeId, rule_index: usize);
1067
1068 fn check_unused_macros(&mut self);
1069
1070 fn has_derive_copy(&self, expn_id: LocalExpnId) -> bool;
1073 fn resolve_derives(
1075 &mut self,
1076 expn_id: LocalExpnId,
1077 force: bool,
1078 derive_paths: &dyn Fn() -> Vec<DeriveResolution>,
1079 ) -> Result<(), Indeterminate>;
1080 fn take_derive_resolutions(&mut self, expn_id: LocalExpnId) -> Option<Vec<DeriveResolution>>;
1083 fn cfg_accessible(
1085 &mut self,
1086 expn_id: LocalExpnId,
1087 path: &ast::Path,
1088 ) -> Result<bool, Indeterminate>;
1089 fn macro_accessible(
1090 &mut self,
1091 expn_id: LocalExpnId,
1092 path: &ast::Path,
1093 ) -> Result<bool, Indeterminate>;
1094
1095 fn get_proc_macro_quoted_span(&self, krate: CrateNum, id: usize) -> Span;
1098
1099 fn declare_proc_macro(&mut self, id: NodeId);
1106
1107 fn append_stripped_cfg_item(&mut self, parent_node: NodeId, ident: Ident, cfg: ast::MetaItem);
1108
1109 fn registered_tools(&self) -> &RegisteredTools;
1111
1112 fn register_glob_delegation(&mut self, invoc_id: LocalExpnId);
1114
1115 fn glob_delegation_suffixes(
1117 &mut self,
1118 trait_def_id: DefId,
1119 impl_def_id: LocalDefId,
1120 ) -> Result<Vec<(Ident, Option<Ident>)>, Indeterminate>;
1121
1122 fn insert_impl_trait_name(&mut self, id: NodeId, name: Symbol);
1125}
1126
1127pub trait LintStoreExpand {
1128 fn pre_expansion_lint(
1129 &self,
1130 sess: &Session,
1131 features: &Features,
1132 registered_tools: &RegisteredTools,
1133 node_id: NodeId,
1134 attrs: &[Attribute],
1135 items: &[P<Item>],
1136 name: Symbol,
1137 );
1138}
1139
1140type LintStoreExpandDyn<'a> = Option<&'a (dyn LintStoreExpand + 'a)>;
1141
1142#[derive(Debug, Clone, Default)]
1143pub struct ModuleData {
1144 pub mod_path: Vec<Ident>,
1146 pub file_path_stack: Vec<PathBuf>,
1149 pub dir_path: PathBuf,
1152}
1153
1154impl ModuleData {
1155 pub fn with_dir_path(&self, dir_path: PathBuf) -> ModuleData {
1156 ModuleData {
1157 mod_path: self.mod_path.clone(),
1158 file_path_stack: self.file_path_stack.clone(),
1159 dir_path,
1160 }
1161 }
1162}
1163
1164#[derive(Clone)]
1165pub struct ExpansionData {
1166 pub id: LocalExpnId,
1167 pub depth: usize,
1168 pub module: Rc<ModuleData>,
1169 pub dir_ownership: DirOwnership,
1170 pub lint_node_id: NodeId,
1172 pub is_trailing_mac: bool,
1173}
1174
1175pub struct ExtCtxt<'a> {
1179 pub sess: &'a Session,
1180 pub ecfg: expand::ExpansionConfig<'a>,
1181 pub num_standard_library_imports: usize,
1182 pub reduced_recursion_limit: Option<(Limit, ErrorGuaranteed)>,
1183 pub root_path: PathBuf,
1184 pub resolver: &'a mut dyn ResolverExpand,
1185 pub current_expansion: ExpansionData,
1186 pub force_mode: bool,
1189 pub expansions: FxIndexMap<Span, Vec<String>>,
1190 pub(super) lint_store: LintStoreExpandDyn<'a>,
1192 pub buffered_early_lint: Vec<BufferedEarlyLint>,
1194 pub(super) expanded_inert_attrs: MarkedAttrs,
1198 pub macro_stats: FxHashMap<(Symbol, MacroKind), MacroStat>,
1200}
1201
1202impl<'a> ExtCtxt<'a> {
1203 pub fn new(
1204 sess: &'a Session,
1205 ecfg: expand::ExpansionConfig<'a>,
1206 resolver: &'a mut dyn ResolverExpand,
1207 lint_store: LintStoreExpandDyn<'a>,
1208 ) -> ExtCtxt<'a> {
1209 ExtCtxt {
1210 sess,
1211 ecfg,
1212 num_standard_library_imports: 0,
1213 reduced_recursion_limit: None,
1214 resolver,
1215 lint_store,
1216 root_path: PathBuf::new(),
1217 current_expansion: ExpansionData {
1218 id: LocalExpnId::ROOT,
1219 depth: 0,
1220 module: Default::default(),
1221 dir_ownership: DirOwnership::Owned { relative: None },
1222 lint_node_id: ast::CRATE_NODE_ID,
1223 is_trailing_mac: false,
1224 },
1225 force_mode: false,
1226 expansions: FxIndexMap::default(),
1227 expanded_inert_attrs: MarkedAttrs::new(),
1228 buffered_early_lint: vec![],
1229 macro_stats: Default::default(),
1230 }
1231 }
1232
1233 pub fn dcx(&self) -> DiagCtxtHandle<'a> {
1234 self.sess.dcx()
1235 }
1236
1237 pub fn expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> {
1239 expand::MacroExpander::new(self, false)
1240 }
1241
1242 pub fn monotonic_expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> {
1245 expand::MacroExpander::new(self, true)
1246 }
1247 pub fn new_parser_from_tts(&self, stream: TokenStream) -> Parser<'a> {
1248 Parser::new(&self.sess.psess, stream, MACRO_ARGUMENTS)
1249 }
1250 pub fn source_map(&self) -> &'a SourceMap {
1251 self.sess.psess.source_map()
1252 }
1253 pub fn psess(&self) -> &'a ParseSess {
1254 &self.sess.psess
1255 }
1256 pub fn call_site(&self) -> Span {
1257 self.current_expansion.id.expn_data().call_site
1258 }
1259
1260 pub(crate) fn expansion_descr(&self) -> String {
1262 let expn_data = self.current_expansion.id.expn_data();
1263 expn_data.kind.descr()
1264 }
1265
1266 pub fn with_def_site_ctxt(&self, span: Span) -> Span {
1269 span.with_def_site_ctxt(self.current_expansion.id.to_expn_id())
1270 }
1271
1272 pub fn with_call_site_ctxt(&self, span: Span) -> Span {
1275 span.with_call_site_ctxt(self.current_expansion.id.to_expn_id())
1276 }
1277
1278 pub fn with_mixed_site_ctxt(&self, span: Span) -> Span {
1281 span.with_mixed_site_ctxt(self.current_expansion.id.to_expn_id())
1282 }
1283
1284 pub fn expansion_cause(&self) -> Option<Span> {
1288 self.current_expansion.id.expansion_cause()
1289 }
1290
1291 pub fn trace_macros_diag(&mut self) {
1292 for (span, notes) in self.expansions.iter() {
1293 let mut db = self.dcx().create_note(errors::TraceMacro { span: *span });
1294 for note in notes {
1295 #[allow(rustc::untranslatable_diagnostic)]
1297 db.note(note.clone());
1298 }
1299 db.emit();
1300 }
1301 self.expansions.clear();
1303 }
1304 pub fn trace_macros(&self) -> bool {
1305 self.ecfg.trace_mac
1306 }
1307 pub fn set_trace_macros(&mut self, x: bool) {
1308 self.ecfg.trace_mac = x
1309 }
1310 pub fn std_path(&self, components: &[Symbol]) -> Vec<Ident> {
1311 let def_site = self.with_def_site_ctxt(DUMMY_SP);
1312 iter::once(Ident::new(kw::DollarCrate, def_site))
1313 .chain(components.iter().map(|&s| Ident::with_dummy_span(s)))
1314 .collect()
1315 }
1316 pub fn def_site_path(&self, components: &[Symbol]) -> Vec<Ident> {
1317 let def_site = self.with_def_site_ctxt(DUMMY_SP);
1318 components.iter().map(|&s| Ident::new(s, def_site)).collect()
1319 }
1320
1321 pub fn check_unused_macros(&mut self) {
1322 self.resolver.check_unused_macros();
1323 }
1324}
1325
1326pub fn resolve_path(sess: &Session, path: impl Into<PathBuf>, span: Span) -> PResult<'_, PathBuf> {
1330 let path = path.into();
1331
1332 if !path.is_absolute() {
1335 let callsite = span.source_callsite();
1336 let source_map = sess.source_map();
1337 let Some(mut base_path) = source_map.span_to_filename(callsite).into_local_path() else {
1338 return Err(sess.dcx().create_err(errors::ResolveRelativePath {
1339 span,
1340 path: source_map
1341 .filename_for_diagnostics(&source_map.span_to_filename(callsite))
1342 .to_string(),
1343 }));
1344 };
1345 base_path.pop();
1346 base_path.push(path);
1347 Ok(base_path)
1348 } else {
1349 match path.components().next() {
1352 Some(Prefix(prefix)) if prefix.kind().is_verbatim() => Ok(path.components().collect()),
1353 _ => Ok(path),
1354 }
1355 }
1356}
1357
1358pub fn parse_macro_name_and_helper_attrs(
1359 dcx: DiagCtxtHandle<'_>,
1360 attr: &impl AttributeExt,
1361 macro_type: &str,
1362) -> Option<(Symbol, Vec<Symbol>)> {
1363 let list = attr.meta_item_list()?;
1367 let ([trait_attr] | [trait_attr, _]) = list.as_slice() else {
1368 dcx.emit_err(errors::AttrNoArguments { span: attr.span() });
1369 return None;
1370 };
1371 let Some(trait_attr) = trait_attr.meta_item() else {
1372 dcx.emit_err(errors::NotAMetaItem { span: trait_attr.span() });
1373 return None;
1374 };
1375 let trait_ident = match trait_attr.ident() {
1376 Some(trait_ident) if trait_attr.is_word() => trait_ident,
1377 _ => {
1378 dcx.emit_err(errors::OnlyOneWord { span: trait_attr.span });
1379 return None;
1380 }
1381 };
1382
1383 if !trait_ident.name.can_be_raw() {
1384 dcx.emit_err(errors::CannotBeNameOfMacro {
1385 span: trait_attr.span,
1386 trait_ident,
1387 macro_type,
1388 });
1389 }
1390
1391 let attributes_attr = list.get(1);
1392 let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
1393 if !attr.has_name(sym::attributes) {
1394 dcx.emit_err(errors::ArgumentNotAttributes { span: attr.span() });
1395 }
1396 attr.meta_item_list()
1397 .unwrap_or_else(|| {
1398 dcx.emit_err(errors::AttributesWrongForm { span: attr.span() });
1399 &[]
1400 })
1401 .iter()
1402 .filter_map(|attr| {
1403 let Some(attr) = attr.meta_item() else {
1404 dcx.emit_err(errors::AttributeMetaItem { span: attr.span() });
1405 return None;
1406 };
1407
1408 let ident = match attr.ident() {
1409 Some(ident) if attr.is_word() => ident,
1410 _ => {
1411 dcx.emit_err(errors::AttributeSingleWord { span: attr.span });
1412 return None;
1413 }
1414 };
1415 if !ident.name.can_be_raw() {
1416 dcx.emit_err(errors::HelperAttributeNameInvalid {
1417 span: attr.span,
1418 name: ident,
1419 });
1420 }
1421
1422 Some(ident.name)
1423 })
1424 .collect()
1425 } else {
1426 Vec::new()
1427 };
1428
1429 Some((trait_ident.name, proc_attrs))
1430}
1431
1432fn pretty_printing_compatibility_hack(item: &Item, psess: &ParseSess) {
1436 if let ast::ItemKind::Enum(ident, _, enum_def) = &item.kind
1437 && ident.name == sym::ProceduralMasqueradeDummyType
1438 && let [variant] = &*enum_def.variants
1439 && variant.ident.name == sym::Input
1440 && let FileName::Real(real) = psess.source_map().span_to_filename(ident.span)
1441 && let Some(c) = real
1442 .local_path()
1443 .unwrap_or(Path::new(""))
1444 .components()
1445 .flat_map(|c| c.as_os_str().to_str())
1446 .find(|c| c.starts_with("rental") || c.starts_with("allsorts-rental"))
1447 {
1448 let crate_matches = if c.starts_with("allsorts-rental") {
1449 true
1450 } else {
1451 let mut version = c.trim_start_matches("rental-").split('.');
1452 version.next() == Some("0")
1453 && version.next() == Some("5")
1454 && version.next().and_then(|c| c.parse::<u32>().ok()).is_some_and(|v| v < 6)
1455 };
1456
1457 if crate_matches {
1458 psess.dcx().emit_fatal(errors::ProcMacroBackCompat {
1459 crate_name: "rental".to_string(),
1460 fixed_version: "0.5.6".to_string(),
1461 });
1462 }
1463 }
1464}
1465
1466pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, psess: &ParseSess) {
1467 let item = match ann {
1468 Annotatable::Item(item) => item,
1469 Annotatable::Stmt(stmt) => match &stmt.kind {
1470 ast::StmtKind::Item(item) => item,
1471 _ => return,
1472 },
1473 _ => return,
1474 };
1475 pretty_printing_compatibility_hack(item, psess)
1476}
1477
1478pub(crate) fn stream_pretty_printing_compatibility_hack(
1479 kind: MetaVarKind,
1480 stream: &TokenStream,
1481 psess: &ParseSess,
1482) {
1483 let item = match kind {
1484 MetaVarKind::Item => {
1485 let mut parser = Parser::new(psess, stream.clone(), None);
1486 parser
1488 .parse_item(ForceCollect::No)
1489 .expect("failed to reparse item")
1490 .expect("an actual item")
1491 }
1492 MetaVarKind::Stmt => {
1493 let mut parser = Parser::new(psess, stream.clone(), None);
1494 let stmt = parser
1496 .parse_stmt(ForceCollect::No)
1497 .expect("failed to reparse")
1498 .expect("an actual stmt");
1499 match &stmt.kind {
1500 ast::StmtKind::Item(item) => item.clone(),
1501 _ => return,
1502 }
1503 }
1504 _ => return,
1505 };
1506 pretty_printing_compatibility_hack(&item, psess)
1507}