compiler/rustc_expand/src/expand.rs RUST 2,647 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 2,647.
1use std::path::PathBuf;2use std::rc::Rc;3use std::sync::Arc;4use std::{iter, mem, slice};56use rustc_ast::mut_visit::*;7use rustc_ast::tokenstream::TokenStream;8use rustc_ast::visit::{self, AssocCtxt, Visitor, VisitorResult, try_visit, walk_list};9use rustc_ast::{10    self as ast, AssocItemKind, AstNodeWrapper, AttrArgs, AttrItemKind, AttrStyle, AttrVec,11    DUMMY_NODE_ID, DelegationSuffixes, EarlyParsedAttribute, ExprKind, ForeignItemKind, HasAttrs,12    HasNodeId, Inline, ItemKind, MacStmtStyle, MetaItemInner, MetaItemKind, ModKind, NodeId,13    PatKind, StmtKind, TyKind, token,14};15use rustc_ast_pretty::pprust;16use rustc_attr_parsing::parser::AllowExprMetavar;17use rustc_attr_parsing::{18    AttributeParser, AttributeSafety, CFG_TEMPLATE, EvalConfigResult, ShouldEmit,19    eval_config_entry, parse_cfg, validate_attr,20};21use rustc_data_structures::flat_map_in_place::FlatMapInPlace;22use rustc_data_structures::stack::ensure_sufficient_stack;23use rustc_errors::{PResult, msg};24use rustc_feature::Features;25use rustc_hir::Target;26use rustc_hir::def::MacroKinds;27use rustc_hir::limit::Limit;28use rustc_parse::parser::{29    AllowConstBlockItems, AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser,30    RecoverColon, RecoverComma, Recovery, token_descr,31};32use rustc_session::Session;33use rustc_session::errors::feature_err;34use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS};35use rustc_span::hygiene::SyntaxContext;36use rustc_span::{ErrorGuaranteed, FileName, Ident, LocalExpnId, Span, Symbol, sym};37use smallvec::SmallVec;3839use crate::base::*;40use crate::config::{StripUnconfigured, attr_into_trace};41use crate::errors::{42    EmptyDelegationMac, GlobDelegationOutsideImpls, GlobDelegationTraitlessQpath, IncompleteParse,43    RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue,44    WrongFragmentKind,45};46use crate::mbe::diagnostics::annotate_err_with_kind;47use crate::module::{48    DirOwnership, ParsedExternalMod, mod_dir_path, mod_file_path_from_attr, parse_external_mod,49};50use crate::placeholders::{PlaceholderExpander, placeholder};51use crate::stats::*;5253macro_rules! ast_fragments {54    (55        $($Kind:ident($AstTy:ty) {56            $kind_name:expr;57            $(one58                fn $visit_ast:ident;59            )?60            $(many61                fn $flat_map_ast_elt:ident;62                fn $visit_ast_elt:ident($($args:tt)*);63            )?64            fn $make_ast:ident;65        })*66    ) => {67        /// A fragment of AST that can be produced by a single macro expansion.68        /// Can also serve as an input and intermediate result for macro expansion operations.69        pub enum AstFragment {70            OptExpr(Option<Box<ast::Expr>>),71            MethodReceiverExpr(Box<ast::Expr>),72            $($Kind($AstTy),)*73        }7475        /// "Discriminant" of an AST fragment.76        #[derive(Copy, Clone, Debug, PartialEq, Eq)]77        pub enum AstFragmentKind {78            OptExpr,79            MethodReceiverExpr,80            $($Kind,)*81        }8283        impl AstFragmentKind {84            pub fn name(self) -> &'static str {85                match self {86                    AstFragmentKind::OptExpr => "expression",87                    AstFragmentKind::MethodReceiverExpr => "expression",88                    $(AstFragmentKind::$Kind => $kind_name,)*89                }90            }9192            fn make_from(self, result: Box<dyn MacResult + '_>) -> Option<AstFragment> {93                match self {94                    AstFragmentKind::OptExpr =>95                        result.make_expr().map(Some).map(AstFragment::OptExpr),96                    AstFragmentKind::MethodReceiverExpr =>97                        result.make_expr().map(AstFragment::MethodReceiverExpr),98                    $(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)*99                }100            }101        }102103        impl AstFragment {104            fn add_placeholders(&mut self, placeholders: &[NodeId]) {105                if placeholders.is_empty() {106                    return;107                }108                match self {109                    $($(AstFragment::$Kind(ast) => ast.extend(placeholders.iter().flat_map(|id| {110                        ${ignore($flat_map_ast_elt)}111                        placeholder(AstFragmentKind::$Kind, *id, None).$make_ast()112                    })),)?)*113                    _ => panic!("unexpected AST fragment kind")114                }115            }116117            pub(crate) fn make_opt_expr(self) -> Option<Box<ast::Expr>> {118                match self {119                    AstFragment::OptExpr(expr) => expr,120                    _ => panic!("AstFragment::make_opt_expr called on the wrong kind of fragment"),121                }122            }123124            pub(crate) fn make_method_receiver_expr(self) -> Box<ast::Expr> {125                match self {126                    AstFragment::MethodReceiverExpr(expr) => expr,127                    _ => panic!("AstFragment::make_method_receiver_expr called on the wrong kind of fragment"),128                }129            }130131            $(pub fn $make_ast(self) -> $AstTy {132                match self {133                    AstFragment::$Kind(ast) => ast,134                    _ => panic!("AstFragment::{} called on the wrong kind of fragment", stringify!($make_ast)),135                }136            })*137138            fn make_ast<T: InvocationCollectorNode>(self) -> T::OutputTy {139                T::fragment_to_output(self)140            }141142            pub(crate) fn mut_visit_with(&mut self, vis: &mut impl MutVisitor) {143                match self {144                    AstFragment::OptExpr(opt_expr) => {145                        if let Some(expr) = opt_expr.take() {146                            *opt_expr = vis.filter_map_expr(expr)147                        }148                    }149                    AstFragment::MethodReceiverExpr(expr) => vis.visit_method_receiver_expr(expr),150                    $($(AstFragment::$Kind(ast) => vis.$visit_ast(ast),)?)*151                    $($(AstFragment::$Kind(ast) =>152                        ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast, $($args)*)),)?)*153                }154            }155156            pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) -> V::Result {157                match self {158                    AstFragment::OptExpr(Some(expr)) => try_visit!(visitor.visit_expr(expr)),159                    AstFragment::OptExpr(None) => {}160                    AstFragment::MethodReceiverExpr(expr) => try_visit!(visitor.visit_method_receiver_expr(expr)),161                    $($(AstFragment::$Kind(ast) => try_visit!(visitor.$visit_ast(ast)),)?)*162                    $($(AstFragment::$Kind(ast) => walk_list!(visitor, $visit_ast_elt, &ast[..], $($args)*),)?)*163                }164                V::Result::output()165            }166        }167168        impl<'a, 'b> MacResult for crate::mbe::macro_rules::ParserAnyMacro<'a, 'b> {169            $(fn $make_ast(self: Box<crate::mbe::macro_rules::ParserAnyMacro<'a, 'b>>)170                           -> Option<$AstTy> {171                Some(self.make(AstFragmentKind::$Kind).$make_ast())172            })*173        }174    }175}176177ast_fragments! {178    Expr(Box<ast::Expr>) {179        "expression";180        one fn visit_expr;181        fn make_expr;182    }183    Pat(Box<ast::Pat>) {184        "pattern";185        one fn visit_pat;186        fn make_pat;187    }188    Ty(Box<ast::Ty>) {189        "type";190        one fn visit_ty;191        fn make_ty;192    }193    Stmts(SmallVec<[ast::Stmt; 1]>) {194        "statement";195        many fn flat_map_stmt; fn visit_stmt();196        fn make_stmts;197    }198    Items(SmallVec<[Box<ast::Item>; 1]>) {199        "item";200        many fn flat_map_item; fn visit_item();201        fn make_items;202    }203    TraitItems(SmallVec<[Box<ast::AssocItem>; 1]>) {204        "trait item";205        many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Trait);206        fn make_trait_items;207    }208    ImplItems(SmallVec<[Box<ast::AssocItem>; 1]>) {209        "impl item";210        many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Impl { of_trait: false });211        fn make_impl_items;212    }213    TraitImplItems(SmallVec<[Box<ast::AssocItem>; 1]>) {214        "impl item";215        many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Impl { of_trait: true });216        fn make_trait_impl_items;217    }218    ForeignItems(SmallVec<[Box<ast::ForeignItem>; 1]>) {219        "foreign item";220        many fn flat_map_foreign_item; fn visit_foreign_item();221        fn make_foreign_items;222    }223    Arms(SmallVec<[ast::Arm; 1]>) {224        "match arm";225        many fn flat_map_arm; fn visit_arm();226        fn make_arms;227    }228    ExprFields(SmallVec<[ast::ExprField; 1]>) {229        "field expression";230        many fn flat_map_expr_field; fn visit_expr_field();231        fn make_expr_fields;232    }233    PatFields(SmallVec<[ast::PatField; 1]>) {234        "field pattern";235        many fn flat_map_pat_field; fn visit_pat_field();236        fn make_pat_fields;237    }238    GenericParams(SmallVec<[ast::GenericParam; 1]>) {239        "generic parameter";240        many fn flat_map_generic_param; fn visit_generic_param();241        fn make_generic_params;242    }243    Params(SmallVec<[ast::Param; 1]>) {244        "function parameter";245        many fn flat_map_param; fn visit_param();246        fn make_params;247    }248    FieldDefs(SmallVec<[ast::FieldDef; 1]>) {249        "field";250        many fn flat_map_field_def; fn visit_field_def();251        fn make_field_defs;252    }253    Variants(SmallVec<[ast::Variant; 1]>) {254        "variant";255        many fn flat_map_variant; fn visit_variant();256        fn make_variants;257    }258    WherePredicates(SmallVec<[ast::WherePredicate; 1]>) {259        "where predicate";260        many fn flat_map_where_predicate; fn visit_where_predicate();261        fn make_where_predicates;262    }263    Crate(ast::Crate) {264        "crate";265        one fn visit_crate;266        fn make_crate;267    }268}269270pub enum SupportsMacroExpansion {271    No,272    Yes { supports_inner_attrs: bool },273}274275impl AstFragmentKind {276    pub(crate) fn dummy(self, span: Span, guar: ErrorGuaranteed) -> AstFragment {277        self.make_from(DummyResult::any(span, guar)).expect("couldn't create a dummy AST fragment")278    }279280    pub fn supports_macro_expansion(self) -> SupportsMacroExpansion {281        match self {282            AstFragmentKind::OptExpr283            | AstFragmentKind::Expr284            | AstFragmentKind::MethodReceiverExpr285            | AstFragmentKind::Stmts286            | AstFragmentKind::Ty287            | AstFragmentKind::Pat => SupportsMacroExpansion::Yes { supports_inner_attrs: false },288            AstFragmentKind::Items289            | AstFragmentKind::TraitItems290            | AstFragmentKind::ImplItems291            | AstFragmentKind::TraitImplItems292            | AstFragmentKind::ForeignItems293            | AstFragmentKind::Crate => SupportsMacroExpansion::Yes { supports_inner_attrs: true },294            AstFragmentKind::Arms295            | AstFragmentKind::ExprFields296            | AstFragmentKind::PatFields297            | AstFragmentKind::GenericParams298            | AstFragmentKind::Params299            | AstFragmentKind::FieldDefs300            | AstFragmentKind::Variants301            | AstFragmentKind::WherePredicates => SupportsMacroExpansion::No,302        }303    }304305    pub(crate) fn expect_from_annotatables(306        self,307        items: impl IntoIterator<Item = Annotatable>,308    ) -> AstFragment {309        let mut items = items.into_iter();310        match self {311            AstFragmentKind::Arms => {312                AstFragment::Arms(items.map(Annotatable::expect_arm).collect())313            }314            AstFragmentKind::ExprFields => {315                AstFragment::ExprFields(items.map(Annotatable::expect_expr_field).collect())316            }317            AstFragmentKind::PatFields => {318                AstFragment::PatFields(items.map(Annotatable::expect_pat_field).collect())319            }320            AstFragmentKind::GenericParams => {321                AstFragment::GenericParams(items.map(Annotatable::expect_generic_param).collect())322            }323            AstFragmentKind::Params => {324                AstFragment::Params(items.map(Annotatable::expect_param).collect())325            }326            AstFragmentKind::FieldDefs => {327                AstFragment::FieldDefs(items.map(Annotatable::expect_field_def).collect())328            }329            AstFragmentKind::Variants => {330                AstFragment::Variants(items.map(Annotatable::expect_variant).collect())331            }332            AstFragmentKind::WherePredicates => AstFragment::WherePredicates(333                items.map(Annotatable::expect_where_predicate).collect(),334            ),335            AstFragmentKind::Items => {336                AstFragment::Items(items.map(Annotatable::expect_item).collect())337            }338            AstFragmentKind::ImplItems => {339                AstFragment::ImplItems(items.map(Annotatable::expect_impl_item).collect())340            }341            AstFragmentKind::TraitImplItems => {342                AstFragment::TraitImplItems(items.map(Annotatable::expect_impl_item).collect())343            }344            AstFragmentKind::TraitItems => {345                AstFragment::TraitItems(items.map(Annotatable::expect_trait_item).collect())346            }347            AstFragmentKind::ForeignItems => {348                AstFragment::ForeignItems(items.map(Annotatable::expect_foreign_item).collect())349            }350            AstFragmentKind::Stmts => {351                AstFragment::Stmts(items.map(Annotatable::expect_stmt).collect())352            }353            AstFragmentKind::Expr => AstFragment::Expr(354                items.next().expect("expected exactly one expression").expect_expr(),355            ),356            AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(357                items.next().expect("expected exactly one expression").expect_expr(),358            ),359            AstFragmentKind::OptExpr => {360                AstFragment::OptExpr(items.next().map(Annotatable::expect_expr))361            }362            AstFragmentKind::Crate => {363                AstFragment::Crate(items.next().expect("expected exactly one crate").expect_crate())364            }365            AstFragmentKind::Pat | AstFragmentKind::Ty => {366                panic!("patterns and types aren't annotatable")367            }368        }369    }370}371372pub struct Invocation {373    pub kind: InvocationKind,374    pub fragment_kind: AstFragmentKind,375    pub expansion_data: ExpansionData,376}377378pub enum InvocationKind {379    Bang {380        mac: Box<ast::MacCall>,381        span: Span,382    },383    Attr {384        attr: ast::Attribute,385        /// Re-insertion position for inert attributes.386        pos: usize,387        item: Annotatable,388        /// Required for resolving derive helper attributes.389        derives: Vec<ast::Path>,390    },391    Derive {392        path: ast::Path,393        is_const: bool,394        item: Annotatable,395    },396    GlobDelegation {397        item: Box<ast::AssocItem>,398        /// Whether this is a trait impl or an inherent impl399        of_trait: bool,400    },401}402403impl InvocationKind {404    fn placeholder_visibility(&self) -> Option<ast::Visibility> {405        // HACK: For unnamed fields placeholders should have the same visibility as the actual406        // fields because for tuple structs/variants resolve determines visibilities of their407        // constructor using these field visibilities before attributes on them are expanded.408        // The assumption is that the attribute expansion cannot change field visibilities,409        // and it holds because only inert attributes are supported in this position.410        match self {411            InvocationKind::Attr { item: Annotatable::FieldDef(field), .. }412            | InvocationKind::Derive { item: Annotatable::FieldDef(field), .. }413                if field.ident.is_none() =>414            {415                Some(field.vis.clone())416            }417            _ => None,418        }419    }420}421422impl Invocation {423    pub fn span(&self) -> Span {424        match &self.kind {425            InvocationKind::Bang { span, .. } => *span,426            InvocationKind::Attr { attr, .. } => attr.span,427            InvocationKind::Derive { path, .. } => path.span,428            InvocationKind::GlobDelegation { item, .. } => item.span,429        }430    }431432    fn span_mut(&mut self) -> &mut Span {433        match &mut self.kind {434            InvocationKind::Bang { span, .. } => span,435            InvocationKind::Attr { attr, .. } => &mut attr.span,436            InvocationKind::Derive { path, .. } => &mut path.span,437            InvocationKind::GlobDelegation { item, .. } => &mut item.span,438        }439    }440}441442pub struct MacroExpander<'a, 'b> {443    pub cx: &'a mut ExtCtxt<'b>,444    monotonic: bool, // cf. `cx.monotonic_expander()`445}446447impl<'a, 'b> MacroExpander<'a, 'b> {448    pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {449        MacroExpander { cx, monotonic }450    }451452    pub fn expand_crate(&mut self, krate: ast::Crate) -> ast::Crate {453        let file_path = match self.cx.source_map().span_to_filename(krate.spans.inner_span) {454            FileName::Real(name) => name455                .into_local_path()456                .expect("attempting to resolve a file path in an external file"),457            other => PathBuf::from(other.prefer_local_unconditionally().to_string()),458        };459        let dir_path = file_path.parent().unwrap_or(&file_path).to_owned();460        self.cx.root_path = dir_path.clone();461        self.cx.current_expansion.module = Rc::new(ModuleData {462            mod_path: vec![Ident::with_dummy_span(self.cx.ecfg.crate_name)],463            file_path_stack: vec![file_path],464            dir_path,465        });466        let krate = self.fully_expand_fragment(AstFragment::Crate(krate)).make_crate();467        assert_eq!(krate.id, ast::CRATE_NODE_ID);468        self.cx.trace_macros_diag();469        krate470    }471472    /// Recursively expand all macro invocations in this AST fragment.473    pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {474        let orig_expansion_data = self.cx.current_expansion.clone();475        let orig_force_mode = self.cx.force_mode;476477        // Collect all macro invocations and replace them with placeholders.478        let (mut fragment_with_placeholders, mut invocations) =479            self.collect_invocations(input_fragment, &[]);480481        // Optimization: if we resolve all imports now,482        // we'll be able to immediately resolve most of imported macros.483        self.resolve_imports();484485        // Resolve paths in all invocations and produce output expanded fragments for them, but486        // do not insert them into our input AST fragment yet, only store in `expanded_fragments`.487        // The output fragments also go through expansion recursively until no invocations are left.488        // Unresolved macros produce dummy outputs as a recovery measure.489        invocations.reverse();490        let mut expanded_fragments = Vec::new();491        let mut expanded_fragments_len = 0;492        let mut undetermined_invocations = Vec::new();493        let (mut progress, mut force) = (false, !self.monotonic);494        loop {495            let Some((invoc, ext)) = invocations.pop() else {496                self.resolve_imports();497                if undetermined_invocations.is_empty() {498                    break;499                }500                invocations = mem::take(&mut undetermined_invocations);501                force = !progress;502                progress = false;503                if force && self.monotonic {504                    self.cx.dcx().span_delayed_bug(505                        invocations.last().unwrap().0.span(),506                        "expansion entered force mode without producing any errors",507                    );508                }509                continue;510            };511512            let ext = match ext {513                Some(ext) => ext,514                None => {515                    let eager_expansion_root = if self.monotonic {516                        invoc.expansion_data.id517                    } else {518                        orig_expansion_data.id519                    };520                    match self.cx.resolver.resolve_macro_invocation(521                        &invoc,522                        eager_expansion_root,523                        force,524                    ) {525                        Ok(ext) => ext,526                        Err(Indeterminate) => {527                            // Cannot resolve, will retry this invocation later.528                            undetermined_invocations.push((invoc, None));529                            continue;530                        }531                    }532                }533            };534535            let ExpansionData { depth, id: expn_id, .. } = invoc.expansion_data;536            let depth = depth - orig_expansion_data.depth;537            self.cx.current_expansion = invoc.expansion_data.clone();538            self.cx.force_mode = force;539540            let fragment_kind = invoc.fragment_kind;541            match self.expand_invoc(invoc, &ext.kind) {542                ExpandResult::Ready(fragment) => {543                    let mut derive_invocations = Vec::new();544                    let derive_placeholders = self545                        .cx546                        .resolver547                        .take_derive_resolutions(expn_id)548                        .map(|derives| {549                            derive_invocations.reserve(derives.len());550                            derives551                                .into_iter()552                                .map(|DeriveResolution { path, item, exts: _, is_const }| {553                                    // FIXME: Consider using the derive resolutions (`_exts`)554                                    // instead of enqueuing the derives to be resolved again later.555                                    // Note that this can result in duplicate diagnostics.556                                    let expn_id = LocalExpnId::fresh_empty();557                                    derive_invocations.push((558                                        Invocation {559                                            kind: InvocationKind::Derive { path, item, is_const },560                                            fragment_kind,561                                            expansion_data: ExpansionData {562                                                id: expn_id,563                                                ..self.cx.current_expansion.clone()564                                            },565                                        },566                                        None,567                                    ));568                                    NodeId::placeholder_from_expn_id(expn_id)569                                })570                                .collect::<Vec<_>>()571                        })572                        .unwrap_or_default();573574                    let (expanded_fragment, collected_invocations) =575                        self.collect_invocations(fragment, &derive_placeholders);576                    // We choose to expand any derive invocations associated with this macro577                    // invocation *before* any macro invocations collected from the output578                    // fragment.579                    derive_invocations.extend(collected_invocations);580581                    progress = true;582                    if expanded_fragments.len() < depth {583                        expanded_fragments.push(Vec::new());584                    }585                    expanded_fragments[depth - 1].push((expn_id, expanded_fragment));586                    expanded_fragments_len += 1;587                    invocations.extend(derive_invocations.into_iter().rev());588                }589                ExpandResult::Retry(invoc) => {590                    if force {591                        self.cx.dcx().span_bug(592                            invoc.span(),593                            "expansion entered force mode but is still stuck",594                        );595                    } else {596                        // Cannot expand, will retry this invocation later.597                        undetermined_invocations.push((invoc, Some(ext)));598                    }599                }600            }601        }602603        self.cx.current_expansion = orig_expansion_data;604        self.cx.force_mode = orig_force_mode;605606        // Finally incorporate all the expanded macros into the input AST fragment.607        let mut placeholder_expander = PlaceholderExpander::with_capacity(expanded_fragments_len);608        while let Some(expanded_fragments) = expanded_fragments.pop() {609            for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() {610                placeholder_expander611                    .add(NodeId::placeholder_from_expn_id(expn_id), expanded_fragment);612            }613        }614        fragment_with_placeholders.mut_visit_with(&mut placeholder_expander);615        fragment_with_placeholders616    }617618    fn resolve_imports(&mut self) {619        if self.monotonic {620            self.cx.resolver.resolve_imports();621        }622    }623624    /// Collects all macro invocations reachable at this time in this AST fragment, and replace625    /// them with "placeholders" - dummy macro invocations with specially crafted `NodeId`s.626    /// Then call into resolver that builds a skeleton ("reduced graph") of the fragment and627    /// prepares data for resolving paths of macro invocations.628    fn collect_invocations(629        &mut self,630        mut fragment: AstFragment,631        extra_placeholders: &[NodeId],632    ) -> (AstFragment, Vec<(Invocation, Option<Arc<SyntaxExtension>>)>) {633        // Resolve `$crate`s in the fragment for pretty-printing.634        self.cx.resolver.resolve_dollar_crates();635636        let mut invocations = {637            let mut collector = InvocationCollector {638                // Non-derive macro invocations cannot see the results of cfg expansion - they639                // will either be removed along with the item, or invoked before the cfg/cfg_attr640                // attribute is expanded. Therefore, we don't need to configure the tokens641                // Derive macros *can* see the results of cfg-expansion - they are handled642                // specially in `fully_expand_fragment`643                cx: self.cx,644                invocations: Vec::new(),645                monotonic: self.monotonic,646            };647            fragment.mut_visit_with(&mut collector);648            fragment.add_placeholders(extra_placeholders);649            collector.invocations650        };651652        if self.monotonic {653            self.cx654                .resolver655                .visit_ast_fragment_with_placeholders(self.cx.current_expansion.id, &fragment);656657            if self.cx.sess.opts.incremental.is_some() {658                for (invoc, _) in invocations.iter_mut() {659                    let expn_id = invoc.expansion_data.id;660                    let parent_def = self.cx.resolver.invocation_parent(expn_id);661                    let span = invoc.span_mut();662                    *span = span.with_parent(Some(parent_def));663                }664            }665        }666667        (fragment, invocations)668    }669670    fn error_recursion_limit_reached(&mut self) -> ErrorGuaranteed {671        let expn_data = self.cx.current_expansion.id.expn_data();672        let suggested_limit = match self.cx.ecfg.recursion_limit {673            Limit(0) => Limit(2),674            limit => limit * 2,675        };676677        let guar = self.cx.dcx().emit_err(RecursionLimitReached {678            span: expn_data.call_site,679            descr: expn_data.kind.descr(),680            suggested_limit,681            crate_name: self.cx.ecfg.crate_name,682        });683684        self.cx.macro_error_and_trace_macros_diag();685        guar686    }687688    /// A macro's expansion does not fit in this fragment kind.689    /// For example, a non-type macro in a type position.690    fn error_wrong_fragment_kind(691        &mut self,692        kind: AstFragmentKind,693        mac: &ast::MacCall,694        span: Span,695    ) -> ErrorGuaranteed {696        let name = pprust::path_to_string(&mac.path);697        let guar = self.cx.dcx().emit_err(WrongFragmentKind { span, kind: kind.name(), name });698        self.cx.macro_error_and_trace_macros_diag();699        guar700    }701702    fn expand_invoc(703        &mut self,704        invoc: Invocation,705        ext: &SyntaxExtensionKind,706    ) -> ExpandResult<AstFragment, Invocation> {707        let recursion_limit = match self.cx.reduced_recursion_limit {708            Some((limit, _)) => limit,709            None => self.cx.ecfg.recursion_limit,710        };711712        if !recursion_limit.value_within_limit(self.cx.current_expansion.depth) {713            let guar = match self.cx.reduced_recursion_limit {714                Some((_, guar)) => guar,715                None => self.error_recursion_limit_reached(),716            };717718            // Reduce the recursion limit by half each time it triggers.719            self.cx.reduced_recursion_limit = Some((recursion_limit / 2, guar));720721            return ExpandResult::Ready(invoc.fragment_kind.dummy(invoc.span(), guar));722        }723724        let macro_stats = self.cx.sess.opts.unstable_opts.macro_stats;725726        let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());727        ExpandResult::Ready(match invoc.kind {728            InvocationKind::Bang { mac, span } => {729                if let SyntaxExtensionKind::Bang(expander) = ext {730                    match expander.expand(self.cx, span, mac.args.tokens.clone()) {731                        Ok(tok_result) => {732                            let fragment =733                                self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span);734                            if macro_stats {735                                update_bang_macro_stats(736                                    self.cx,737                                    fragment_kind,738                                    span,739                                    mac,740                                    &fragment,741                                );742                            }743                            fragment744                        }745                        Err(guar) => return ExpandResult::Ready(fragment_kind.dummy(span, guar)),746                    }747                } else if let Some(expander) = ext.as_legacy_bang() {748                    let tok_result = match expander.expand(self.cx, span, mac.args.tokens.clone()) {749                        ExpandResult::Ready(tok_result) => tok_result,750                        ExpandResult::Retry(_) => {751                            // retry the original752                            return ExpandResult::Retry(Invocation {753                                kind: InvocationKind::Bang { mac, span },754                                ..invoc755                            });756                        }757                    };758                    if let Some(fragment) = fragment_kind.make_from(tok_result) {759                        if macro_stats {760                            update_bang_macro_stats(self.cx, fragment_kind, span, mac, &fragment);761                        }762                        fragment763                    } else {764                        let guar = self.error_wrong_fragment_kind(fragment_kind, &mac, span);765                        fragment_kind.dummy(span, guar)766                    }767                } else {768                    unreachable!();769                }770            }771            InvocationKind::Attr { attr, pos, mut item, derives } => {772                if let Some(expander) = ext.as_attr() {773                    self.gate_proc_macro_input(&item);774                    self.gate_proc_macro_attr_item(span, &item);775                    let tokens = match &item {776                        // FIXME: Collect tokens and use them instead of generating777                        // fake ones. These are unstable, so it needs to be778                        // fixed prior to stabilization779                        // Fake tokens when we are invoking an inner attribute, and780                        // we are invoking it on an out-of-line module or crate.781                        Annotatable::Crate(krate) => {782                            rustc_parse::fake_token_stream_for_crate(&self.cx.sess.psess, krate)783                        }784                        Annotatable::Item(item_inner)785                            if matches!(attr.style, AttrStyle::Inner)786                                && matches!(787                                    item_inner.kind,788                                    ItemKind::Mod(789                                        _,790                                        _,791                                        ModKind::Unloaded792                                            | ModKind::Loaded(_, Inline::No { .. }, _),793                                    )794                                ) =>795                        {796                            rustc_parse::fake_token_stream_for_item(&self.cx.sess.psess, item_inner)797                        }798                        Annotatable::Item(item_inner) if item_inner.tokens.is_none() => {799                            rustc_parse::fake_token_stream_for_item(&self.cx.sess.psess, item_inner)800                        }801                        // When a function has EII implementations attached (via `eii_impls`),802                        // use fake tokens so the pretty-printer re-emits the EII attribute803                        // (e.g. `#[hello]`) in the token stream. Without this, the EII804                        // attribute is lost during the token roundtrip performed by805                        // `AttrProcMacro` expanders like `contracts::requires/ensures`,806                        // breaking the EII link on the resulting re-parsed item.807                        Annotatable::Item(item_inner)808                            if matches!(&item_inner.kind,809                                ItemKind::Fn(f) if !f.eii_impls.is_empty()) =>810                        {811                            rustc_parse::fake_token_stream_for_item(&self.cx.sess.psess, item_inner)812                        }813                        Annotatable::ForeignItem(item_inner) if item_inner.tokens.is_none() => {814                            rustc_parse::fake_token_stream_for_foreign_item(815                                &self.cx.sess.psess,816                                item_inner,817                            )818                        }819                        _ => item.to_tokens(),820                    };821                    let attr_item = attr.get_normal_item();822                    let safety = attr_item.unsafety;823                    if let AttrArgs::Eq { .. } = attr_item.args.unparsed_ref().unwrap() {824                        self.cx.dcx().emit_err(UnsupportedKeyValue { span });825                    }826                    let inner_tokens = attr_item.args.unparsed_ref().unwrap().inner_tokens();827                    match expander.expand_with_safety(self.cx, safety, span, inner_tokens, tokens) {828                        Ok(tok_result) => {829                            let fragment = self.parse_ast_fragment(830                                tok_result,831                                fragment_kind,832                                &attr_item.path,833                                span,834                            );835                            if macro_stats {836                                update_attr_macro_stats(837                                    self.cx,838                                    fragment_kind,839                                    span,840                                    &attr_item.path,841                                    &attr,842                                    item,843                                    &fragment,844                                );845                            }846                            fragment847                        }848                        Err(guar) => return ExpandResult::Ready(fragment_kind.dummy(span, guar)),849                    }850                } else if let SyntaxExtensionKind::LegacyAttr(expander) = ext {851                    // `LegacyAttr` is only used for builtin attribute macros, which have their852                    // safety checked by `check_builtin_meta_item`, so we don't need to check853                    // `unsafety` here.854                    match validate_attr::parse_meta(&self.cx.sess.psess, &attr) {855                        Ok(meta) => {856                            let item_clone = macro_stats.then(|| item.clone());857                            let items = match expander.expand(self.cx, span, &meta, item, false) {858                                ExpandResult::Ready(items) => items,859                                ExpandResult::Retry(item) => {860                                    // Reassemble the original invocation for retrying.861                                    return ExpandResult::Retry(Invocation {862                                        kind: InvocationKind::Attr { attr, pos, item, derives },863                                        ..invoc864                                    });865                                }866                            };867                            if matches!(868                                fragment_kind,869                                AstFragmentKind::Expr | AstFragmentKind::MethodReceiverExpr870                            ) && items.is_empty()871                            {872                                let guar = self.cx.dcx().emit_err(RemoveExprNotSupported { span });873                                fragment_kind.dummy(span, guar)874                            } else {875                                let fragment = fragment_kind.expect_from_annotatables(items);876                                if macro_stats {877                                    update_attr_macro_stats(878                                        self.cx,879                                        fragment_kind,880                                        span,881                                        &meta.path,882                                        &attr,883                                        item_clone.unwrap(),884                                        &fragment,885                                    );886                                }887                                fragment888                            }889                        }890                        Err(err) => {891                            let _guar = err.emit();892                            fragment_kind.expect_from_annotatables(iter::once(item))893                        }894                    }895                } else if let SyntaxExtensionKind::NonMacroAttr = ext {896                    // `-Zmacro-stats` ignores these because they don't do any real expansion.897                    self.cx.expanded_inert_attrs.mark(&attr);898                    item.visit_attrs(|attrs| attrs.insert(pos, attr));899                    fragment_kind.expect_from_annotatables(iter::once(item))900                } else {901                    unreachable!();902                }903            }904            InvocationKind::Derive { path, item, is_const } => match ext {905                SyntaxExtensionKind::Derive(expander)906                | SyntaxExtensionKind::LegacyDerive(expander) => {907                    if let SyntaxExtensionKind::Derive(..) = ext {908                        self.gate_proc_macro_input(&item);909                    }910                    // The `MetaItem` representing the trait to derive can't911                    // have an unsafe around it (as of now).912                    let meta = ast::MetaItem {913                        unsafety: ast::Safety::Default,914                        kind: MetaItemKind::Word,915                        span,916                        path,917                    };918                    let items = match expander.expand(self.cx, span, &meta, item, is_const) {919                        ExpandResult::Ready(items) => items,920                        ExpandResult::Retry(item) => {921                            // Reassemble the original invocation for retrying.922                            return ExpandResult::Retry(Invocation {923                                kind: InvocationKind::Derive { path: meta.path, item, is_const },924                                ..invoc925                            });926                        }927                    };928                    let fragment = fragment_kind.expect_from_annotatables(items);929                    if macro_stats {930                        update_derive_macro_stats(931                            self.cx,932                            fragment_kind,933                            span,934                            &meta.path,935                            &fragment,936                        );937                    }938                    fragment939                }940                SyntaxExtensionKind::MacroRules(expander)941                    if expander.kinds().contains(MacroKinds::DERIVE) =>942                {943                    if is_const {944                        let guar = self945                            .cx946                            .dcx()947                            .span_err(span, "macro `derive` does not support const derives");948                        return ExpandResult::Ready(fragment_kind.dummy(span, guar));949                    }950                    let body = item.to_tokens();951                    match expander.expand_derive(self.cx, span, &body) {952                        Ok(tok_result) => {953                            let fragment =954                                self.parse_ast_fragment(tok_result, fragment_kind, &path, span);955                            if macro_stats {956                                update_derive_macro_stats(957                                    self.cx,958                                    fragment_kind,959                                    span,960                                    &path,961                                    &fragment,962                                );963                            }964                            fragment965                        }966                        Err(guar) => return ExpandResult::Ready(fragment_kind.dummy(span, guar)),967                    }968                }969                _ => unreachable!(),970            },971            InvocationKind::GlobDelegation { item, of_trait } => {972                let AssocItemKind::DelegationMac(deleg) = &item.kind else { unreachable!() };973                let suffixes = match ext {974                    SyntaxExtensionKind::GlobDelegation(expander) => match expander.expand(self.cx)975                    {976                        ExpandResult::Ready(suffixes) => suffixes,977                        ExpandResult::Retry(()) => {978                            // Reassemble the original invocation for retrying.979                            return ExpandResult::Retry(Invocation {980                                kind: InvocationKind::GlobDelegation { item, of_trait },981                                ..invoc982                            });983                        }984                    },985                    SyntaxExtensionKind::Bang(..) => {986                        let msg = "expanded a dummy glob delegation";987                        let guar = self.cx.dcx().span_delayed_bug(span, msg);988                        return ExpandResult::Ready(fragment_kind.dummy(span, guar));989                    }990                    _ => unreachable!(),991                };992993                type Node = AstNodeWrapper<Box<ast::AssocItem>, ImplItemTag>;994                let single_delegations = build_single_delegations::<Node>(995                    self.cx, deleg, &item, &suffixes, item.span, true,996                );997                // `-Zmacro-stats` ignores these because they don't seem important.998                fragment_kind.expect_from_annotatables(single_delegations.map(|item| {999                    Annotatable::AssocItem(Box::new(item), AssocCtxt::Impl { of_trait })1000                }))1001            }1002        })1003    }10041005    fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {1006        let kind = match item {1007            Annotatable::Item(_)1008            | Annotatable::AssocItem(..)1009            | Annotatable::ForeignItem(_)1010            | Annotatable::Crate(..) => return,1011            Annotatable::Stmt(stmt) => {1012                // Attributes are stable on item statements,1013                // but unstable on all other kinds of statements1014                if stmt.is_item() {1015                    return;1016                }1017                "statements"1018            }1019            Annotatable::Expr(_) => "expressions",1020            Annotatable::Arm(..)1021            | Annotatable::ExprField(..)1022            | Annotatable::PatField(..)1023            | Annotatable::GenericParam(..)1024            | Annotatable::Param(..)1025            | Annotatable::FieldDef(..)1026            | Annotatable::Variant(..)1027            | Annotatable::WherePredicate(..) => panic!("unexpected annotatable"),1028        };1029        if self.cx.ecfg.features.proc_macro_hygiene() {1030            return;1031        }1032        feature_err(1033            self.cx.sess,1034            sym::proc_macro_hygiene,1035            span,1036            format!("custom attributes cannot be applied to {kind}"),1037        )1038        .emit();1039    }10401041    fn gate_proc_macro_input(&self, annotatable: &Annotatable) {1042        struct GateProcMacroInput<'a> {1043            sess: &'a Session,1044        }10451046        impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> {1047            fn visit_item(&mut self, item: &'ast ast::Item) {1048                match &item.kind {1049                    ItemKind::Mod(_, _, mod_kind)1050                        if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) =>1051                    {1052                        feature_err(1053                            self.sess,1054                            sym::proc_macro_hygiene,1055                            item.span,1056                            msg!("file modules in proc macro input are unstable"),1057                        )1058                        .emit();1059                    }1060                    _ => {}1061                }10621063                visit::walk_item(self, item);1064            }1065        }10661067        if !self.cx.ecfg.features.proc_macro_hygiene() {1068            annotatable.visit_with(&mut GateProcMacroInput { sess: self.cx.sess });1069        }1070    }10711072    fn parse_ast_fragment(1073        &mut self,1074        toks: TokenStream,1075        kind: AstFragmentKind,1076        path: &ast::Path,1077        span: Span,1078    ) -> AstFragment {1079        let mut parser = self.cx.new_parser_from_tts(toks);1080        match parse_ast_fragment(&mut parser, kind) {1081            Ok(fragment) => {1082                ensure_complete_parse(&parser, path, kind.name(), span);1083                fragment1084            }1085            Err(mut err) => {1086                if err.span.is_dummy() {1087                    err.span(span);1088                }1089                annotate_err_with_kind(&mut err, kind, span);1090                let guar = err.emit();1091                self.cx.macro_error_and_trace_macros_diag();1092                kind.dummy(span, guar)1093            }1094        }1095    }1096}10971098pub fn parse_ast_fragment<'a>(1099    this: &mut Parser<'a>,1100    kind: AstFragmentKind,1101) -> PResult<'a, AstFragment> {1102    Ok(match kind {1103        AstFragmentKind::Items => {1104            let mut items = SmallVec::new();1105            while let Some(item) = this.parse_item(ForceCollect::No, AllowConstBlockItems::Yes)? {1106                items.push(item);1107            }1108            AstFragment::Items(items)1109        }1110        AstFragmentKind::TraitItems => {1111            let mut items = SmallVec::new();1112            while let Some(item) = this.parse_trait_item(ForceCollect::No)? {1113                items.extend(item);1114            }1115            AstFragment::TraitItems(items)1116        }1117        AstFragmentKind::ImplItems => {1118            let mut items = SmallVec::new();1119            while let Some(item) = this.parse_impl_item(ForceCollect::No)? {1120                items.extend(item);1121            }1122            AstFragment::ImplItems(items)1123        }1124        AstFragmentKind::TraitImplItems => {1125            let mut items = SmallVec::new();1126            while let Some(item) = this.parse_impl_item(ForceCollect::No)? {1127                items.extend(item);1128            }1129            AstFragment::TraitImplItems(items)1130        }1131        AstFragmentKind::ForeignItems => {1132            let mut items = SmallVec::new();1133            while let Some(item) = this.parse_foreign_item(ForceCollect::No)? {1134                items.extend(item);1135            }1136            AstFragment::ForeignItems(items)1137        }1138        AstFragmentKind::Stmts => {1139            let mut stmts = SmallVec::new();1140            // Won't make progress on a `}`.1141            while this.token != token::Eof && this.token != token::CloseBrace {1142                if let Some(stmt) = this.parse_full_stmt(AttemptLocalParseRecovery::Yes)? {1143                    stmts.push(stmt);1144                }1145            }1146            AstFragment::Stmts(stmts)1147        }1148        AstFragmentKind::Expr => AstFragment::Expr(this.parse_expr()?),1149        AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(this.parse_expr()?),1150        AstFragmentKind::OptExpr => {1151            if this.token != token::Eof {1152                AstFragment::OptExpr(Some(this.parse_expr()?))1153            } else {1154                AstFragment::OptExpr(None)1155            }1156        }1157        AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?),1158        AstFragmentKind::Pat => AstFragment::Pat(Box::new(this.parse_pat_allow_top_guard(1159            None,1160            RecoverComma::No,1161            RecoverColon::Yes,1162            CommaRecoveryMode::LikelyTuple,1163        )?)),1164        AstFragmentKind::Crate => AstFragment::Crate(this.parse_crate_mod()?),1165        AstFragmentKind::Arms1166        | AstFragmentKind::ExprFields1167        | AstFragmentKind::PatFields1168        | AstFragmentKind::GenericParams1169        | AstFragmentKind::Params1170        | AstFragmentKind::FieldDefs1171        | AstFragmentKind::Variants1172        | AstFragmentKind::WherePredicates => panic!("unexpected AST fragment kind"),1173    })1174}11751176pub(crate) fn ensure_complete_parse<'a>(1177    parser: &Parser<'a>,1178    macro_path: &ast::Path,1179    kind_name: &str,1180    span: Span,1181) {1182    if parser.token != token::Eof {1183        let descr = token_descr(&parser.token);1184        // Avoid emitting backtrace info twice.1185        let def_site_span = parser.token.span.with_ctxt(SyntaxContext::root());11861187        let semi_span = parser.psess.source_map().next_point(span);1188        let add_semicolon = match &parser.psess.source_map().span_to_snippet(semi_span) {1189            Ok(snippet) if &snippet[..] != ";" && kind_name == "expression" => {1190                Some(span.shrink_to_hi())1191            }1192            _ => None,1193        };11941195        let expands_to_match_arm = kind_name == "pattern" && parser.token == token::FatArrow;11961197        parser.dcx().emit_err(IncompleteParse {1198            span: def_site_span,1199            descr,1200            label_span: span,1201            macro_path: pprust::path_to_string(macro_path),1202            kind_name,1203            expands_to_match_arm,1204            add_semicolon,1205        });1206    }1207}12081209/// Wraps a call to `walk_*` / `walk_flat_map_*`1210/// for an AST node that supports attributes1211/// (see the `Annotatable` enum)1212/// This method assigns a `NodeId`, and sets that `NodeId`1213/// as our current 'lint node id'. If a macro call is found1214/// inside this AST node, we will use this AST node's `NodeId`1215/// to emit lints associated with that macro (allowing1216/// `#[allow]` / `#[deny]` to be applied close to1217/// the macro invocation).1218///1219/// Do *not* call this for a macro AST node1220/// (e.g. `ExprKind::MacCall`) - we cannot emit lints1221/// at these AST nodes, since they are removed and1222/// replaced with the result of macro expansion.1223///1224/// All other `NodeId`s are assigned by `visit_id`.1225/// * `self` is the 'self' parameter for the current method,1226/// * `id` is a mutable reference to the `NodeId` field1227///    of the current AST node.1228/// * `closure` is a closure that executes the1229///   `walk_*` / `walk_flat_map_*` method1230///   for the current AST node.1231macro_rules! assign_id {1232    ($self:ident, $id:expr, $closure:expr) => {{1233        let old_id = $self.cx.current_expansion.lint_node_id;1234        if $self.monotonic {1235            debug_assert_eq!(*$id, ast::DUMMY_NODE_ID);1236            let new_id = $self.cx.resolver.next_node_id();1237            *$id = new_id;1238            $self.cx.current_expansion.lint_node_id = new_id;1239        }1240        let ret = ($closure)();1241        $self.cx.current_expansion.lint_node_id = old_id;1242        ret1243    }};1244}12451246enum AddSemicolon {1247    Yes,1248    No,1249}12501251/// A trait implemented for all `AstFragment` nodes and providing all pieces1252/// of functionality used by `InvocationCollector`.1253trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized {1254    type OutputTy = SmallVec<[Self; 1]>;1255    type ItemKind = ItemKind;1256    const KIND: AstFragmentKind;1257    fn to_annotatable(self) -> Annotatable;1258    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy;1259    fn descr() -> &'static str {1260        unreachable!()1261    }1262    fn walk_flat_map(self, _collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {1263        unreachable!()1264    }1265    fn walk(&mut self, _collector: &mut InvocationCollector<'_, '_>) {1266        unreachable!()1267    }1268    fn is_mac_call(&self) -> bool {1269        false1270    }1271    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {1272        unreachable!()1273    }1274    fn delegation(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {1275        None1276    }1277    fn delegation_item_kind(_deleg: Box<ast::Delegation>) -> Self::ItemKind {1278        unreachable!()1279    }1280    fn from_item(_item: ast::Item<Self::ItemKind>) -> Self {1281        unreachable!()1282    }1283    fn flatten_outputs(_outputs: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {1284        unreachable!()1285    }1286    fn pre_flat_map_node_collect_attr(_cfg: &StripUnconfigured<'_>, _attr: &ast::Attribute) {}1287    fn post_flat_map_node_collect_bang(_output: &mut Self::OutputTy, _add_semicolon: AddSemicolon) {1288    }1289    fn wrap_flat_map_node_walk_flat_map(1290        node: Self,1291        collector: &mut InvocationCollector<'_, '_>,1292        walk_flat_map: impl FnOnce(Self, &mut InvocationCollector<'_, '_>) -> Self::OutputTy,1293    ) -> Result<Self::OutputTy, Self> {1294        Ok(walk_flat_map(node, collector))1295    }1296    fn expand_cfg_false(1297        &mut self,1298        collector: &mut InvocationCollector<'_, '_>,1299        _pos: usize,1300        span: Span,1301    ) {1302        collector.cx.dcx().emit_err(RemoveNodeNotSupported { span, descr: Self::descr() });1303    }13041305    /// All of the identifiers (items) declared by this node.1306    /// This is an approximation and should only be used for diagnostics.1307    fn declared_idents(&self) -> Vec<Ident> {1308        vec![]1309    }13101311    fn as_target(&self) -> Target;1312}13131314impl InvocationCollectorNode for Box<ast::Item> {1315    const KIND: AstFragmentKind = AstFragmentKind::Items;1316    fn to_annotatable(self) -> Annotatable {1317        Annotatable::Item(self)1318    }1319    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {1320        fragment.make_items()1321    }1322    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {1323        walk_flat_map_item(collector, self)1324    }1325    fn is_mac_call(&self) -> bool {1326        matches!(self.kind, ItemKind::MacCall(..))1327    }1328    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {1329        match self.kind {1330            ItemKind::MacCall(mac) => (mac, self.attrs, AddSemicolon::No),1331            _ => unreachable!(),1332        }1333    }1334    fn delegation(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {1335        match &self.kind {1336            ItemKind::DelegationMac(deleg) => Some((deleg, self)),1337            _ => None,1338        }1339    }1340    fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {1341        ItemKind::Delegation(deleg)1342    }1343    fn from_item(item: ast::Item<Self::ItemKind>) -> Self {1344        Box::new(item)1345    }1346    fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {1347        items.flatten().collect()1348    }1349    fn wrap_flat_map_node_walk_flat_map(1350        mut node: Self,1351        collector: &mut InvocationCollector<'_, '_>,1352        walk_flat_map: impl FnOnce(Self, &mut InvocationCollector<'_, '_>) -> Self::OutputTy,1353    ) -> Result<Self::OutputTy, Self> {1354        if !matches!(node.kind, ItemKind::Mod(..)) {1355            return Ok(walk_flat_map(node, collector));1356        }13571358        // Work around borrow checker not seeing through `P`'s deref.1359        let (span, mut attrs) = (node.span, mem::take(&mut node.attrs));1360        let ItemKind::Mod(_, ident, ref mut mod_kind) = node.kind else { unreachable!() };1361        let ecx = &mut collector.cx;1362        let (file_path, dir_path, dir_ownership) = match mod_kind {1363            ModKind::Loaded(_, inline, _) => {1364                // Inline `mod foo { ... }`, but we still need to push directories.1365                let (dir_path, dir_ownership) = mod_dir_path(1366                    ecx.sess,1367                    ident,1368                    &attrs,1369                    &ecx.current_expansion.module,1370                    ecx.current_expansion.dir_ownership,1371                    *inline,1372                );1373                // If the module was parsed from an external file, recover its path.1374                // This lets `parse_external_mod` catch cycles if it's self-referential.1375                let file_path = match inline {1376                    Inline::Yes => None,1377                    Inline::No { .. } => mod_file_path_from_attr(ecx.sess, &attrs, &dir_path),1378                };1379                node.attrs = attrs;1380                (file_path, dir_path, dir_ownership)1381            }1382            ModKind::Unloaded => {1383                // We have an outline `mod foo;` so we need to parse the file.1384                let old_attrs_len = attrs.len();1385                let ParsedExternalMod {1386                    items,1387                    spans,1388                    file_path,1389                    dir_path,1390                    dir_ownership,1391                    had_parse_error,1392                } = parse_external_mod(1393                    ecx.sess,1394                    ident,1395                    span,1396                    &ecx.current_expansion.module,1397                    ecx.current_expansion.dir_ownership,1398                    &mut attrs,1399                );14001401                if let Some(lint_store) = ecx.lint_store {1402                    lint_store.pre_expansion_lint(1403                        ecx.sess,1404                        ecx.ecfg.features,1405                        ecx.resolver.registered_tools(),1406                        ecx.current_expansion.lint_node_id,1407                        &attrs,1408                        &items,1409                        ident.name,1410                    );1411                }14121413                *mod_kind = ModKind::Loaded(items, Inline::No { had_parse_error }, spans);1414                node.attrs = attrs;1415                if node.attrs.len() > old_attrs_len {1416                    // If we loaded an out-of-line module and added some inner attributes,1417                    // then we need to re-configure it and re-collect attributes for1418                    // resolution and expansion.1419                    return Err(node);1420                }1421                (Some(file_path), dir_path, dir_ownership)1422            }1423        };14241425        // Set the module info before we flat map.1426        let mut module = ecx.current_expansion.module.with_dir_path(dir_path);1427        module.mod_path.push(ident);1428        if let Some(file_path) = file_path {1429            module.file_path_stack.push(file_path);1430        }14311432        let orig_module = mem::replace(&mut ecx.current_expansion.module, Rc::new(module));1433        let orig_dir_ownership =1434            mem::replace(&mut ecx.current_expansion.dir_ownership, dir_ownership);14351436        let res = Ok(walk_flat_map(node, collector));14371438        collector.cx.current_expansion.dir_ownership = orig_dir_ownership;1439        collector.cx.current_expansion.module = orig_module;1440        res1441    }14421443    fn declared_idents(&self) -> Vec<Ident> {1444        if let ItemKind::Use(ut) = &self.kind {1445            fn collect_use_tree_leaves(ut: &ast::UseTree, idents: &mut Vec<Ident>) {1446                match &ut.kind {1447                    ast::UseTreeKind::Glob(_) => {}1448                    ast::UseTreeKind::Simple(_) => idents.push(ut.ident()),1449                    ast::UseTreeKind::Nested { items, .. } => {1450                        for (ut, _) in items {1451                            collect_use_tree_leaves(ut, idents);1452                        }1453                    }1454                }1455            }1456            let mut idents = Vec::new();1457            collect_use_tree_leaves(ut, &mut idents);1458            idents1459        } else {1460            self.kind.ident().into_iter().collect()1461        }1462    }14631464    fn as_target(&self) -> Target {1465        Target::from_ast_item(self)1466    }1467}14681469struct TraitItemTag;1470impl InvocationCollectorNode for AstNodeWrapper<Box<ast::AssocItem>, TraitItemTag> {1471    type OutputTy = SmallVec<[Box<ast::AssocItem>; 1]>;1472    type ItemKind = AssocItemKind;1473    const KIND: AstFragmentKind = AstFragmentKind::TraitItems;1474    fn to_annotatable(self) -> Annotatable {1475        Annotatable::AssocItem(self.wrapped, AssocCtxt::Trait)1476    }1477    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {1478        fragment.make_trait_items()1479    }1480    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {1481        walk_flat_map_assoc_item(collector, self.wrapped, AssocCtxt::Trait)1482    }1483    fn is_mac_call(&self) -> bool {1484        matches!(self.wrapped.kind, AssocItemKind::MacCall(..))1485    }1486    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {1487        let item = self.wrapped;1488        match item.kind {1489            AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No),1490            _ => unreachable!(),1491        }1492    }1493    fn delegation(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {1494        match &self.wrapped.kind {1495            AssocItemKind::DelegationMac(deleg) => Some((deleg, &self.wrapped)),1496            _ => None,1497        }1498    }1499    fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {1500        AssocItemKind::Delegation(deleg)1501    }1502    fn from_item(item: ast::Item<Self::ItemKind>) -> Self {1503        AstNodeWrapper::new(Box::new(item), TraitItemTag)1504    }1505    fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {1506        items.flatten().collect()1507    }1508    fn as_target(&self) -> Target {1509        Target::from_assoc_item_kind(&self.wrapped.kind, AssocCtxt::Trait)1510    }1511}15121513struct ImplItemTag;1514impl InvocationCollectorNode for AstNodeWrapper<Box<ast::AssocItem>, ImplItemTag> {1515    type OutputTy = SmallVec<[Box<ast::AssocItem>; 1]>;1516    type ItemKind = AssocItemKind;1517    const KIND: AstFragmentKind = AstFragmentKind::ImplItems;1518    fn to_annotatable(self) -> Annotatable {1519        Annotatable::AssocItem(self.wrapped, AssocCtxt::Impl { of_trait: false })1520    }1521    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {1522        fragment.make_impl_items()1523    }1524    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {1525        walk_flat_map_assoc_item(collector, self.wrapped, AssocCtxt::Impl { of_trait: false })1526    }1527    fn is_mac_call(&self) -> bool {1528        matches!(self.wrapped.kind, AssocItemKind::MacCall(..))1529    }1530    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {1531        let item = self.wrapped;1532        match item.kind {1533            AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No),1534            _ => unreachable!(),1535        }1536    }1537    fn delegation(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {1538        match &self.wrapped.kind {1539            AssocItemKind::DelegationMac(deleg) => Some((deleg, &self.wrapped)),1540            _ => None,1541        }1542    }1543    fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {1544        AssocItemKind::Delegation(deleg)1545    }1546    fn from_item(item: ast::Item<Self::ItemKind>) -> Self {1547        AstNodeWrapper::new(Box::new(item), ImplItemTag)1548    }1549    fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {1550        items.flatten().collect()1551    }1552    fn as_target(&self) -> Target {1553        Target::from_assoc_item_kind(&self.wrapped.kind, AssocCtxt::Impl { of_trait: false })1554    }1555}15561557struct TraitImplItemTag;1558impl InvocationCollectorNode for AstNodeWrapper<Box<ast::AssocItem>, TraitImplItemTag> {1559    type OutputTy = SmallVec<[Box<ast::AssocItem>; 1]>;1560    type ItemKind = AssocItemKind;1561    const KIND: AstFragmentKind = AstFragmentKind::TraitImplItems;1562    fn to_annotatable(self) -> Annotatable {1563        Annotatable::AssocItem(self.wrapped, AssocCtxt::Impl { of_trait: true })1564    }1565    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {1566        fragment.make_trait_impl_items()1567    }1568    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {1569        walk_flat_map_assoc_item(collector, self.wrapped, AssocCtxt::Impl { of_trait: true })1570    }1571    fn is_mac_call(&self) -> bool {1572        matches!(self.wrapped.kind, AssocItemKind::MacCall(..))1573    }1574    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {1575        let item = self.wrapped;1576        match item.kind {1577            AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No),1578            _ => unreachable!(),1579        }1580    }1581    fn delegation(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {1582        match &self.wrapped.kind {1583            AssocItemKind::DelegationMac(deleg) => Some((deleg, &self.wrapped)),1584            _ => None,1585        }1586    }1587    fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {1588        AssocItemKind::Delegation(deleg)1589    }1590    fn from_item(item: ast::Item<Self::ItemKind>) -> Self {1591        AstNodeWrapper::new(Box::new(item), TraitImplItemTag)1592    }1593    fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {1594        items.flatten().collect()1595    }1596    fn as_target(&self) -> Target {1597        Target::from_assoc_item_kind(&self.wrapped.kind, AssocCtxt::Impl { of_trait: true })1598    }1599}16001601impl InvocationCollectorNode for Box<ast::ForeignItem> {1602    const KIND: AstFragmentKind = AstFragmentKind::ForeignItems;1603    fn to_annotatable(self) -> Annotatable {1604        Annotatable::ForeignItem(self)1605    }1606    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {1607        fragment.make_foreign_items()1608    }1609    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {1610        walk_flat_map_foreign_item(collector, self)1611    }1612    fn is_mac_call(&self) -> bool {1613        matches!(self.kind, ForeignItemKind::MacCall(..))1614    }1615    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {1616        match self.kind {1617            ForeignItemKind::MacCall(mac) => (mac, self.attrs, AddSemicolon::No),1618            _ => unreachable!(),1619        }1620    }1621    fn as_target(&self) -> Target {1622        match &self.kind {1623            ForeignItemKind::Static(_) => Target::ForeignStatic,1624            ForeignItemKind::Fn(_) => Target::ForeignFn,1625            ForeignItemKind::TyAlias(_) => Target::ForeignTy,1626            ForeignItemKind::MacCall(_) => Target::MacroCall,1627        }1628    }1629}16301631impl InvocationCollectorNode for ast::Variant {1632    const KIND: AstFragmentKind = AstFragmentKind::Variants;1633    fn to_annotatable(self) -> Annotatable {1634        Annotatable::Variant(self)1635    }1636    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {1637        fragment.make_variants()1638    }1639    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {1640        walk_flat_map_variant(collector, self)1641    }1642    fn as_target(&self) -> Target {1643        Target::Variant1644    }1645}16461647impl InvocationCollectorNode for ast::WherePredicate {1648    const KIND: AstFragmentKind = AstFragmentKind::WherePredicates;1649    fn to_annotatable(self) -> Annotatable {1650        Annotatable::WherePredicate(self)1651    }1652    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {1653        fragment.make_where_predicates()1654    }1655    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {1656        walk_flat_map_where_predicate(collector, self)1657    }1658    fn as_target(&self) -> Target {1659        Target::WherePredicate1660    }1661}16621663impl InvocationCollectorNode for ast::FieldDef {1664    const KIND: AstFragmentKind = AstFragmentKind::FieldDefs;1665    fn to_annotatable(self) -> Annotatable {1666        Annotatable::FieldDef(self)1667    }1668    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {1669        fragment.make_field_defs()1670    }1671    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {1672        walk_flat_map_field_def(collector, self)1673    }1674    fn as_target(&self) -> Target {1675        Target::Field1676    }1677}16781679impl InvocationCollectorNode for ast::PatField {1680    const KIND: AstFragmentKind = AstFragmentKind::PatFields;1681    fn to_annotatable(self) -> Annotatable {1682        Annotatable::PatField(self)1683    }1684    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {1685        fragment.make_pat_fields()1686    }1687    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {1688        walk_flat_map_pat_field(collector, self)1689    }1690    fn as_target(&self) -> Target {1691        Target::PatField1692    }1693}16941695impl InvocationCollectorNode for ast::ExprField {1696    const KIND: AstFragmentKind = AstFragmentKind::ExprFields;1697    fn to_annotatable(self) -> Annotatable {1698        Annotatable::ExprField(self)1699    }1700    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {1701        fragment.make_expr_fields()1702    }1703    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {1704        walk_flat_map_expr_field(collector, self)1705    }1706    fn as_target(&self) -> Target {1707        Target::ExprField1708    }1709}17101711impl InvocationCollectorNode for ast::Param {1712    const KIND: AstFragmentKind = AstFragmentKind::Params;1713    fn to_annotatable(self) -> Annotatable {1714        Annotatable::Param(self)1715    }1716    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {1717        fragment.make_params()1718    }1719    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {1720        walk_flat_map_param(collector, self)1721    }1722    fn as_target(&self) -> Target {1723        Target::Param1724    }1725}17261727impl InvocationCollectorNode for ast::GenericParam {1728    const KIND: AstFragmentKind = AstFragmentKind::GenericParams;1729    fn to_annotatable(self) -> Annotatable {1730        Annotatable::GenericParam(self)1731    }1732    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {1733        fragment.make_generic_params()1734    }1735    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {1736        walk_flat_map_generic_param(collector, self)1737    }1738    fn as_target(&self) -> Target {1739        let mut has_default = false;1740        Target::GenericParam {1741            kind: match &self.kind {1742                rustc_ast::GenericParamKind::Lifetime => {1743                    rustc_hir::target::GenericParamKind::Lifetime1744                }1745                rustc_ast::GenericParamKind::Type { default } => {1746                    has_default = default.is_some();1747                    rustc_hir::target::GenericParamKind::Type1748                }1749                rustc_ast::GenericParamKind::Const { default, .. } => {1750                    has_default = default.is_some();1751                    rustc_hir::target::GenericParamKind::Const1752                }1753            },1754            has_default,1755        }1756    }1757}17581759impl InvocationCollectorNode for ast::Arm {1760    const KIND: AstFragmentKind = AstFragmentKind::Arms;1761    fn to_annotatable(self) -> Annotatable {1762        Annotatable::Arm(self)1763    }1764    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {1765        fragment.make_arms()1766    }1767    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {1768        walk_flat_map_arm(collector, self)1769    }1770    fn as_target(&self) -> Target {1771        Target::Arm1772    }1773}17741775impl InvocationCollectorNode for ast::Stmt {1776    const KIND: AstFragmentKind = AstFragmentKind::Stmts;1777    fn to_annotatable(self) -> Annotatable {1778        Annotatable::Stmt(Box::new(self))1779    }1780    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {1781        fragment.make_stmts()1782    }1783    fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {1784        walk_flat_map_stmt(collector, self)1785    }1786    fn is_mac_call(&self) -> bool {1787        match &self.kind {1788            StmtKind::MacCall(..) => true,1789            StmtKind::Item(item) => matches!(item.kind, ItemKind::MacCall(..)),1790            StmtKind::Semi(expr) => matches!(expr.kind, ExprKind::MacCall(..)),1791            StmtKind::Expr(..) => unreachable!(),1792            StmtKind::Let(..) | StmtKind::Empty => false,1793        }1794    }1795    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {1796        // We pull macro invocations (both attributes and fn-like macro calls) out of their1797        // `StmtKind`s and treat them as statement macro invocations, not as items or expressions.1798        let (add_semicolon, mac, attrs) = match self.kind {1799            StmtKind::MacCall(mac) => {1800                let ast::MacCallStmt { mac, style, attrs, .. } = *mac;1801                (style == MacStmtStyle::Semicolon, mac, attrs)1802            }1803            StmtKind::Item(item) => match *item {1804                ast::Item { kind: ItemKind::MacCall(mac), attrs, .. } => {1805                    (mac.args.need_semicolon(), mac, attrs)1806                }1807                _ => unreachable!(),1808            },1809            StmtKind::Semi(expr) => match *expr {1810                ast::Expr { kind: ExprKind::MacCall(mac), attrs, .. } => {1811                    (mac.args.need_semicolon(), mac, attrs)1812                }1813                _ => unreachable!(),1814            },1815            _ => unreachable!(),1816        };1817        (mac, attrs, if add_semicolon { AddSemicolon::Yes } else { AddSemicolon::No })1818    }1819    fn delegation(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {1820        match &self.kind {1821            StmtKind::Item(item) => match &item.kind {1822                ItemKind::DelegationMac(deleg) => Some((deleg, item)),1823                _ => None,1824            },1825            _ => None,1826        }1827    }1828    fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {1829        ItemKind::Delegation(deleg)1830    }1831    fn from_item(item: ast::Item<Self::ItemKind>) -> Self {1832        ast::Stmt { id: ast::DUMMY_NODE_ID, span: item.span, kind: StmtKind::Item(Box::new(item)) }1833    }1834    fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {1835        items.flatten().collect()1836    }1837    fn post_flat_map_node_collect_bang(stmts: &mut Self::OutputTy, add_semicolon: AddSemicolon) {1838        // If this is a macro invocation with a semicolon, then apply that1839        // semicolon to the final statement produced by expansion.1840        if matches!(add_semicolon, AddSemicolon::Yes) {1841            if let Some(stmt) = stmts.pop() {1842                stmts.push(stmt.add_trailing_semicolon());1843            }1844        }1845    }1846    fn as_target(&self) -> Target {1847        Target::Statement1848    }1849}18501851impl InvocationCollectorNode for ast::Crate {1852    type OutputTy = ast::Crate;1853    const KIND: AstFragmentKind = AstFragmentKind::Crate;1854    fn to_annotatable(self) -> Annotatable {1855        Annotatable::Crate(self)1856    }1857    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {1858        fragment.make_crate()1859    }1860    fn walk(&mut self, collector: &mut InvocationCollector<'_, '_>) {1861        walk_crate(collector, self)1862    }1863    fn expand_cfg_false(1864        &mut self,1865        collector: &mut InvocationCollector<'_, '_>,1866        pos: usize,1867        _span: Span,1868    ) {1869        // Attributes above `cfg(FALSE)` are left in place, because we may want to configure1870        // some global crate properties even on fully unconfigured crates.1871        self.attrs.truncate(pos);1872        // Standard prelude imports are left in the crate for backward compatibility.1873        self.items.truncate(collector.cx.num_standard_library_imports);1874    }1875    fn as_target(&self) -> Target {1876        Target::Crate1877    }1878}18791880impl InvocationCollectorNode for ast::Ty {1881    type OutputTy = Box<ast::Ty>;1882    const KIND: AstFragmentKind = AstFragmentKind::Ty;1883    fn to_annotatable(self) -> Annotatable {1884        unreachable!()1885    }1886    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {1887        fragment.make_ty()1888    }1889    fn walk(&mut self, collector: &mut InvocationCollector<'_, '_>) {1890        // Save the pre-expanded name of this `ImplTrait`, so that later when defining1891        // an APIT we use a name that doesn't have any placeholder fragments in it.1892        if let ast::TyKind::ImplTrait(..) = self.kind {1893            // HACK: pprust breaks strings with newlines when the type1894            // gets too long. We don't want these to show up in compiler1895            // output or built artifacts, so replace them here...1896            // Perhaps we should instead format APITs more robustly.1897            let name = Symbol::intern(&pprust::ty_to_string(self).replace('\n', " "));1898            collector.cx.resolver.insert_impl_trait_name(self.id, name);1899        }1900        walk_ty(collector, self)1901    }1902    fn is_mac_call(&self) -> bool {1903        matches!(self.kind, ast::TyKind::MacCall(..))1904    }1905    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {1906        match self.kind {1907            TyKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No),1908            _ => unreachable!(),1909        }1910    }1911    fn as_target(&self) -> Target {1912        // This is only used for attribute parsing, which are not allowed on types.1913        unreachable!()1914    }1915}19161917impl InvocationCollectorNode for ast::Pat {1918    type OutputTy = Box<ast::Pat>;1919    const KIND: AstFragmentKind = AstFragmentKind::Pat;1920    fn to_annotatable(self) -> Annotatable {1921        unreachable!()1922    }1923    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {1924        fragment.make_pat()1925    }1926    fn walk(&mut self, collector: &mut InvocationCollector<'_, '_>) {1927        walk_pat(collector, self)1928    }1929    fn is_mac_call(&self) -> bool {1930        matches!(self.kind, PatKind::MacCall(..))1931    }1932    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {1933        match self.kind {1934            PatKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No),1935            _ => unreachable!(),1936        }1937    }1938    fn as_target(&self) -> Target {1939        todo!();1940    }1941}19421943impl InvocationCollectorNode for ast::Expr {1944    type OutputTy = Box<ast::Expr>;1945    const KIND: AstFragmentKind = AstFragmentKind::Expr;1946    fn to_annotatable(self) -> Annotatable {1947        Annotatable::Expr(Box::new(self))1948    }1949    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {1950        fragment.make_expr()1951    }1952    fn descr() -> &'static str {1953        "an expression"1954    }1955    fn walk(&mut self, collector: &mut InvocationCollector<'_, '_>) {1956        walk_expr(collector, self)1957    }1958    fn is_mac_call(&self) -> bool {1959        matches!(self.kind, ExprKind::MacCall(..))1960    }1961    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {1962        match self.kind {1963            ExprKind::MacCall(mac) => (mac, self.attrs, AddSemicolon::No),1964            _ => unreachable!(),1965        }1966    }1967    fn as_target(&self) -> Target {1968        Target::Expression1969    }1970}19711972struct OptExprTag;1973impl InvocationCollectorNode for AstNodeWrapper<Box<ast::Expr>, OptExprTag> {1974    type OutputTy = Option<Box<ast::Expr>>;1975    const KIND: AstFragmentKind = AstFragmentKind::OptExpr;1976    fn to_annotatable(self) -> Annotatable {1977        Annotatable::Expr(self.wrapped)1978    }1979    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {1980        fragment.make_opt_expr()1981    }1982    fn walk_flat_map(mut self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy {1983        walk_expr(collector, &mut self.wrapped);1984        Some(self.wrapped)1985    }1986    fn is_mac_call(&self) -> bool {1987        matches!(self.wrapped.kind, ast::ExprKind::MacCall(..))1988    }1989    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {1990        let node = self.wrapped;1991        match node.kind {1992            ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),1993            _ => unreachable!(),1994        }1995    }1996    fn pre_flat_map_node_collect_attr(cfg: &StripUnconfigured<'_>, attr: &ast::Attribute) {1997        cfg.maybe_emit_expr_attr_err(attr);1998    }1999    fn as_target(&self) -> Target {2000        Target::Expression

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.