compiler/rustc_ast/src/visit.rs RUST 1,201 lines View on github.com → Search inside
1//! AST walker. Each overridden visit method has full control over what2//! happens with its node, it can do its own traversal of the node's children,3//! call `visit::walk_*` to apply the default traversal algorithm, or prevent4//! deeper traversal by doing nothing.5//!6//! Note: it is an important invariant that the default visitor walks the body7//! of a function in "execution order" (more concretely, reverse post-order8//! with respect to the CFG implied by the AST), meaning that if AST node A may9//! execute before AST node B, then A is visited first. The borrow checker in10//! particular relies on this property.11//!12//! Note: walking an AST before macro expansion is probably a bad idea. For13//! instance, a walker looking for item names in a module will miss all of14//! those that are created by the expansion of a macro.1516pub use rustc_ast_ir::visit::VisitorResult;17pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list};18use rustc_span::{Ident, Span, Spanned, Symbol};19use thin_vec::ThinVec;2021use crate::ast::*;22use crate::tokenstream::DelimSpan;2324#[derive(Copy, Clone, Debug, PartialEq)]25pub enum AssocCtxt {26    Trait,27    Impl { of_trait: bool },28}2930#[derive(Copy, Clone, Debug, PartialEq)]31pub enum FnCtxt {32    Free,33    Foreign,34    Assoc(AssocCtxt),35}3637#[derive(Copy, Clone, Debug)]38pub enum BoundKind {39    /// Trait bounds in generics bounds and type/trait alias.40    /// E.g., `<T: Bound>`, `type A: Bound`, or `where T: Bound`.41    Bound,4243    /// Trait bounds in `impl` type.44    /// E.g., `type Foo = impl Bound1 + Bound2 + Bound3`.45    Impl,4647    /// Trait bounds in trait object type.48    /// E.g., `dyn Bound1 + Bound2 + Bound3`.49    TraitObject,5051    /// Super traits of a trait.52    /// E.g., `trait A: B`53    SuperTraits,54}55impl BoundKind {56    pub fn descr(self) -> &'static str {57        match self {58            BoundKind::Bound => "bounds",59            BoundKind::Impl => "`impl Trait`",60            BoundKind::TraitObject => "`dyn` trait object bounds",61            BoundKind::SuperTraits => "supertrait bounds",62        }63    }64}6566#[derive(Copy, Clone, Debug)]67pub enum LifetimeCtxt {68    /// Appears in a reference type.69    Ref,70    /// Appears as a bound on a type or another lifetime.71    Bound,72    /// Appears as a generic argument.73    GenericArg,74}7576pub(crate) trait Visitable<'a, V: Visitor<'a>> {77    type Extra: Copy;7879    #[must_use]80    fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result;81}8283impl<'a, V: Visitor<'a>, T: ?Sized> Visitable<'a, V> for Box<T>84where85    T: Visitable<'a, V>,86{87    type Extra = T::Extra;88    fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {89        (**self).visit(visitor, extra)90    }91}9293impl<'a, V: Visitor<'a>, T> Visitable<'a, V> for Option<T>94where95    T: Visitable<'a, V>,96{97    type Extra = T::Extra;98    fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {99        if let Some(this) = self {100            try_visit!(this.visit(visitor, extra));101        }102        V::Result::output()103    }104}105106impl<'a, V: Visitor<'a>, T> Visitable<'a, V> for Spanned<T>107where108    T: Visitable<'a, V>,109{110    type Extra = T::Extra;111    fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {112        let Spanned { span: _, node } = self;113        node.visit(visitor, extra)114    }115}116117impl<'a, V: Visitor<'a>, T> Visitable<'a, V> for [T]118where119    T: Visitable<'a, V>,120{121    type Extra = T::Extra;122    fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {123        for item in self {124            try_visit!(item.visit(visitor, extra));125        }126        V::Result::output()127    }128}129130impl<'a, V: Visitor<'a>, T> Visitable<'a, V> for Vec<T>131where132    T: Visitable<'a, V>,133{134    type Extra = T::Extra;135    fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {136        for item in self {137            try_visit!(item.visit(visitor, extra));138        }139        V::Result::output()140    }141}142143impl<'a, V: Visitor<'a>, T> Visitable<'a, V> for (T,)144where145    T: Visitable<'a, V>,146{147    type Extra = T::Extra;148    fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {149        self.0.visit(visitor, extra)150    }151}152153impl<'a, V: Visitor<'a>, T1, T2> Visitable<'a, V> for (T1, T2)154where155    T1: Visitable<'a, V, Extra = ()>,156    T2: Visitable<'a, V, Extra = ()>,157{158    type Extra = ();159    fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {160        try_visit!(self.0.visit(visitor, extra));161        try_visit!(self.1.visit(visitor, extra));162        V::Result::output()163    }164}165166impl<'a, V: Visitor<'a>, T1, T2, T3> Visitable<'a, V> for (T1, T2, T3)167where168    T1: Visitable<'a, V, Extra = ()>,169    T2: Visitable<'a, V, Extra = ()>,170    T3: Visitable<'a, V, Extra = ()>,171{172    type Extra = ();173    fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {174        try_visit!(self.0.visit(visitor, extra));175        try_visit!(self.1.visit(visitor, extra));176        try_visit!(self.2.visit(visitor, extra));177        V::Result::output()178    }179}180181impl<'a, V: Visitor<'a>, T1, T2, T3, T4> Visitable<'a, V> for (T1, T2, T3, T4)182where183    T1: Visitable<'a, V, Extra = ()>,184    T2: Visitable<'a, V, Extra = ()>,185    T3: Visitable<'a, V, Extra = ()>,186    T4: Visitable<'a, V, Extra = ()>,187{188    type Extra = ();189    fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {190        try_visit!(self.0.visit(visitor, extra));191        try_visit!(self.1.visit(visitor, extra));192        try_visit!(self.2.visit(visitor, extra));193        try_visit!(self.3.visit(visitor, extra));194        V::Result::output()195    }196}197198pub(crate) trait Walkable<'a, V: Visitor<'a>> {199    #[must_use]200    fn walk_ref(&'a self, visitor: &mut V) -> V::Result;201}202203macro_rules! visit_visitable {204    ($visitor:expr, $($expr:expr),* $(,)?) => {{205        $(try_visit!(Visitable::visit($expr, $visitor, ()));)*206    }};207}208209macro_rules! visit_visitable_with {210    ($visitor:expr, $expr:expr, $extra:expr $(,)?) => {211        try_visit!(Visitable::visit($expr, $visitor, $extra))212    };213}214215macro_rules! walk_walkable {216    ($visitor:expr, $expr:expr, ) => {217        Walkable::walk_ref($expr, $visitor)218    };219}220221macro_rules! impl_visitable {222    (|&$lt:lifetime $self:ident: $self_ty:ty,223      $vis:ident: &mut $vis_ty:ident,224      $extra:ident: $extra_ty:ty| $block:block) => {225        #[allow(unused_parens, non_local_definitions)]226        impl<$lt, $vis_ty: Visitor<$lt>> Visitable<$lt, $vis_ty> for $self_ty {227            type Extra = $extra_ty;228            fn visit(&$lt $self, $vis: &mut $vis_ty, $extra: Self::Extra) -> V::Result {229                $block230            }231        }232    };233}234235macro_rules! impl_walkable {236    ($(<$K:ident: $Kb:ident>)? |&$lt:lifetime $self:ident: $self_ty:ty,237      $vis:ident: &mut $vis_ty:ident| $block:block) => {238        #[allow(unused_parens, non_local_definitions)]239        impl<$($K: $Kb,)? $lt, $vis_ty: Visitor<$lt>> Walkable<$lt, $vis_ty> for $self_ty {240            fn walk_ref(&$lt $self, $vis: &mut $vis_ty) -> V::Result {241                $block242            }243        }244    };245}246247macro_rules! impl_visitable_noop {248    (<$lt:lifetime> $($ty:ty,)*) => {249        $(250            impl_visitable!(|&$lt self: $ty, _vis: &mut V, _extra: ()| {251                V::Result::output()252            });253        )*254    };255}256257macro_rules! impl_visitable_list {258    (<$lt:lifetime> $($ty:ty,)*) => {259        $(impl<$lt, V: Visitor<$lt>, T> Visitable<$lt, V> for $ty260        where261            &$lt $ty: IntoIterator<Item = &$lt T>,262            T: $lt + Visitable<$lt, V>,263        {264            type Extra = <T as Visitable<$lt, V>>::Extra;265266            #[inline]267            fn visit(&$lt self, visitor: &mut V, extra: Self::Extra) -> V::Result {268                for i in self {269                    try_visit!(i.visit(visitor, extra));270                }271                V::Result::output()272            }273        })*274    };275}276277macro_rules! impl_visitable_direct {278    (<$lt:lifetime> $($ty:ty,)*) => {279        $(impl_visitable!(280            |&$lt self: $ty, visitor: &mut V, _extra: ()| {281                Walkable::walk_ref(self, visitor)282            }283        );)*284    };285}286287macro_rules! impl_visitable_calling_walkable {288    (<$lt:lifetime>289        $( fn $method:ident($ty:ty $(, $extra_name:ident: $extra_ty:ty)?); )*290    ) => {291        $(fn $method(&mut self, node: &$lt $ty $(, $extra_name:$extra_ty)?) -> Self::Result {292            impl_visitable!(|&$lt self: $ty, visitor: &mut V, extra: ($($extra_ty)?)| {293                let ($($extra_name)?) = extra;294                visitor.$method(self $(, $extra_name)?)295            });296            walk_walkable!(self, node, )297        })*298    };299}300301macro_rules! define_named_walk {302    ($Visitor:ident<$lt:lifetime>303        $( pub fn $method:ident($ty:ty); )*304    ) => {305        $(pub fn $method<$lt, V: $Visitor<$lt>>(visitor: &mut V, node: &$lt $ty) -> V::Result {306            walk_walkable!(visitor, node,)307        })*308    };309}310311#[macro_export]312macro_rules! common_visitor_and_walkers {313    ($(($mut: ident))? $Visitor:ident$(<$lt:lifetime>)?) => {314        $(${ignore($lt)}315            #[derive(Copy, Clone)]316        )?317        #[derive(Debug)]318        pub enum FnKind<'a> {319            /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.320            Fn(FnCtxt, &'a $($mut)? Visibility, &'a $($mut)? Fn),321322            /// E.g., `|x, y| body`.323            Closure(&'a $($mut)? ClosureBinder, &'a $($mut)? Option<CoroutineKind>, &'a $($mut)? Box<FnDecl>, &'a $($mut)? Box<Expr>),324        }325326        impl<'a> FnKind<'a> {327            pub fn header(&'a $($mut)? self) -> Option<&'a $($mut)? FnHeader> {328                match *self {329                    FnKind::Fn(_, _, Fn { sig, .. }) => Some(&$($mut)? sig.header),330                    FnKind::Closure(..) => None,331                }332            }333334            pub fn ident(&'a $($mut)? self) -> Option<&'a $($mut)? Ident> {335                match self {336                    FnKind::Fn(_, _, Fn { ident, .. }) => Some(ident),337                    _ => None,338                }339            }340341            pub fn decl(&'a $($mut)? self) -> &'a $($mut)? FnDecl {342                match self {343                    FnKind::Fn(_, _, Fn { sig, .. }) => &$($mut)? sig.decl,344                    FnKind::Closure(_, _, decl, _) => decl,345                }346            }347348            pub fn ctxt(&self) -> Option<FnCtxt> {349                match self {350                    FnKind::Fn(ctxt, ..) => Some(*ctxt),351                    FnKind::Closure(..) => None,352                }353            }354        }355356        // This macro generates `impl Visitable` and `impl MutVisitable` that do nothing.357        impl_visitable_noop!(<$($lt)? $($mut)?>358            AttrId,359            bool,360            rustc_span::ByteSymbol,361            char,362            crate::token::CommentKind,363            crate::token::Delimiter,364            crate::token::Lit,365            crate::token::LitKind,366            crate::tokenstream::LazyAttrTokenStream,367            crate::tokenstream::TokenStream,368            EarlyParsedAttribute,369            Movability,370            Mutability,371            Pinnedness,372            Result<(), rustc_span::ErrorGuaranteed>,373            rustc_data_structures::fx::FxHashMap<Symbol, usize>,374            rustc_span::ErrorGuaranteed,375            std::borrow::Cow<'_, str>,376            Symbol,377            u8,378            usize,379        );380        // `Span` is only a no-op for the non-mutable visitor.381        $(impl_visitable_noop!(<$lt> Span,);)?382383        // This macro generates `impl Visitable` and `impl MutVisitable` that simply iterate over384        // their contents. We do not use a generic impl for `ThinVec` because we want to allow385        // custom visits for the `MutVisitor`.386        impl_visitable_list!(<$($lt)? $($mut)?>387            ThinVec<AngleBracketedArg>,388            ThinVec<Attribute>,389            ThinVec<(Ident, Option<Ident>)>,390            ThinVec<(NodeId, Path)>,391            ThinVec<PathSegment>,392            ThinVec<PreciseCapturingArg>,393            ThinVec<Pat>,394            ThinVec<Box<Ty>>,395            ThinVec<TyPat>,396            ThinVec<EiiImpl>,397        );398399        // This macro generates `impl Visitable` and `impl MutVisitable` that forward to `Walkable`400        // or `MutWalkable`. By default, all types that do not have a custom visit method in the401        // visitor should appear here.402        impl_visitable_direct!(<$($lt)? $($mut)?>403            AngleBracketedArg,404            AngleBracketedArgs,405            AsmMacro,406            AssignOpKind,407            AssocItemConstraintKind,408            AttrArgs,409            AttrItem,410            AttrKind,411            AttrStyle,412            FnPtrTy,413            BindingMode,414            GenBlockKind,415            RangeLimits,416            UnsafeBinderCastKind,417            BinOpKind,418            BlockCheckMode,419            MgcaDisambiguation,420            BorrowKind,421            BoundAsyncness,422            BoundConstness,423            BoundPolarity,424            ByRef,425            Closure,426            Const,427            ConstBlockItem,428            ConstItem,429            ConstItemRhsKind,430            Defaultness,431            Delegation,432            DelegationMac,433            DelegationSuffixes,434            DelimArgs,435            DelimSpan,436            EnumDef,437            Extern,438            ForLoopKind,439            FormatArgPosition,440            FormatArgsPiece,441            FormatArgument,442            FormatArgumentKind,443            FormatArguments,444            FormatPlaceholder,445            GenericParamKind,446            Guard,447            Impl,448            ImplPolarity,449            Inline,450            InlineAsmOperand,451            InlineAsmRegOrRegClass,452            InlineAsmTemplatePiece,453            IsAuto,454            LocalKind,455            MacCallStmt,456            MacStmtStyle,457            MatchKind,458            MethodCall,459            ModKind,460            ModSpans,461            MutTy,462            NormalAttr,463            AttrItemKind,464            Parens,465            ParenthesizedArgs,466            PatFieldsRest,467            PatKind,468            RangeEnd,469            RangeSyntax,470            Recovered,471            RestrictionKind,472            Safety,473            StaticItem,474            StrLit,475            StrStyle,476            StructExpr,477            StructRest,478            Term,479            Trait,480            TraitBoundModifiers,481            TraitObjectSyntax,482            TyAlias,483            TyKind,484            TyPatKind,485            UnOp,486            UnsafeBinderTy,487            UnsafeSource,488            UseTreeKind,489            VisibilityKind,490            WhereBoundPredicate,491            WhereClause,492            WhereEqPredicate,493            WhereRegionPredicate,494            YieldKind,495            EiiDecl,496            EiiImpl,497        );498499        /// Each method of this trait is a hook to be potentially500        /// overridden. Each method's default implementation recursively visits501        /// the substructure of the input via the corresponding `walk` method;502        #[doc = concat!(" e.g., the `visit_item` method by default calls `visit"$(, "_", stringify!($mut))?, "::walk_item`.")]503        ///504        /// If you want to ensure that your code handles every variant505        /// explicitly, you need to override each method. (And you also need506        /// to monitor future changes to this trait in case a new method with a507        /// new default implementation gets introduced.)508        ///509        /// Every `walk_*` method uses deconstruction to access fields of structs and510        /// enums. This will result in a compile error if a field is added, which makes511        /// it more likely the appropriate visit call will be added for it.512        pub trait $Visitor<$($lt)?> : Sized $(${ignore($mut)} + MutVisitorResult<Result = ()>)? {513            $(514                ${ignore($lt)}515                /// The result type of the `visit_*` methods. Can be either `()`,516                /// or `ControlFlow<T>`.517                type Result: VisitorResult = ();518            )?519520            // Methods in this trait have one of three forms, with the last two forms521            // only occurring on `MutVisitor`:522            //523            //   fn visit_t(&mut self, t: &mut T);                      // common524            //   fn flat_map_t(&mut self, t: T) -> SmallVec<[T; 1]>;    // rare525            //   fn filter_map_t(&mut self, t: T) -> Option<T>;         // rarest526            //527            // When writing these methods, it is better to use destructuring like this:528            //529            //   fn visit_abc(&mut self, ABC { a, b, c: _ }: &mut ABC) {530            //       visit_a(a);531            //       visit_b(b);532            //   }533            //534            // than to use field access like this:535            //536            //   fn visit_abc(&mut self, abc: &mut ABC) {537            //       visit_a(&mut abc.a);538            //       visit_b(&mut abc.b);539            //       // ignore abc.c540            //   }541            //542            // As well as being more concise, the former is explicit about which fields543            // are skipped. Furthermore, if a new field is added, the destructuring544            // version will cause a compile error, which is good. In comparison, the545            // field access version will continue working and it would be easy to546            // forget to add handling for it.547            fn visit_ident(&mut self, Ident { name: _, span }: &$($lt)? $($mut)? Ident) -> Self::Result {548                impl_visitable!(|&$($lt)? $($mut)? self: Ident, visitor: &mut V, _extra: ()| {549                    visitor.visit_ident(self)550                });551                visit_span(self, span)552            }553554            // This macro defines a custom visit method for each listed type.555            // It implements `impl Visitable` and `impl MutVisitable` to call those methods on the556            // visitor.557            impl_visitable_calling_walkable!(<$($lt)? $($mut)?>558                fn visit_anon_const(AnonConst);559                fn visit_arm(Arm);560                //fn visit_assoc_item(AssocItem, _ctxt: AssocCtxt);561                fn visit_assoc_item_constraint(AssocItemConstraint);562                fn visit_attribute(Attribute);563                fn visit_block(Block);564                //fn visit_nested_use_tree((UseTree, NodeId));565                fn visit_capture_by(CaptureBy);566                fn visit_closure_binder(ClosureBinder);567                fn visit_contract(FnContract);568                fn visit_coroutine_kind(CoroutineKind);569                fn visit_crate(Crate);570                fn visit_expr(Expr);571                fn visit_expr_field(ExprField);572                fn visit_field_def(FieldDef);573                fn visit_fn_decl(FnDecl);574                fn visit_fn_header(FnHeader);575                fn visit_fn_ret_ty(FnRetTy);576                //fn visit_foreign_item(ForeignItem);577                fn visit_foreign_mod(ForeignMod);578                fn visit_format_args(FormatArgs);579                fn visit_generic_arg(GenericArg);580                fn visit_generic_args(GenericArgs);581                fn visit_generic_param(GenericParam);582                fn visit_generics(Generics);583                fn visit_inline_asm(InlineAsm);584                fn visit_inline_asm_sym(InlineAsmSym);585                //fn visit_item(Item);586                fn visit_label(Label);587                fn visit_lifetime(Lifetime, _ctxt: LifetimeCtxt);588                fn visit_local(Local);589                fn visit_mac_call(MacCall);590                fn visit_macro_def(MacroDef);591                fn visit_param_bound(GenericBound, _ctxt: BoundKind);592                fn visit_param(Param);593                fn visit_pat_field(PatField);594                fn visit_path(Path);595                fn visit_path_segment(PathSegment);596                fn visit_pat(Pat);597                fn visit_poly_trait_ref(PolyTraitRef);598                fn visit_precise_capturing_arg(PreciseCapturingArg);599                fn visit_qself(QSelf);600                fn visit_impl_restriction(ImplRestriction);601                fn visit_trait_ref(TraitRef);602                fn visit_ty_pat(TyPat);603                fn visit_ty(Ty);604                fn visit_use_tree(UseTree);605                fn visit_variant_data(VariantData);606                fn visit_variant(Variant);607                fn visit_vis(Visibility);608                fn visit_where_predicate_kind(WherePredicateKind);609                fn visit_where_predicate(WherePredicate);610            );611612            // We want `Visitor` to take the `NodeId` by value.613            fn visit_id(&mut self, _id: $(&$mut)? NodeId) -> Self::Result {614                $(impl_visitable!(615                    |&$lt self: NodeId, visitor: &mut V, _extra: ()| {616                        visitor.visit_id(*self)617                    }618                );)?619                $(impl_visitable!(620                    |&$mut self: NodeId, visitor: &mut V, _extra: ()| {621                        visitor.visit_id(self)622                    }623                );)?624                Self::Result::output()625            }626627            /// This method is a hack to workaround unstable of `stmt_expr_attributes`.628            /// It can be removed once that feature is stabilized.629            fn visit_method_receiver_expr(&mut self, ex: &$($lt)? $($mut)? Expr) -> Self::Result {630                self.visit_expr(ex)631            }632633            fn visit_item(&mut self, item: &$($lt)? $($mut)? Item) -> Self::Result {634                impl_visitable!(|&$($lt)? $($mut)? self: Item, vis: &mut V, _extra: ()| {635                    vis.visit_item(self)636                });637                walk_item(self, item)638            }639640            fn visit_foreign_item(&mut self, item: &$($lt)? $($mut)? ForeignItem) -> Self::Result {641                impl_visitable!(|&$($lt)? $($mut)? self: ForeignItem, vis: &mut V, _extra: ()| {642                    vis.visit_foreign_item(self)643                });644                walk_item(self, item)645            }646647            fn visit_assoc_item(&mut self, item: &$($lt)? $($mut)? AssocItem, ctxt: AssocCtxt) -> Self::Result {648                impl_visitable!(|&$($lt)? $($mut)? self: AssocItem, vis: &mut V, ctxt: AssocCtxt| {649                    vis.visit_assoc_item(self, ctxt)650                });651                walk_assoc_item(self, item, ctxt)652            }653654            // for `MutVisitor`: `Span` and `NodeId` are mutated at the caller site.655            fn visit_fn(656                &mut self,657                fk: FnKind<$($lt)? $(${ignore($mut)} '_)?>,658                _: &AttrVec,659                _: Span,660                _: NodeId,661            ) -> Self::Result {662                walk_fn(self, fk)663            }664665            // (non-mut) `Visitor`-only methods666            $(667                fn visit_stmt(&mut self, s: &$lt Stmt) -> Self::Result {668                    walk_stmt(self, s)669                }670671                fn visit_nested_use_tree(&mut self, use_tree: &$lt UseTree, id: NodeId) -> Self::Result {672                    try_visit!(self.visit_id(id));673                    self.visit_use_tree(use_tree)674                }675            )?676677            // `MutVisitor`-only methods678            $(679                // Span visiting is no longer used, but we keep it for now,680                // in case it's needed for something like #127241.681                #[inline]682                fn visit_span(&mut self, _sp: &$mut Span) {683                    impl_visitable!(|&mut self: Span, visitor: &mut V, _extra: ()| {684                        visitor.visit_span(self)685                    });686                    // Do nothing.687                }688689                fn flat_map_foreign_item(&mut self, ni: Box<ForeignItem>) -> SmallVec<[Box<ForeignItem>; 1]> {690                    walk_flat_map_foreign_item(self, ni)691                }692693                fn flat_map_item(&mut self, i: Box<Item>) -> SmallVec<[Box<Item>; 1]> {694                    walk_flat_map_item(self, i)695                }696697                fn flat_map_field_def(&mut self, fd: FieldDef) -> SmallVec<[FieldDef; 1]> {698                    walk_flat_map_field_def(self, fd)699                }700701                fn flat_map_assoc_item(702                    &mut self,703                    i: Box<AssocItem>,704                    ctxt: AssocCtxt,705                ) -> SmallVec<[Box<AssocItem>; 1]> {706                    walk_flat_map_assoc_item(self, i, ctxt)707                }708709                fn flat_map_stmt(&mut self, s: Stmt) -> SmallVec<[Stmt; 1]> {710                    walk_flat_map_stmt(self, s)711                }712713                fn flat_map_arm(&mut self, arm: Arm) -> SmallVec<[Arm; 1]> {714                    walk_flat_map_arm(self, arm)715                }716717                fn filter_map_expr(&mut self, e: Box<Expr>) -> Option<Box<Expr>> {718                    walk_filter_map_expr(self, e)719                }720721                fn flat_map_variant(&mut self, v: Variant) -> SmallVec<[Variant; 1]> {722                    walk_flat_map_variant(self, v)723                }724725                fn flat_map_param(&mut self, param: Param) -> SmallVec<[Param; 1]> {726                    walk_flat_map_param(self, param)727                }728729                fn flat_map_generic_param(&mut self, param: GenericParam) -> SmallVec<[GenericParam; 1]> {730                    walk_flat_map_generic_param(self, param)731                }732733                fn flat_map_expr_field(&mut self, f: ExprField) -> SmallVec<[ExprField; 1]> {734                    walk_flat_map_expr_field(self, f)735                }736737                fn flat_map_where_predicate(738                    &mut self,739                    where_predicate: WherePredicate,740                ) -> SmallVec<[WherePredicate; 1]> {741                    walk_flat_map_where_predicate(self, where_predicate)742                }743744                fn flat_map_pat_field(&mut self, fp: PatField) -> SmallVec<[PatField; 1]> {745                    walk_flat_map_pat_field(self, fp)746                }747            )?748        }749750        pub trait WalkItemKind {751            type Ctxt;752            fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(753                &$($lt)? $($mut)? self,754                attrs: &AttrVec,755                span: Span,756                id: NodeId,757                visibility: &$($lt)? $($mut)? Visibility,758                ctxt: Self::Ctxt,759                vis: &mut V,760            ) -> V::Result;761        }762763        // This is only used by the MutVisitor. We include this symmetry here to make writing other764        // functions easier.765        $(${ignore($lt)}766            #[expect(unused, rustc::disallowed_pass_by_ref)]767            #[inline]768        )?769        fn visit_span<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, span: &$($lt)? $($mut)? Span) -> V::Result {770            $(${ignore($mut)} vis.visit_span(span))?;771            V::Result::output()772        }773774        $(impl_visitable!(|&$lt self: ThinVec<(UseTree, NodeId)>, vis: &mut V, _extra: ()| {775            for (nested_tree, nested_id) in self {776                try_visit!(vis.visit_nested_use_tree(nested_tree, *nested_id));777            }778            V::Result::output()779        });)?780        $(impl_visitable_list!(<$mut> ThinVec<(UseTree, NodeId)>,);)?781782        fn walk_item_inner<$($lt,)? K: WalkItemKind, V: $Visitor$(<$lt>)?>(783            visitor: &mut V,784            item: &$($mut)? $($lt)? Item<K>,785            ctxt: K::Ctxt,786        ) -> V::Result {787            let Item { attrs, id, kind, vis, span, tokens: _ } = item;788            visit_visitable!($($mut)? visitor, id, attrs, vis);789            try_visit!(kind.walk(attrs, *span, *id, vis, ctxt, visitor));790            visit_visitable!($($mut)? visitor, span);791            V::Result::output()792        }793794        // Do not implement `Walkable`/`MutWalkable` for *Item to avoid confusion.795        pub fn walk_item<$($lt,)? K: WalkItemKind<Ctxt = ()>, V: $Visitor$(<$lt>)?>(796            visitor: &mut V,797            item: &$($mut)? $($lt)? Item<K>,798        ) -> V::Result {799            walk_item_inner(visitor, item, ())800        }801802        // Do not implement `Walkable`/`MutWalkable` for *Item to avoid confusion.803        pub fn walk_assoc_item<$($lt,)? K: WalkItemKind<Ctxt = AssocCtxt>, V: $Visitor$(<$lt>)?>(804            visitor: &mut V,805            item: &$($mut)? $($lt)? Item<K>,806            ctxt: AssocCtxt,807        ) -> V::Result {808            walk_item_inner(visitor, item, ctxt)809        }810811        impl WalkItemKind for ItemKind {812            type Ctxt = ();813            fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(814                &$($lt)? $($mut)? self,815                attrs: &AttrVec,816                span: Span,817                id: NodeId,818                visibility: &$($lt)? $($mut)? Visibility,819                _ctxt: Self::Ctxt,820                vis: &mut V,821            ) -> V::Result {822                match self {823                    ItemKind::Fn(func) => {824                        let kind = FnKind::Fn(FnCtxt::Free, visibility, &$($mut)? *func);825                        try_visit!(vis.visit_fn(kind, attrs, span, id));826                    }827                    ItemKind::ExternCrate(orig_name, ident) =>828                        visit_visitable!($($mut)? vis, orig_name, ident),829                    ItemKind::Use(use_tree) =>830                        visit_visitable!($($mut)? vis, use_tree),831                    ItemKind::Static(item) =>832                        visit_visitable!($($mut)? vis, item),833                    ItemKind::ConstBlock(item) =>834                        visit_visitable!($($mut)? vis, item),835                    ItemKind::Const(item) =>836                        visit_visitable!($($mut)? vis, item),837                    ItemKind::Mod(safety, ident, mod_kind) =>838                        visit_visitable!($($mut)? vis, safety, ident, mod_kind),839                    ItemKind::ForeignMod(nm) =>840                        visit_visitable!($($mut)? vis, nm),841                    ItemKind::GlobalAsm(asm) =>842                        visit_visitable!($($mut)? vis, asm),843                    ItemKind::TyAlias(ty_alias) =>844                        visit_visitable!($($mut)? vis, ty_alias),845                    ItemKind::Enum(ident, generics, enum_definition) =>846                        visit_visitable!($($mut)? vis, ident, generics, enum_definition),847                    ItemKind::Struct(ident, generics, variant_data)848                    | ItemKind::Union(ident, generics, variant_data) =>849                        visit_visitable!($($mut)? vis, ident, generics, variant_data),850                    ItemKind::Impl(impl_) =>851                        visit_visitable!($($mut)? vis, impl_),852                    ItemKind::Trait(trait_) =>853                        visit_visitable!($($mut)? vis, trait_),854                    ItemKind::TraitAlias(box TraitAlias { constness, ident, generics, bounds}) => {855                        visit_visitable!($($mut)? vis, constness, ident, generics);856                        visit_visitable_with!($($mut)? vis, bounds, BoundKind::Bound)857                    }858                    ItemKind::MacCall(m) =>859                        visit_visitable!($($mut)? vis, m),860                    ItemKind::MacroDef(ident, def) =>861                        visit_visitable!($($mut)? vis, ident, def),862                    ItemKind::Delegation(delegation) =>863                        visit_visitable!($($mut)? vis, delegation),864                    ItemKind::DelegationMac(dm) =>865                        visit_visitable!($($mut)? vis, dm),866                }867                V::Result::output()868            }869        }870871        impl WalkItemKind for AssocItemKind {872            type Ctxt = AssocCtxt;873            fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(874                &$($lt)? $($mut)? self,875                attrs: &AttrVec,876                span: Span,877                id: NodeId,878                visibility: &$($lt)? $($mut)? Visibility,879                ctxt: Self::Ctxt,880                vis: &mut V,881            ) -> V::Result {882                match self {883                    AssocItemKind::Const(item) =>884                        visit_visitable!($($mut)? vis, item),885                    AssocItemKind::Fn(func) => {886                        let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), visibility, &$($mut)? *func);887                        try_visit!(vis.visit_fn(kind, attrs, span, id))888                    }889                    AssocItemKind::Type(alias) =>890                        visit_visitable!($($mut)? vis, alias),891                    AssocItemKind::MacCall(mac) =>892                        visit_visitable!($($mut)? vis, mac),893                    AssocItemKind::Delegation(delegation) =>894                        visit_visitable!($($mut)? vis, delegation),895                    AssocItemKind::DelegationMac(dm) =>896                        visit_visitable!($($mut)? vis, dm),897                }898                V::Result::output()899            }900        }901902        impl WalkItemKind for ForeignItemKind {903            type Ctxt = ();904            fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(905                &$($lt)? $($mut)? self,906                attrs: &AttrVec,907                span: Span,908                id: NodeId,909                visibility: &$($lt)? $($mut)? Visibility,910                _ctxt: Self::Ctxt,911                vis: &mut V,912            ) -> V::Result {913                match self {914                    ForeignItemKind::Static(item) =>915                        visit_visitable!($($mut)? vis, item),916                    ForeignItemKind::Fn(func) => {917                        let kind = FnKind::Fn(FnCtxt::Foreign, visibility, &$($mut)?*func);918                        try_visit!(vis.visit_fn(kind, attrs, span, id))919                    }920                    ForeignItemKind::TyAlias(alias) =>921                        visit_visitable!($($mut)? vis, alias),922                    ForeignItemKind::MacCall(mac) =>923                        visit_visitable!($($mut)? vis, mac),924                }925                V::Result::output()926            }927        }928929        pub fn walk_fn<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, kind: FnKind<$($lt)? $(${ignore($mut)} '_)?>) -> V::Result {930            match kind {931                FnKind::Fn(932                    _ctxt,933                    // Visibility is visited as a part of the item.934                    _vis,935                    Fn { defaultness, ident, sig, generics, contract, body, define_opaque, eii_impls },936                ) => {937                    let FnSig { header, decl, span } = sig;938                    visit_visitable!($($mut)? vis,939                        defaultness, ident, header, generics, decl,940                        contract, body, span, define_opaque, eii_impls941                    );942                }943                FnKind::Closure(binder, coroutine_kind, decl, body) =>944                    visit_visitable!($($mut)? vis, binder, coroutine_kind, decl, body),945            }946            V::Result::output()947        }948949        impl_walkable!(|&$($mut)? $($lt)? self: Impl, vis: &mut V| {950            let Impl { generics, of_trait, self_ty, items, constness: _ } = self;951            try_visit!(vis.visit_generics(generics));952            if let Some(box of_trait) = of_trait {953                let TraitImplHeader { defaultness, safety, polarity, trait_ref } = of_trait;954                visit_visitable!($($mut)? vis, defaultness, safety, polarity, trait_ref);955            }956            try_visit!(vis.visit_ty(self_ty));957            visit_visitable_with!($($mut)? vis, items, AssocCtxt::Impl { of_trait: of_trait.is_some() });958            V::Result::output()959        });960961        // Special case to call `visit_method_receiver_expr`.962        impl_walkable!(|&$($mut)? $($lt)? self: MethodCall, vis: &mut V| {963            let MethodCall { seg, receiver, args, span } = self;964            try_visit!(vis.visit_method_receiver_expr(receiver));965            visit_visitable!($($mut)? vis, seg, args, span);966            V::Result::output()967        });968969        impl_walkable!(|&$($mut)? $($lt)? self: Expr, vis: &mut V| {970            let Expr { id, kind, span, attrs, tokens: _ } = self;971            visit_visitable!($($mut)? vis, id, attrs);972            match kind {973                ExprKind::Array(exprs) =>974                    visit_visitable!($($mut)? vis, exprs),975                ExprKind::ConstBlock(anon_const) =>976                    visit_visitable!($($mut)? vis, anon_const),977                ExprKind::Repeat(element, count) =>978                    visit_visitable!($($mut)? vis, element, count),979                ExprKind::Struct(se) =>980                    visit_visitable!($($mut)? vis, se),981                ExprKind::Tup(exprs) =>982                    visit_visitable!($($mut)? vis, exprs),983                ExprKind::Call(callee_expression, arguments) =>984                    visit_visitable!($($mut)? vis, callee_expression, arguments),985                ExprKind::MethodCall(mc) =>986                    visit_visitable!($($mut)? vis, mc),987                ExprKind::Binary(op, lhs, rhs) =>988                    visit_visitable!($($mut)? vis, op, lhs, rhs),989                ExprKind::AddrOf(kind, mutbl, subexpression) =>990                    visit_visitable!($($mut)? vis, kind, mutbl, subexpression),991                ExprKind::Unary(op, subexpression) =>992                    visit_visitable!($($mut)? vis, op, subexpression),993                ExprKind::Cast(subexpression, typ) | ExprKind::Type(subexpression, typ) =>994                    visit_visitable!($($mut)? vis, subexpression, typ),995                ExprKind::Let(pat, expr, span, _recovered) =>996                    visit_visitable!($($mut)? vis, pat, expr, span),997                ExprKind::If(head_expression, if_block, optional_else) =>998                    visit_visitable!($($mut)? vis, head_expression, if_block, optional_else),999                ExprKind::While(subexpression, block, opt_label) =>1000                    visit_visitable!($($mut)? vis, subexpression, block, opt_label),1001                ExprKind::ForLoop { pat, iter, body, label, kind } =>1002                    visit_visitable!($($mut)? vis, pat, iter, body, label, kind),1003                ExprKind::Loop(block, opt_label, span) =>1004                    visit_visitable!($($mut)? vis, block, opt_label, span),1005                ExprKind::Match(subexpression, arms, kind) =>1006                    visit_visitable!($($mut)? vis, subexpression, arms, kind),1007                ExprKind::Closure(box Closure {1008                    binder,1009                    capture_clause,1010                    coroutine_kind,1011                    constness,1012                    movability,1013                    fn_decl,1014                    body,1015                    fn_decl_span,1016                    fn_arg_span,1017                }) => {1018                    visit_visitable!($($mut)? vis, constness, movability, capture_clause);1019                    let kind = FnKind::Closure(binder, coroutine_kind, fn_decl, body);1020                    try_visit!(vis.visit_fn(kind, attrs, *span, *id));1021                    visit_visitable!($($mut)? vis, fn_decl_span, fn_arg_span);1022                }1023                ExprKind::Block(block, opt_label) =>1024                    visit_visitable!($($mut)? vis, block, opt_label),1025                ExprKind::Gen(capt, body, kind, decl_span) =>1026                    visit_visitable!($($mut)? vis, capt, body, kind, decl_span),1027                ExprKind::Await(expr, span) | ExprKind::Use(expr, span) =>1028                    visit_visitable!($($mut)? vis, expr, span),1029                ExprKind::Assign(lhs, rhs, span) =>1030                    visit_visitable!($($mut)? vis, lhs, rhs, span),1031                ExprKind::AssignOp(op, lhs, rhs) =>1032                    visit_visitable!($($mut)? vis, op, lhs, rhs),1033                ExprKind::Field(subexpression, ident) =>1034                    visit_visitable!($($mut)? vis, subexpression, ident),1035                ExprKind::Index(main_expression, index_expression, span) =>1036                    visit_visitable!($($mut)? vis, main_expression, index_expression, span),1037                ExprKind::Range(start, end, limit) =>1038                    visit_visitable!($($mut)? vis, start, end, limit),1039                ExprKind::Underscore => {}1040                ExprKind::Path(maybe_qself, path) =>1041                    visit_visitable!($($mut)? vis, maybe_qself, path),1042                ExprKind::Break(opt_label, opt_expr) =>1043                    visit_visitable!($($mut)? vis, opt_label, opt_expr),1044                ExprKind::Continue(opt_label) =>1045                    visit_visitable!($($mut)? vis, opt_label),1046                ExprKind::Ret(optional_expression) | ExprKind::Yeet(optional_expression) =>1047                    visit_visitable!($($mut)? vis, optional_expression),1048                ExprKind::Become(expr) =>1049                    visit_visitable!($($mut)? vis, expr),1050                ExprKind::MacCall(mac) =>1051                    visit_visitable!($($mut)? vis, mac),1052                ExprKind::Paren(subexpression) =>1053                    visit_visitable!($($mut)? vis, subexpression),1054                ExprKind::InlineAsm(asm) =>1055                    visit_visitable!($($mut)? vis, asm),1056                ExprKind::FormatArgs(f) =>1057                    visit_visitable!($($mut)? vis, f),1058                ExprKind::OffsetOf(container, fields) =>1059                    visit_visitable!($($mut)? vis, container, fields),1060                ExprKind::Yield(kind) =>1061                    visit_visitable!($($mut)? vis, kind),1062                ExprKind::Try(subexpression) =>1063                    visit_visitable!($($mut)? vis, subexpression),1064                ExprKind::TryBlock(body, optional_type) =>1065                    visit_visitable!($($mut)? vis, body, optional_type),1066                ExprKind::Lit(token) =>1067                    visit_visitable!($($mut)? vis, token),1068                ExprKind::IncludedBytes(bytes) =>1069                    visit_visitable!($($mut)? vis, bytes),1070                ExprKind::UnsafeBinderCast(kind, expr, ty) =>1071                    visit_visitable!($($mut)? vis, kind, expr, ty),1072                ExprKind::Err(_guar) => {}1073                ExprKind::Dummy => {}1074            }10751076            visit_span(vis, span)1077        });10781079        define_named_walk!($(($mut))? $Visitor$(<$lt>)?1080            pub fn walk_anon_const(AnonConst);1081            pub fn walk_arm(Arm);1082            //pub fn walk_assoc_item(AssocItem, _ctxt: AssocCtxt);1083            pub fn walk_assoc_item_constraint(AssocItemConstraint);1084            pub fn walk_attribute(Attribute);1085            pub fn walk_block(Block);1086            //pub fn walk_nested_use_tree((UseTree, NodeId));1087            pub fn walk_capture_by(CaptureBy);1088            pub fn walk_closure_binder(ClosureBinder);1089            pub fn walk_contract(FnContract);1090            pub fn walk_coroutine_kind(CoroutineKind);1091            pub fn walk_crate(Crate);1092            pub fn walk_expr(Expr);1093            pub fn walk_expr_field(ExprField);1094            pub fn walk_field_def(FieldDef);1095            pub fn walk_fn_decl(FnDecl);1096            pub fn walk_fn_header(FnHeader);1097            pub fn walk_fn_ret_ty(FnRetTy);1098            //pub fn walk_foreign_item(ForeignItem);1099            pub fn walk_foreign_mod(ForeignMod);1100            pub fn walk_format_args(FormatArgs);1101            pub fn walk_generic_arg(GenericArg);1102            pub fn walk_generic_args(GenericArgs);1103            pub fn walk_generic_param(GenericParam);1104            pub fn walk_generics(Generics);1105            pub fn walk_inline_asm(InlineAsm);1106            pub fn walk_inline_asm_sym(InlineAsmSym);1107            //pub fn walk_item(Item);1108            pub fn walk_label(Label);1109            pub fn walk_lifetime(Lifetime);1110            pub fn walk_local(Local);1111            pub fn walk_mac(MacCall);1112            pub fn walk_macro_def(MacroDef);1113            pub fn walk_param_bound(GenericBound);1114            pub fn walk_param(Param);1115            pub fn walk_pat_field(PatField);1116            pub fn walk_path(Path);1117            pub fn walk_path_segment(PathSegment);1118            pub fn walk_pat(Pat);1119            pub fn walk_poly_trait_ref(PolyTraitRef);1120            pub fn walk_precise_capturing_arg(PreciseCapturingArg);1121            pub fn walk_qself(QSelf);1122            pub fn walk_impl_restriction(ImplRestriction);1123            pub fn walk_trait_ref(TraitRef);1124            pub fn walk_ty_pat(TyPat);1125            pub fn walk_ty(Ty);1126            pub fn walk_use_tree(UseTree);1127            pub fn walk_variant_data(VariantData);1128            pub fn walk_variant(Variant);1129            pub fn walk_vis(Visibility);1130            pub fn walk_where_predicate_kind(WherePredicateKind);1131            pub fn walk_where_predicate(WherePredicate);1132        );1133    };1134}11351136common_visitor_and_walkers!(Visitor<'a>);11371138macro_rules! generate_list_visit_fns {1139    ($($name:ident, $Ty:ty, $visit_fn:ident$(, $param:ident: $ParamTy:ty)*;)+) => {1140        $(1141            #[allow(unused_parens)]1142            impl<'a, V: Visitor<'a>> Visitable<'a, V> for ThinVec<$Ty> {1143                type Extra = ($($ParamTy),*);11441145                #[inline]1146                fn visit(1147                    &'a self,1148                    visitor: &mut V,1149                    ($($param),*): Self::Extra,1150                ) -> V::Result {1151                    $name(visitor, self $(, $param)*)1152                }1153            }11541155            fn $name<'a, V: Visitor<'a>>(1156                vis: &mut V,1157                values: &'a ThinVec<$Ty>,1158                $(1159                    $param: $ParamTy,1160                )*1161            ) -> V::Result {1162                walk_list!(vis, $visit_fn, values$(,$param)*);1163                V::Result::output()1164            }1165        )+1166    }1167}11681169generate_list_visit_fns! {1170    visit_items, Box<Item>, visit_item;1171    visit_foreign_items, Box<ForeignItem>, visit_foreign_item;1172    visit_generic_params, GenericParam, visit_generic_param;1173    visit_stmts, Stmt, visit_stmt;1174    visit_exprs, Box<Expr>, visit_expr;1175    visit_expr_fields, ExprField, visit_expr_field;1176    visit_pat_fields, PatField, visit_pat_field;1177    visit_variants, Variant, visit_variant;1178    visit_assoc_items, Box<AssocItem>, visit_assoc_item, ctxt: AssocCtxt;1179    visit_where_predicates, WherePredicate, visit_where_predicate;1180    visit_params, Param, visit_param;1181    visit_field_defs, FieldDef, visit_field_def;1182    visit_arms, Arm, visit_arm;1183}11841185pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V::Result {1186    let Stmt { id, kind, span: _ } = statement;1187    try_visit!(visitor.visit_id(*id));1188    match kind {1189        StmtKind::Let(local) => try_visit!(visitor.visit_local(local)),1190        StmtKind::Item(item) => try_visit!(visitor.visit_item(item)),1191        StmtKind::Expr(expr) | StmtKind::Semi(expr) => try_visit!(visitor.visit_expr(expr)),1192        StmtKind::Empty => {}1193        StmtKind::MacCall(mac) => {1194            let MacCallStmt { mac, attrs, style: _, tokens: _ } = &**mac;1195            walk_list!(visitor, visit_attribute, attrs);1196            try_visit!(visitor.visit_mac_call(mac));1197        }1198    }1199    V::Result::output()1200}

Code quality findings 6

Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
impl<'a, V: Visitor<'a>, T> Visitable<'a, V> for [T]
Info: Wildcard imports (`use some::path::*;`) can obscure the origin of names and lead to conflicts. Prefer importing specific items explicitly.
info maintainability wildcard-import
use crate::ast::*;
Info: Usage of `#[allow(...)]` suppresses compiler lints. Ensure the allowance is justified, well-scoped, and ideally temporary. Overuse can hide potential issues.
info maintainability allow-lint
#[allow(unused_parens, non_local_definitions)]
Info: Usage of `#[allow(...)]` suppresses compiler lints. Ensure the allowance is justified, well-scoped, and ideally temporary. Overuse can hide potential issues.
info maintainability allow-lint
#[allow(unused_parens, non_local_definitions)]
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match self {
Info: Usage of `#[allow(...)]` suppresses compiler lints. Ensure the allowance is justified, well-scoped, and ideally temporary. Overuse can hide potential issues.
info maintainability allow-lint
#[allow(unused_parens)]

Get this view in your editor

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