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