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