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