diff options
Diffstat (limited to 'compiler/rustc_ast/src/visit.rs')
| -rw-r--r-- | compiler/rustc_ast/src/visit.rs | 1873 |
1 files changed, 1060 insertions, 813 deletions
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index d2f22b04a67..d0c2b2bf68b 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -15,11 +15,13 @@ pub use rustc_ast_ir::visit::VisitorResult; pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list}; +use rustc_span::source_map::Spanned; use rustc_span::{Ident, Span}; use thin_vec::ThinVec; use crate::ast::*; use crate::ptr::P; +use crate::tokenstream::DelimSpan; #[derive(Copy, Clone, Debug, PartialEq)] pub enum AssocCtxt { @@ -64,45 +66,6 @@ impl BoundKind { } #[derive(Copy, Clone, Debug)] -pub enum FnKind<'a> { - /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`. - Fn(FnCtxt, &'a Visibility, &'a Fn), - - /// E.g., `|x, y| body`. - Closure(&'a ClosureBinder, &'a Option<CoroutineKind>, &'a FnDecl, &'a Expr), -} - -impl<'a> FnKind<'a> { - pub fn header(&self) -> Option<&'a FnHeader> { - match *self { - FnKind::Fn(_, _, Fn { sig, .. }) => Some(&sig.header), - FnKind::Closure(..) => None, - } - } - - pub fn ident(&self) -> Option<&Ident> { - match self { - FnKind::Fn(_, _, Fn { ident, .. }) => Some(ident), - _ => None, - } - } - - pub fn decl(&self) -> &'a FnDecl { - match self { - FnKind::Fn(_, _, Fn { sig, .. }) => &sig.decl, - FnKind::Closure(_, _, decl, _) => decl, - } - } - - pub fn ctxt(&self) -> Option<FnCtxt> { - match self { - FnKind::Fn(ctxt, ..) => Some(*ctxt), - FnKind::Closure(..) => None, - } - } -} - -#[derive(Copy, Clone, Debug)] pub enum LifetimeCtxt { /// Appears in a reference type. Ref, @@ -112,206 +75,405 @@ pub enum LifetimeCtxt { GenericArg, } -/// Each method of the `Visitor` trait is a hook to be potentially -/// overridden. Each method's default implementation recursively visits -/// the substructure of the input via the corresponding `walk` method; -/// e.g., the `visit_item` method by default calls `visit::walk_item`. -/// -/// If you want to ensure that your code handles every variant -/// explicitly, you need to override each method. (And you also need -/// to monitor future changes to `Visitor` in case a new method with a -/// new default implementation gets introduced.) -/// -/// Every `walk_*` method uses deconstruction to access fields of structs and -/// enums. This will result in a compile error if a field is added, which makes -/// it more likely the appropriate visit call will be added for it. -pub trait Visitor<'ast>: Sized { - /// The result type of the `visit_*` methods. Can be either `()`, - /// or `ControlFlow<T>`. - type Result: VisitorResult = (); - - fn visit_ident(&mut self, _ident: &'ast Ident) -> Self::Result { - Self::Result::output() - } - fn visit_foreign_mod(&mut self, nm: &'ast ForeignMod) -> Self::Result { - walk_foreign_mod(self, nm) - } - fn visit_foreign_item(&mut self, i: &'ast ForeignItem) -> Self::Result { - walk_item(self, i) - } - fn visit_item(&mut self, i: &'ast Item) -> Self::Result { - walk_item(self, i) - } - fn visit_local(&mut self, l: &'ast Local) -> Self::Result { - walk_local(self, l) - } - fn visit_block(&mut self, b: &'ast Block) -> Self::Result { - walk_block(self, b) - } - fn visit_stmt(&mut self, s: &'ast Stmt) -> Self::Result { - walk_stmt(self, s) - } - fn visit_param(&mut self, param: &'ast Param) -> Self::Result { - walk_param(self, param) - } - fn visit_arm(&mut self, a: &'ast Arm) -> Self::Result { - walk_arm(self, a) - } - fn visit_pat(&mut self, p: &'ast Pat) -> Self::Result { - walk_pat(self, p) - } - fn visit_anon_const(&mut self, c: &'ast AnonConst) -> Self::Result { - walk_anon_const(self, c) - } - fn visit_expr(&mut self, ex: &'ast Expr) -> Self::Result { - walk_expr(self, ex) - } - /// This method is a hack to workaround unstable of `stmt_expr_attributes`. - /// It can be removed once that feature is stabilized. - fn visit_method_receiver_expr(&mut self, ex: &'ast Expr) -> Self::Result { - self.visit_expr(ex) - } - fn visit_ty(&mut self, t: &'ast Ty) -> Self::Result { - walk_ty(self, t) - } - fn visit_ty_pat(&mut self, t: &'ast TyPat) -> Self::Result { - walk_ty_pat(self, t) - } - fn visit_generic_param(&mut self, param: &'ast GenericParam) -> Self::Result { - walk_generic_param(self, param) - } - fn visit_generics(&mut self, g: &'ast Generics) -> Self::Result { - walk_generics(self, g) - } - fn visit_closure_binder(&mut self, b: &'ast ClosureBinder) -> Self::Result { - walk_closure_binder(self, b) - } - fn visit_contract(&mut self, c: &'ast FnContract) -> Self::Result { - walk_contract(self, c) - } - fn visit_where_predicate(&mut self, p: &'ast WherePredicate) -> Self::Result { - walk_where_predicate(self, p) - } - fn visit_where_predicate_kind(&mut self, k: &'ast WherePredicateKind) -> Self::Result { - walk_where_predicate_kind(self, k) - } - fn visit_fn(&mut self, fk: FnKind<'ast>, _: Span, _: NodeId) -> Self::Result { - walk_fn(self, fk) - } - fn visit_assoc_item(&mut self, i: &'ast AssocItem, ctxt: AssocCtxt) -> Self::Result { - walk_assoc_item(self, i, ctxt) - } - fn visit_trait_ref(&mut self, t: &'ast TraitRef) -> Self::Result { - walk_trait_ref(self, t) - } - fn visit_param_bound(&mut self, bounds: &'ast GenericBound, _ctxt: BoundKind) -> Self::Result { - walk_param_bound(self, bounds) - } - fn visit_precise_capturing_arg(&mut self, arg: &'ast PreciseCapturingArg) -> Self::Result { - walk_precise_capturing_arg(self, arg) - } - fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef) -> Self::Result { - walk_poly_trait_ref(self, t) - } - fn visit_variant_data(&mut self, s: &'ast VariantData) -> Self::Result { - walk_variant_data(self, s) - } - fn visit_field_def(&mut self, s: &'ast FieldDef) -> Self::Result { - walk_field_def(self, s) - } - fn visit_variant(&mut self, v: &'ast Variant) -> Self::Result { - walk_variant(self, v) - } - fn visit_variant_discr(&mut self, discr: &'ast AnonConst) -> Self::Result { - self.visit_anon_const(discr) - } - fn visit_label(&mut self, label: &'ast Label) -> Self::Result { - walk_label(self, label) - } - fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, _: LifetimeCtxt) -> Self::Result { - walk_lifetime(self, lifetime) - } - fn visit_mac_call(&mut self, mac: &'ast MacCall) -> Self::Result { - walk_mac(self, mac) - } - fn visit_id(&mut self, _id: NodeId) -> Self::Result { - Self::Result::output() - } - fn visit_macro_def(&mut self, _mac: &'ast MacroDef) -> Self::Result { - Self::Result::output() - } - fn visit_path(&mut self, path: &'ast Path) -> Self::Result { - walk_path(self, path) - } - fn visit_use_tree(&mut self, use_tree: &'ast UseTree) -> Self::Result { - walk_use_tree(self, use_tree) - } - fn visit_nested_use_tree(&mut self, use_tree: &'ast UseTree, id: NodeId) -> Self::Result { - try_visit!(self.visit_id(id)); - self.visit_use_tree(use_tree) - } - fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) -> Self::Result { - walk_path_segment(self, path_segment) - } - fn visit_generic_args(&mut self, generic_args: &'ast GenericArgs) -> Self::Result { - walk_generic_args(self, generic_args) - } - fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) -> Self::Result { - walk_generic_arg(self, generic_arg) - } - fn visit_assoc_item_constraint( - &mut self, - constraint: &'ast AssocItemConstraint, - ) -> Self::Result { - walk_assoc_item_constraint(self, constraint) - } - fn visit_attribute(&mut self, attr: &'ast Attribute) -> Self::Result { - walk_attribute(self, attr) - } - fn visit_vis(&mut self, vis: &'ast Visibility) -> Self::Result { - walk_vis(self, vis) - } - fn visit_fn_ret_ty(&mut self, ret_ty: &'ast FnRetTy) -> Self::Result { - walk_fn_ret_ty(self, ret_ty) - } - fn visit_fn_header(&mut self, header: &'ast FnHeader) -> Self::Result { - walk_fn_header(self, header) - } - fn visit_expr_field(&mut self, f: &'ast ExprField) -> Self::Result { - walk_expr_field(self, f) - } - fn visit_pat_field(&mut self, fp: &'ast PatField) -> Self::Result { - walk_pat_field(self, fp) - } - fn visit_crate(&mut self, krate: &'ast Crate) -> Self::Result { - walk_crate(self, krate) - } - fn visit_inline_asm(&mut self, asm: &'ast InlineAsm) -> Self::Result { - walk_inline_asm(self, asm) - } - fn visit_format_args(&mut self, fmt: &'ast FormatArgs) -> Self::Result { - walk_format_args(self, fmt) - } - fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) -> Self::Result { - walk_inline_asm_sym(self, sym) - } - fn visit_capture_by(&mut self, _capture_by: &'ast CaptureBy) -> Self::Result { - Self::Result::output() - } - fn visit_coroutine_kind(&mut self, coroutine_kind: &'ast CoroutineKind) -> Self::Result { - walk_coroutine_kind(self, coroutine_kind) - } - fn visit_fn_decl(&mut self, fn_decl: &'ast FnDecl) -> Self::Result { - walk_fn_decl(self, fn_decl) - } - fn visit_qself(&mut self, qs: &'ast Option<P<QSelf>>) -> Self::Result { - walk_qself(self, qs) - } -} - #[macro_export] macro_rules! common_visitor_and_walkers { ($(($mut: ident))? $Visitor:ident$(<$lt:lifetime>)?) => { + $(${ignore($lt)} + #[derive(Copy, Clone)] + )? + #[derive(Debug)] + pub enum FnKind<'a> { + /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`. + Fn(FnCtxt, &'a $($mut)? Visibility, &'a $($mut)? Fn), + + /// E.g., `|x, y| body`. + Closure(&'a $($mut)? ClosureBinder, &'a $($mut)? Option<CoroutineKind>, &'a $($mut)? P<FnDecl>, &'a $($mut)? P<Expr>), + } + + impl<'a> FnKind<'a> { + pub fn header(&'a $($mut)? self) -> Option<&'a $($mut)? FnHeader> { + match *self { + FnKind::Fn(_, _, Fn { sig, .. }) => Some(&$($mut)? sig.header), + FnKind::Closure(..) => None, + } + } + + pub fn ident(&'a $($mut)? self) -> Option<&'a $($mut)? Ident> { + match self { + FnKind::Fn(_, _, Fn { ident, .. }) => Some(ident), + _ => None, + } + } + + pub fn decl(&'a $($mut)? self) -> &'a $($mut)? FnDecl { + match self { + FnKind::Fn(_, _, Fn { sig, .. }) => &$($mut)? sig.decl, + FnKind::Closure(_, _, decl, _) => decl, + } + } + + pub fn ctxt(&self) -> Option<FnCtxt> { + match self { + FnKind::Fn(ctxt, ..) => Some(*ctxt), + FnKind::Closure(..) => None, + } + } + } + + /// Each method of this trait is a hook to be potentially + /// overridden. Each method's default implementation recursively visits + /// the substructure of the input via the corresponding `walk` method; + #[doc = concat!(" e.g., the `visit_item` method by default calls `visit"$(, "_", stringify!($mut))?, "::walk_item`.")] + /// + /// If you want to ensure that your code handles every variant + /// explicitly, you need to override each method. (And you also need + /// to monitor future changes to this trait in case a new method with a + /// new default implementation gets introduced.) + /// + /// Every `walk_*` method uses deconstruction to access fields of structs and + /// enums. This will result in a compile error if a field is added, which makes + /// it more likely the appropriate visit call will be added for it. + pub trait $Visitor<$($lt)?> : Sized $(${ignore($mut)} + MutVisitorResult<Result = ()>)? { + $( + ${ignore($lt)} + /// The result type of the `visit_*` methods. Can be either `()`, + /// or `ControlFlow<T>`. + type Result: VisitorResult = (); + )? + + // Methods in this trait have one of three forms, with the last two forms + // only occuring on `MutVisitor`: + // + // fn visit_t(&mut self, t: &mut T); // common + // fn flat_map_t(&mut self, t: T) -> SmallVec<[T; 1]>; // rare + // fn filter_map_t(&mut self, t: T) -> Option<T>; // rarest + // + // When writing these methods, it is better to use destructuring like this: + // + // fn visit_abc(&mut self, ABC { a, b, c: _ }: &mut ABC) { + // visit_a(a); + // visit_b(b); + // } + // + // than to use field access like this: + // + // fn visit_abc(&mut self, abc: &mut ABC) { + // visit_a(&mut abc.a); + // visit_b(&mut abc.b); + // // ignore abc.c + // } + // + // As well as being more concise, the former is explicit about which fields + // are skipped. Furthermore, if a new field is added, the destructuring + // version will cause a compile error, which is good. In comparison, the + // field access version will continue working and it would be easy to + // forget to add handling for it. + fn visit_ident(&mut self, Ident { name: _, span }: &$($lt)? $($mut)? Ident) -> Self::Result { + visit_span(self, span) + } + + fn visit_foreign_mod(&mut self, nm: &$($lt)? $($mut)? ForeignMod) -> Self::Result { + walk_foreign_mod(self, nm) + } + + fn visit_foreign_item(&mut self, i: &$($lt)? $($mut)? ForeignItem) -> Self::Result { + walk_item(self, i) + } + + fn visit_item(&mut self, i: &$($lt)? $($mut)? Item) -> Self::Result { + walk_item(self, i) + } + + fn visit_local(&mut self, l: &$($lt)? $($mut)? Local) -> Self::Result { + walk_local(self, l) + } + + fn visit_block(&mut self, b: &$($lt)? $($mut)? Block) -> Self::Result { + walk_block(self, b) + } + + fn visit_param(&mut self, param: &$($lt)? $($mut)? Param) -> Self::Result { + walk_param(self, param) + } + + fn visit_arm(&mut self, a: &$($lt)? $($mut)? Arm) -> Self::Result { + walk_arm(self, a) + } + + fn visit_pat(&mut self, p: &$($lt)? $($mut)? Pat) -> Self::Result { + walk_pat(self, p) + } + + fn visit_anon_const(&mut self, c: &$($lt)? $($mut)? AnonConst) -> Self::Result { + walk_anon_const(self, c) + } + + fn visit_expr(&mut self, ex: &$($lt)? $($mut)? Expr) -> Self::Result { + walk_expr(self, ex) + } + + /// This method is a hack to workaround unstable of `stmt_expr_attributes`. + /// It can be removed once that feature is stabilized. + fn visit_method_receiver_expr(&mut self, ex: &$($lt)? $($mut)? Expr) -> Self::Result { + self.visit_expr(ex) + } + + fn visit_ty(&mut self, t: &$($lt)? $($mut)? Ty) -> Self::Result { + walk_ty(self, t) + } + + fn visit_ty_pat(&mut self, t: &$($lt)? $($mut)? TyPat) -> Self::Result { + walk_ty_pat(self, t) + } + + fn visit_generic_param(&mut self, param: &$($lt)? $($mut)? GenericParam) -> Self::Result { + walk_generic_param(self, param) + } + + fn visit_generics(&mut self, g: &$($lt)? $($mut)? Generics) -> Self::Result { + walk_generics(self, g) + } + fn visit_closure_binder(&mut self, b: &$($lt)? $($mut)? ClosureBinder) -> Self::Result { + walk_closure_binder(self, b) + } + fn visit_contract(&mut self, c: &$($lt)? $($mut)? FnContract) -> Self::Result { + walk_contract(self, c) + } + + fn visit_where_predicate(&mut self, p: &$($lt)? $($mut)? WherePredicate) -> Self::Result { + walk_where_predicate(self, p) + } + + fn visit_where_predicate_kind(&mut self, k: &$($lt)? $($mut)? WherePredicateKind) -> Self::Result { + walk_where_predicate_kind(self, k) + } + + // for `MutVisitor`: `Span` and `NodeId` are mutated at the caller site. + fn visit_fn( + &mut self, + fk: FnKind<$($lt)? $(${ignore($mut)} '_)?>, + _: Span, + _: NodeId + ) -> Self::Result { + walk_fn(self, fk) + } + + fn visit_assoc_item(&mut self, i: &$($lt)? $($mut)? AssocItem, ctxt: AssocCtxt) -> Self::Result { + walk_assoc_item(self, i, ctxt) + } + + fn visit_trait_ref(&mut self, t: &$($lt)? $($mut)? TraitRef) -> Self::Result { + walk_trait_ref(self, t) + } + + fn visit_param_bound(&mut self, bounds: &$($lt)? $($mut)? GenericBound, _ctxt: BoundKind) -> Self::Result { + walk_param_bound(self, bounds) + } + + fn visit_precise_capturing_arg(&mut self, arg: &$($lt)? $($mut)? PreciseCapturingArg) -> Self::Result { + walk_precise_capturing_arg(self, arg) + } + + fn visit_poly_trait_ref(&mut self, t: &$($lt)? $($mut)? PolyTraitRef) -> Self::Result { + walk_poly_trait_ref(self, t) + } + + fn visit_variant_data(&mut self, s: &$($lt)? $($mut)? VariantData) -> Self::Result { + walk_variant_data(self, s) + } + + fn visit_field_def(&mut self, s: &$($lt)? $($mut)? FieldDef) -> Self::Result { + walk_field_def(self, s) + } + + fn visit_variant(&mut self, v: &$($lt)? $($mut)? Variant) -> Self::Result { + walk_variant(self, v) + } + + fn visit_label(&mut self, label: &$($lt)? $($mut)? Label) -> Self::Result { + walk_label(self, label) + } + + fn visit_lifetime(&mut self, lifetime: &$($lt)? $($mut)? Lifetime, $(${ignore($lt)} _: LifetimeCtxt )?) -> Self::Result { + walk_lifetime(self, lifetime) + } + + fn visit_mac_call(&mut self, mac: &$($lt)? $($mut)? MacCall) -> Self::Result { + walk_mac(self, mac) + } + + fn visit_id(&mut self, _id: $(&$mut)? NodeId) -> Self::Result { + Self::Result::output() + } + + fn visit_macro_def(&mut self, macro_def: &$($lt)? $($mut)? MacroDef) -> Self::Result { + walk_macro_def(self, macro_def) + } + + fn visit_path(&mut self, path: &$($lt)? $($mut)? Path) -> Self::Result { + walk_path(self, path) + } + + fn visit_use_tree(&mut self, use_tree: &$($lt)? $($mut)? UseTree) -> Self::Result { + walk_use_tree(self, use_tree) + } + + fn visit_path_segment(&mut self, path_segment: &$($lt)? $($mut)? PathSegment) -> Self::Result { + walk_path_segment(self, path_segment) + } + + fn visit_generic_args(&mut self, generic_args: &$($lt)? $($mut)? GenericArgs) -> Self::Result { + walk_generic_args(self, generic_args) + } + + fn visit_generic_arg(&mut self, generic_arg: &$($lt)? $($mut)? GenericArg) -> Self::Result { + walk_generic_arg(self, generic_arg) + } + + fn visit_assoc_item_constraint( + &mut self, + constraint: &$($lt)? $($mut)? AssocItemConstraint, + ) -> Self::Result { + walk_assoc_item_constraint(self, constraint) + } + + fn visit_attribute(&mut self, attr: &$($lt)? $($mut)? Attribute) -> Self::Result { + walk_attribute(self, attr) + } + + fn visit_vis(&mut self, vis: &$($lt)? $($mut)? Visibility) -> Self::Result { + walk_vis(self, vis) + } + + fn visit_fn_ret_ty(&mut self, ret_ty: &$($lt)? $($mut)? FnRetTy) -> Self::Result { + walk_fn_ret_ty(self, ret_ty) + } + + fn visit_fn_header(&mut self, header: &$($lt)? $($mut)? FnHeader) -> Self::Result { + walk_fn_header(self, header) + } + + fn visit_expr_field(&mut self, f: &$($lt)? $($mut)? ExprField) -> Self::Result { + walk_expr_field(self, f) + } + + fn visit_pat_field(&mut self, fp: &$($lt)? $($mut)? PatField) -> Self::Result { + walk_pat_field(self, fp) + } + + fn visit_crate(&mut self, krate: &$($lt)? $($mut)? Crate) -> Self::Result { + walk_crate(self, krate) + } + + fn visit_inline_asm(&mut self, asm: &$($lt)? $($mut)? InlineAsm) -> Self::Result { + walk_inline_asm(self, asm) + } + + fn visit_format_args(&mut self, fmt: &$($lt)? $($mut)? FormatArgs) -> Self::Result { + walk_format_args(self, fmt) + } + + fn visit_inline_asm_sym(&mut self, sym: &$($lt)? $($mut)? InlineAsmSym) -> Self::Result { + walk_inline_asm_sym(self, sym) + } + + fn visit_capture_by(&mut self, capture_by: &$($lt)? $($mut)? CaptureBy) -> Self::Result { + walk_capture_by(self, capture_by) + } + + fn visit_coroutine_kind(&mut self, coroutine_kind: &$($lt)? $($mut)? CoroutineKind) -> Self::Result { + walk_coroutine_kind(self, coroutine_kind) + } + + fn visit_fn_decl(&mut self, fn_decl: &$($lt)? $($mut)? FnDecl) -> Self::Result { + walk_fn_decl(self, fn_decl) + } + + fn visit_qself(&mut self, qs: &$($lt)? $($mut)? Option<P<QSelf>>) -> Self::Result { + walk_qself(self, qs) + } + + // (non-mut) `Visitor`-only methods + $( + fn visit_stmt(&mut self, s: &$lt Stmt) -> Self::Result { + walk_stmt(self, s) + } + + fn visit_nested_use_tree(&mut self, use_tree: &$lt UseTree, id: NodeId) -> Self::Result { + try_visit!(self.visit_id(id)); + self.visit_use_tree(use_tree) + } + )? + + // `MutVisitor`-only methods + $( + fn flat_map_foreign_item(&mut self, ni: P<ForeignItem>) -> SmallVec<[P<ForeignItem>; 1]> { + walk_flat_map_foreign_item(self, ni) + } + + fn flat_map_item(&mut self, i: P<Item>) -> SmallVec<[P<Item>; 1]> { + walk_flat_map_item(self, i) + } + + fn flat_map_field_def(&mut self, fd: FieldDef) -> SmallVec<[FieldDef; 1]> { + walk_flat_map_field_def(self, fd) + } + + fn flat_map_assoc_item( + &mut self, + i: P<AssocItem>, + ctxt: AssocCtxt, + ) -> SmallVec<[P<AssocItem>; 1]> { + walk_flat_map_assoc_item(self, i, ctxt) + } + + fn flat_map_stmt(&mut self, s: Stmt) -> SmallVec<[Stmt; 1]> { + walk_flat_map_stmt(self, s) + } + + fn flat_map_arm(&mut self, arm: Arm) -> SmallVec<[Arm; 1]> { + walk_flat_map_arm(self, arm) + } + + fn filter_map_expr(&mut self, e: P<Expr>) -> Option<P<Expr>> { + walk_filter_map_expr(self, e) + } + + fn flat_map_variant(&mut self, v: Variant) -> SmallVec<[Variant; 1]> { + walk_flat_map_variant(self, v) + } + + fn flat_map_param(&mut self, param: Param) -> SmallVec<[Param; 1]> { + walk_flat_map_param(self, param) + } + + fn flat_map_generic_param(&mut self, param: GenericParam) -> SmallVec<[GenericParam; 1]> { + walk_flat_map_generic_param(self, param) + } + + fn flat_map_expr_field(&mut self, f: ExprField) -> SmallVec<[ExprField; 1]> { + walk_flat_map_expr_field(self, f) + } + + fn flat_map_where_predicate( + &mut self, + where_predicate: WherePredicate, + ) -> SmallVec<[WherePredicate; 1]> { + walk_flat_map_where_predicate(self, where_predicate) + } + + // Span visiting is no longer used, but we keep it for now, + // in case it's needed for something like #127241. + fn visit_span(&mut self, _sp: &$mut Span) { + // Do nothing. + } + + fn flat_map_pat_field(&mut self, fp: PatField) -> SmallVec<[PatField; 1]> { + walk_flat_map_pat_field(self, fp) + } + )? + } + pub trait WalkItemKind { type Ctxt; fn walk<$($lt,)? V: $Visitor$(<$lt>)?>( @@ -320,8 +482,8 @@ macro_rules! common_visitor_and_walkers { id: NodeId, visibility: &$($lt)? $($mut)? Visibility, ctxt: Self::Ctxt, - visitor: &mut V, - ) $(-> <V as Visitor<$lt>>::Result)?; + vis: &mut V, + ) -> V::Result; } // this is only used by the MutVisitor. We include this symmetry here to make writing other functions easier @@ -329,12 +491,12 @@ macro_rules! common_visitor_and_walkers { #[expect(unused, rustc::pass_by_value)] #[inline] )? - fn visit_span<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, span: &$($lt)? $($mut)? Span) $(-> <V as Visitor<$lt>>::Result)? { + fn visit_span<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, span: &$($lt)? $($mut)? Span) -> V::Result { $( ${ignore($mut)} - visitor.visit_span(span); + vis.visit_span(span); )? - $(${ignore($lt)}V::Result::output())? + V::Result::output() } /// helper since `Visitor` wants `NodeId` but `MutVisitor` wants `&mut NodeId` @@ -342,34 +504,34 @@ macro_rules! common_visitor_and_walkers { #[expect(rustc::pass_by_value)] )? #[inline] - fn visit_id<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, id: &$($lt)? $($mut)? NodeId) $(-> <V as Visitor<$lt>>::Result)? { + fn visit_id<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, id: &$($lt)? $($mut)? NodeId) -> V::Result { // deref `&NodeId` into `NodeId` only for `Visitor` - visitor.visit_id( $(${ignore($lt)} * )? id) + vis.visit_id( $(${ignore($lt)} * )? id) } // this is only used by the MutVisitor. We include this symmetry here to make writing other functions easier - fn visit_safety<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, safety: &$($lt)? $($mut)? Safety) $(-> <V as Visitor<$lt>>::Result)? { + fn visit_safety<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, safety: &$($lt)? $($mut)? Safety) -> V::Result { match safety { Safety::Unsafe(span) => visit_span(vis, span), Safety::Safe(span) => visit_span(vis, span), - Safety::Default => { $(${ignore($lt)}V::Result::output())? } + Safety::Default => { V::Result::output() } } } - fn visit_constness<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, constness: &$($lt)? $($mut)? Const) $(-> <V as Visitor<$lt>>::Result)? { + fn visit_constness<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, constness: &$($lt)? $($mut)? Const) -> V::Result { match constness { Const::Yes(span) => visit_span(vis, span), Const::No => { - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } } } - fn visit_defaultness<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, defaultness: &$($lt)? $($mut)? Defaultness) $(-> <V as Visitor<$lt>>::Result)? { + fn visit_defaultness<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, defaultness: &$($lt)? $($mut)? Defaultness) -> V::Result { match defaultness { Defaultness::Default(span) => visit_span(vis, span), Defaultness::Final => { - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } } } @@ -377,9 +539,9 @@ macro_rules! common_visitor_and_walkers { fn visit_polarity<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, polarity: &$($lt)? $($mut)? ImplPolarity, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { match polarity { - ImplPolarity::Positive => { $(<V as Visitor<$lt>>::Result::output())? } + ImplPolarity::Positive => { V::Result::output() } ImplPolarity::Negative(span) => visit_span(vis, span), } } @@ -390,7 +552,7 @@ macro_rules! common_visitor_and_walkers { fn visit_modifiers<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, m: &$($lt)? $($mut)? TraitBoundModifiers - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let TraitBoundModifiers { constness, asyncness, polarity } = m; match constness { BoundConstness::Never => {} @@ -404,26 +566,44 @@ macro_rules! common_visitor_and_walkers { BoundPolarity::Positive => {} BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => try_visit!(visit_span(vis, span)), } - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } - fn visit_bounds<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, bounds: &$($lt)? $($mut)? GenericBounds, ctxt: BoundKind) $(-> <V as Visitor<$lt>>::Result)? { + $(${ignore($lt)} + #[inline] + )? + fn walk_capture_by<$($lt,)? V: $Visitor$(<$lt>)?>( + vis: &mut V, + capture_by: &$($lt)? $($mut)? CaptureBy + ) -> V::Result { + match capture_by { + CaptureBy::Ref => { V::Result::output() } + CaptureBy::Value { move_kw } => { + visit_span(vis, move_kw) + } + CaptureBy::Use { use_kw } => { + visit_span(vis, use_kw) + } + } + } + + fn visit_bounds<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, bounds: &$($lt)? $($mut)? GenericBounds, ctxt: BoundKind) -> V::Result { walk_list!(visitor, visit_param_bound, bounds, ctxt); - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } - pub fn walk_label<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, Label { ident }: &$($lt)? $($mut)? Label) $(-> <V as Visitor<$lt>>::Result)? { + pub fn walk_label<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, Label { ident }: &$($lt)? $($mut)? Label) -> V::Result { visitor.visit_ident(ident) } - pub fn walk_fn_header<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, header: &$($lt)? $($mut)? FnHeader) $(-> <V as Visitor<$lt>>::Result)? { + pub fn walk_fn_header<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, header: &$($lt)? $($mut)? FnHeader) -> V::Result { let FnHeader { safety, coroutine_kind, constness, ext: _ } = header; try_visit!(visit_constness(visitor, constness)); visit_opt!(visitor, visit_coroutine_kind, coroutine_kind); visit_safety(visitor, safety) } - pub fn walk_lifetime<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, Lifetime { id, ident }: &$($lt)? $($mut)? Lifetime) $(-> <V as Visitor<$lt>>::Result)? { + pub fn walk_lifetime<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, Lifetime { id, ident }: &$($lt)? $($mut)? Lifetime) -> V::Result { try_visit!(visit_id(visitor, id)); visitor.visit_ident(ident) } @@ -432,7 +612,7 @@ macro_rules! common_visitor_and_walkers { visitor: &mut V, item: &$($mut)? $($lt)? Item<K>, ctxt: K::Ctxt, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let Item { attrs, id, kind, vis, span, tokens: _ } = item; try_visit!(visit_id(visitor, id)); walk_list!(visitor, visit_attribute, attrs); @@ -444,7 +624,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_item<$($lt,)? V: $Visitor$(<$lt>)?, K: WalkItemKind<Ctxt = ()>>( visitor: &mut V, item: &$($mut)? $($lt)? Item<K>, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { walk_item_ctxt(visitor, item, ()) } @@ -452,7 +632,7 @@ macro_rules! common_visitor_and_walkers { visitor: &mut V, item: &$($mut)? $($lt)? AssocItem, ctxt: AssocCtxt, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { walk_item_ctxt(visitor, item, ctxt) } @@ -465,7 +645,7 @@ macro_rules! common_visitor_and_walkers { visibility: &$($lt)? $($mut)? Visibility, _ctxt: Self::Ctxt, vis: &mut V, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { match self { ItemKind::ExternCrate(_orig_name, ident) => vis.visit_ident(ident), ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree), @@ -505,7 +685,7 @@ macro_rules! common_visitor_and_walkers { } ModKind::Unloaded => {} } - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm), ItemKind::GlobalAsm(asm) => vis.visit_inline_asm(asm), @@ -526,7 +706,7 @@ macro_rules! common_visitor_and_walkers { $(${ignore($mut)} walk_ty_alias_where_clauses(vis, where_clauses); )? - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } ItemKind::Enum(ident, generics, enum_definition) => { try_visit!(vis.visit_ident(ident)); @@ -590,7 +770,7 @@ macro_rules! common_visitor_and_walkers { try_visit!(vis.visit_ident(ident)); visit_opt!(vis, visit_ident, rename); visit_opt!(vis, visit_block, body); - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => { try_visit!(vis.visit_qself(qself)); @@ -602,7 +782,7 @@ macro_rules! common_visitor_and_walkers { } } visit_opt!(vis, visit_block, body); - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } } } @@ -611,7 +791,7 @@ macro_rules! common_visitor_and_walkers { fn walk_const_item<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, item: &$($lt)? $($mut)? ConstItem, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let ConstItem { defaultness, ident, generics, ty, expr, define_opaque } = item; try_visit!(visit_defaultness(vis, defaultness)); try_visit!(vis.visit_ident(ident)); @@ -621,7 +801,7 @@ macro_rules! common_visitor_and_walkers { walk_define_opaques(vis, define_opaque) } - fn walk_foreign_mod<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, foreign_mod: &$($lt)? $($mut)? ForeignMod) $(-> <V as Visitor<$lt>>::Result)? { + fn walk_foreign_mod<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, foreign_mod: &$($lt)? $($mut)? ForeignMod) -> V::Result { let ForeignMod { extern_span: _, safety, abi: _, items } = foreign_mod; try_visit!(visit_safety(vis, safety)); visit_foreign_items(vis, items) @@ -630,14 +810,14 @@ macro_rules! common_visitor_and_walkers { fn walk_define_opaques<$($lt,)? V: $Visitor$(<$lt>)?>( visitor: &mut V, define_opaque: &$($lt)? $($mut)? Option<ThinVec<(NodeId, Path)>>, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { if let Some(define_opaque) = define_opaque { for (id, path) in define_opaque { try_visit!(visit_id(visitor, id)); try_visit!(visitor.visit_path(path)); } } - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } impl WalkItemKind for AssocItemKind { @@ -649,7 +829,7 @@ macro_rules! common_visitor_and_walkers { visibility: &$($lt)? $($mut)? Visibility, ctxt: Self::Ctxt, vis: &mut V, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { match self { AssocItemKind::Const(item) => { walk_const_item(vis, item) @@ -674,7 +854,7 @@ macro_rules! common_visitor_and_walkers { $(${ignore($mut)} walk_ty_alias_where_clauses(vis, where_clauses); )? - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } AssocItemKind::MacCall(mac) => { vis.visit_mac_call(mac) @@ -694,7 +874,7 @@ macro_rules! common_visitor_and_walkers { try_visit!(vis.visit_ident(ident)); visit_opt!(vis, visit_ident, rename); visit_opt!(vis, visit_block, body); - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => { try_visit!(vis.visit_qself(qself)); @@ -706,7 +886,7 @@ macro_rules! common_visitor_and_walkers { } } visit_opt!(vis, visit_block, body); - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } } } @@ -721,7 +901,7 @@ macro_rules! common_visitor_and_walkers { visibility: &$($lt)? $($mut)? Visibility, _ctxt: Self::Ctxt, vis: &mut V, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { match self { ForeignItemKind::Static(box StaticItem { ident, @@ -756,7 +936,7 @@ macro_rules! common_visitor_and_walkers { $(${ignore($mut)} walk_ty_alias_where_clauses(vis, where_clauses); )? - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } ForeignItemKind::MacCall(mac) => { vis.visit_mac_call(mac) @@ -768,7 +948,7 @@ macro_rules! common_visitor_and_walkers { fn walk_coroutine_kind<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, coroutine_kind: &$($lt)? $($mut)? CoroutineKind, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let (CoroutineKind::Async { span, closure_id, return_impl_trait_id } | CoroutineKind::Gen { span, closure_id, return_impl_trait_id } | CoroutineKind::AsyncGen { span, closure_id, return_impl_trait_id }) @@ -781,7 +961,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_pat<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, pattern: &$($lt)? $($mut)? Pat - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let Pat { id, kind, span, tokens: _ } = pattern; try_visit!(visit_id(vis, id)); match kind { @@ -832,7 +1012,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_anon_const<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, constant: &$($lt)? $($mut)? AnonConst, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let AnonConst { id, value } = constant; try_visit!(visit_id(vis, id)); vis.visit_expr(value) @@ -841,18 +1021,18 @@ macro_rules! common_visitor_and_walkers { pub fn walk_path_segment<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, segment: &$($lt)? $($mut)? PathSegment, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let PathSegment { ident, id, args } = segment; try_visit!(visit_id(vis, id)); try_visit!(vis.visit_ident(ident)); visit_opt!(vis, visit_generic_args, args); - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } pub fn walk_block<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, block: &$($lt)? $($mut)? Block - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let Block { stmts, id, rules: _, span, tokens: _ } = block; try_visit!(visit_id(vis, id)); try_visit!(visit_stmts(vis, stmts)); @@ -862,7 +1042,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_ty<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, ty: &$($lt)? $($mut)? Ty - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let Ty { id, kind, span, tokens: _ } = ty; try_visit!(visit_id(vis, id)); match kind { @@ -882,7 +1062,7 @@ macro_rules! common_visitor_and_walkers { TyKind::BareFn(function_declaration) => { let BareFnTy { safety, ext: _, generic_params, decl, decl_span } = &$($mut)? **function_declaration; - visit_safety(vis, safety); + try_visit!(visit_safety(vis, safety)); try_visit!(visit_generic_params(vis, generic_params)); try_visit!(vis.visit_fn_decl(decl)); try_visit!(visit_span(vis, decl_span)); @@ -920,7 +1100,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_crate<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, krate: &$($lt)? $($mut)? Crate, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let Crate { attrs, items, spans, id, is_placeholder: _ } = krate; try_visit!(visit_id(vis, id)); walk_list!(vis, visit_attribute, attrs); @@ -933,7 +1113,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_local<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, local: &$($lt)? $($mut)? Local, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let Local { id, super_, pat, ty, kind, span, colon_sp, attrs, tokens: _ } = local; if let Some(sp) = super_ { try_visit!(visit_span(vis, sp)); @@ -961,7 +1141,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_poly_trait_ref<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, p: &$($lt)? $($mut)? PolyTraitRef, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let PolyTraitRef { bound_generic_params, modifiers, trait_ref, span } = p; try_visit!(visit_modifiers(vis, modifiers)); try_visit!(visit_generic_params(vis, bound_generic_params)); @@ -972,7 +1152,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_trait_ref<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, TraitRef { path, ref_id }: &$($lt)? $($mut)? TraitRef, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { try_visit!(vis.visit_path(path)); visit_id(vis, ref_id) } @@ -980,22 +1160,21 @@ macro_rules! common_visitor_and_walkers { pub fn walk_variant<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, variant: &$($lt)? $($mut)? Variant, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let Variant { attrs, id, span, vis: visibility, ident, data, disr_expr, is_placeholder: _ } = variant; try_visit!(visit_id(vis, id)); walk_list!(vis, visit_attribute, attrs); try_visit!(vis.visit_vis(visibility)); try_visit!(vis.visit_ident(ident)); try_visit!(vis.visit_variant_data(data)); - $(${ignore($lt)} visit_opt!(vis, visit_variant_discr, disr_expr); )? - $(${ignore($mut)} visit_opt!(vis, visit_anon_const, disr_expr); )? + visit_opt!(vis, visit_anon_const, disr_expr); visit_span(vis, span) } pub fn walk_expr_field<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, f: &$($lt)? $($mut)? ExprField, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let ExprField { attrs, id, span, ident, expr, is_shorthand: _, is_placeholder: _ } = f; try_visit!(visit_id(vis, id)); walk_list!(vis, visit_attribute, attrs); @@ -1007,7 +1186,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_pat_field<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, fp: &$($lt)? $($mut)? PatField, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let PatField { ident, pat, is_shorthand: _, attrs, id, span, is_placeholder: _ } = fp; try_visit!(visit_id(vis, id)); walk_list!(vis, visit_attribute, attrs); @@ -1019,7 +1198,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_ty_pat<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, tp: &$($lt)? $($mut)? TyPat, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let TyPat { id, kind, span, tokens: _ } = tp; try_visit!(visit_id(vis, id)); match kind { @@ -1036,19 +1215,19 @@ macro_rules! common_visitor_and_walkers { fn walk_qself<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, qself: &$($lt)? $($mut)? Option<P<QSelf>>, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { if let Some(qself) = qself { let QSelf { ty, path_span, position: _ } = &$($mut)? **qself; try_visit!(vis.visit_ty(ty)); try_visit!(visit_span(vis, path_span)); } - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } pub fn walk_path<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, path: &$($lt)? $($mut)? Path, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let Path { span, segments, tokens: _ } = path; walk_list!(vis, visit_path_segment, segments); visit_span(vis, span) @@ -1057,7 +1236,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_use_tree<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, use_tree: &$($lt)? $($mut)? UseTree, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let UseTree { prefix, kind, span } = use_tree; try_visit!(vis.visit_path(prefix)); match kind { @@ -1075,573 +1254,641 @@ macro_rules! common_visitor_and_walkers { } visit_span(vis, span) } - }; -} - -common_visitor_and_walkers!(Visitor<'a>); -macro_rules! generate_list_visit_fns { - ($($name:ident, $Ty:ty, $visit_fn:ident$(, $param:ident: $ParamTy:ty)*;)+) => { - $( - fn $name<'a, V: Visitor<'a>>( - vis: &mut V, - values: &'a ThinVec<$Ty>, - $( - $param: $ParamTy, - )* - ) -> V::Result { - walk_list!(vis, $visit_fn, values$(,$param)*); - V::Result::output() + pub fn walk_generic_args<$($lt,)? V: $Visitor$(<$lt>)?>( + vis: &mut V, + generic_args: &$($lt)? $($mut)? GenericArgs + ) -> V::Result { + match generic_args { + GenericArgs::AngleBracketed(AngleBracketedArgs { span, args }) => { + for arg in args { + match arg { + AngleBracketedArg::Arg(a) => try_visit!(vis.visit_generic_arg(a)), + AngleBracketedArg::Constraint(c) => { + try_visit!(vis.visit_assoc_item_constraint(c)) + } + } + } + visit_span(vis, span) + } + GenericArgs::Parenthesized(data) => { + let ParenthesizedArgs { span, inputs, inputs_span, output } = data; + walk_list!(vis, visit_ty, inputs); + try_visit!(vis.visit_fn_ret_ty(output)); + try_visit!(visit_span(vis, span)); + visit_span(vis, inputs_span) + } + GenericArgs::ParenthesizedElided(span) => visit_span(vis, span) } - )+ - } -} + } -generate_list_visit_fns! { - visit_items, P<Item>, visit_item; - visit_foreign_items, P<ForeignItem>, visit_foreign_item; - visit_generic_params, GenericParam, visit_generic_param; - visit_stmts, Stmt, visit_stmt; - visit_pat_fields, PatField, visit_pat_field; - visit_variants, Variant, visit_variant; - visit_assoc_items, P<AssocItem>, visit_assoc_item, ctxt: AssocCtxt; -} + pub fn walk_generic_arg<$($lt,)? V: $Visitor$(<$lt>)?>( + vis: &mut V, + generic_arg: &$($lt)? $($mut)? GenericArg, + ) -> V::Result { + match generic_arg { + GenericArg::Lifetime(lt) => vis.visit_lifetime(lt, $(${ignore($lt)} LifetimeCtxt::GenericArg)? ), + GenericArg::Type(ty) => vis.visit_ty(ty), + GenericArg::Const(ct) => vis.visit_anon_const(ct), + } + } -#[expect(rustc::pass_by_value)] // needed for symmetry with mut_visit -fn visit_nested_use_tree<'a, V: Visitor<'a>>( - vis: &mut V, - nested_tree: &'a UseTree, - &nested_id: &NodeId, -) -> V::Result { - vis.visit_nested_use_tree(nested_tree, nested_id) -} + pub fn walk_assoc_item_constraint<$($lt,)? V: $Visitor$(<$lt>)?>( + vis: &mut V, + constraint: &$($lt)? $($mut)? AssocItemConstraint, + ) -> V::Result { + let AssocItemConstraint { id, ident, gen_args, kind, span } = constraint; + try_visit!(visit_id(vis, id)); + try_visit!(vis.visit_ident(ident)); + visit_opt!(vis, visit_generic_args, gen_args); + match kind { + AssocItemConstraintKind::Equality { term } => match term { + Term::Ty(ty) => try_visit!(vis.visit_ty(ty)), + Term::Const(c) => try_visit!(vis.visit_anon_const(c)), + }, + AssocItemConstraintKind::Bound { bounds } => { + try_visit!(visit_bounds(vis, bounds, BoundKind::Bound)); + } + } + visit_span(vis, span) + } -pub fn walk_generic_args<'a, V>(visitor: &mut V, generic_args: &'a GenericArgs) -> V::Result -where - V: Visitor<'a>, -{ - match generic_args { - GenericArgs::AngleBracketed(AngleBracketedArgs { span: _, args }) => { - for arg in args { - match arg { - AngleBracketedArg::Arg(a) => try_visit!(visitor.visit_generic_arg(a)), - AngleBracketedArg::Constraint(c) => { - try_visit!(visitor.visit_assoc_item_constraint(c)) - } + pub fn walk_param_bound<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, bound: &$($lt)? $($mut)? GenericBound) -> V::Result { + match bound { + GenericBound::Trait(trait_ref) => vis.visit_poly_trait_ref(trait_ref), + GenericBound::Outlives(lifetime) => vis.visit_lifetime(lifetime, $(${ignore($lt)} LifetimeCtxt::Bound)?), + GenericBound::Use(args, span) => { + walk_list!(vis, visit_precise_capturing_arg, args); + visit_span(vis, span) } } } - GenericArgs::Parenthesized(data) => { - let ParenthesizedArgs { span: _, inputs, inputs_span: _, output } = data; - walk_list!(visitor, visit_ty, inputs); - try_visit!(visitor.visit_fn_ret_ty(output)); + + pub fn walk_precise_capturing_arg<$($lt,)? V: $Visitor$(<$lt>)?>( + vis: &mut V, + arg: &$($lt)? $($mut)? PreciseCapturingArg, + ) -> V::Result { + match arg { + PreciseCapturingArg::Lifetime(lt) => vis.visit_lifetime(lt, $(${ignore($lt)} LifetimeCtxt::GenericArg)?), + PreciseCapturingArg::Arg(path, id) => { + try_visit!(visit_id(vis, id)); + vis.visit_path(path) + } + } } - GenericArgs::ParenthesizedElided(_span) => {} - } - V::Result::output() -} -pub fn walk_generic_arg<'a, V>(visitor: &mut V, generic_arg: &'a GenericArg) -> V::Result -where - V: Visitor<'a>, -{ - match generic_arg { - GenericArg::Lifetime(lt) => visitor.visit_lifetime(lt, LifetimeCtxt::GenericArg), - GenericArg::Type(ty) => visitor.visit_ty(ty), - GenericArg::Const(ct) => visitor.visit_anon_const(ct), - } -} + pub fn walk_generic_param<$($lt,)? V: $Visitor$(<$lt>)?>( + vis: &mut V, + param: &$($lt)? $($mut)? GenericParam, + ) -> V::Result { + let GenericParam { id, ident, attrs, bounds, is_placeholder: _, kind, colon_span } = + param; + try_visit!(visit_id(vis, id)); + walk_list!(vis, visit_attribute, attrs); + try_visit!(vis.visit_ident(ident)); + walk_list!(vis, visit_param_bound, bounds, BoundKind::Bound); + match kind { + GenericParamKind::Lifetime => (), + GenericParamKind::Type { default } => visit_opt!(vis, visit_ty, default), + GenericParamKind::Const { ty, default, kw_span: _ } => { + try_visit!(vis.visit_ty(ty)); + visit_opt!(vis, visit_anon_const, default); + } + } + if let Some(sp) = colon_span { + try_visit!(visit_span(vis, sp)) + } + V::Result::output() + } -pub fn walk_assoc_item_constraint<'a, V: Visitor<'a>>( - visitor: &mut V, - constraint: &'a AssocItemConstraint, -) -> V::Result { - let AssocItemConstraint { id: _, ident, gen_args, kind, span: _ } = constraint; - try_visit!(visitor.visit_ident(ident)); - visit_opt!(visitor, visit_generic_args, gen_args); - match kind { - AssocItemConstraintKind::Equality { term } => match term { - Term::Ty(ty) => try_visit!(visitor.visit_ty(ty)), - Term::Const(c) => try_visit!(visitor.visit_anon_const(c)), - }, - AssocItemConstraintKind::Bound { bounds } => { - walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); + pub fn walk_generics<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, generics: &$($lt)? $($mut)? Generics) -> V::Result { + let Generics { params, where_clause, span } = generics; + let WhereClause { has_where_token: _, predicates, span: where_clause_span } = where_clause; + try_visit!(visit_generic_params(vis, params)); + try_visit!(visit_where_predicates(vis, predicates)); + try_visit!(visit_span(vis, span)); + visit_span(vis, where_clause_span) } - } - V::Result::output() -} -pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) -> V::Result { - match bound { - GenericBound::Trait(trait_ref) => visitor.visit_poly_trait_ref(trait_ref), - GenericBound::Outlives(lifetime) => visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound), - GenericBound::Use(args, _span) => { - walk_list!(visitor, visit_precise_capturing_arg, args); + pub fn walk_contract<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, c: &$($lt)? $($mut)? FnContract) -> V::Result { + let FnContract { requires, ensures } = c; + visit_opt!(vis, visit_expr, requires); + visit_opt!(vis, visit_expr, ensures); V::Result::output() } - } -} -pub fn walk_precise_capturing_arg<'a, V: Visitor<'a>>( - visitor: &mut V, - arg: &'a PreciseCapturingArg, -) -> V::Result { - match arg { - PreciseCapturingArg::Lifetime(lt) => visitor.visit_lifetime(lt, LifetimeCtxt::GenericArg), - PreciseCapturingArg::Arg(path, id) => { - try_visit!(visitor.visit_id(*id)); - visitor.visit_path(path) + pub fn walk_where_predicate<$($lt,)? V: $Visitor$(<$lt>)?>( + vis: &mut V, + predicate: &$($lt)? $($mut)? WherePredicate, + ) -> V::Result { + let WherePredicate { attrs, kind, id, span, is_placeholder: _ } = predicate; + try_visit!(visit_id(vis, id)); + walk_list!(vis, visit_attribute, attrs); + try_visit!(visit_span(vis, span)); + vis.visit_where_predicate_kind(kind) } - } -} -pub fn walk_generic_param<'a, V: Visitor<'a>>( - visitor: &mut V, - param: &'a GenericParam, -) -> V::Result { - let GenericParam { id: _, ident, attrs, bounds, is_placeholder: _, kind, colon_span: _ } = - param; - walk_list!(visitor, visit_attribute, attrs); - try_visit!(visitor.visit_ident(ident)); - walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); - match kind { - GenericParamKind::Lifetime => (), - GenericParamKind::Type { default } => visit_opt!(visitor, visit_ty, default), - GenericParamKind::Const { ty, default, kw_span: _ } => { - try_visit!(visitor.visit_ty(ty)); - visit_opt!(visitor, visit_anon_const, default); + pub fn walk_closure_binder<$($lt,)? V: $Visitor$(<$lt>)?>( + vis: &mut V, + binder: &$($lt)? $($mut)? ClosureBinder, + ) -> V::Result { + match binder { + ClosureBinder::NotPresent => {} + ClosureBinder::For { generic_params, span } => { + try_visit!(visit_generic_params(vis, generic_params)); + try_visit!(visit_span(vis, span)); + } + } + V::Result::output() } - } - V::Result::output() -} -pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics) -> V::Result { - let Generics { params, where_clause, span: _ } = generics; - let WhereClause { has_where_token: _, predicates, span: _ } = where_clause; - walk_list!(visitor, visit_generic_param, params); - walk_list!(visitor, visit_where_predicate, predicates); - V::Result::output() -} + pub fn walk_where_predicate_kind<$($lt,)? V: $Visitor$(<$lt>)?>( + vis: &mut V, + kind: &$($lt)? $($mut)? WherePredicateKind, + ) -> V::Result { + match kind { + WherePredicateKind::BoundPredicate(WhereBoundPredicate { + bounded_ty, + bounds, + bound_generic_params, + }) => { + try_visit!(visit_generic_params(vis, bound_generic_params)); + try_visit!(vis.visit_ty(bounded_ty)); + walk_list!(vis, visit_param_bound, bounds, BoundKind::Bound); + } + WherePredicateKind::RegionPredicate(WhereRegionPredicate { lifetime, bounds }) => { + try_visit!(vis.visit_lifetime(lifetime, $(${ignore($lt)} LifetimeCtxt::Bound )?)); + walk_list!(vis, visit_param_bound, bounds, BoundKind::Bound); + } + WherePredicateKind::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty }) => { + try_visit!(vis.visit_ty(lhs_ty)); + try_visit!(vis.visit_ty(rhs_ty)); + } + } + V::Result::output() + } -pub fn walk_closure_binder<'a, V: Visitor<'a>>( - visitor: &mut V, - binder: &'a ClosureBinder, -) -> V::Result { - match binder { - ClosureBinder::NotPresent => {} - ClosureBinder::For { generic_params, span: _ } => { - walk_list!(visitor, visit_generic_param, generic_params) + pub fn walk_fn_decl<$($lt,)? V: $Visitor$(<$lt>)?>( + vis: &mut V, + FnDecl { inputs, output }: &$($lt)? $($mut)? FnDecl, + ) -> V::Result { + try_visit!(visit_params(vis, inputs)); + vis.visit_fn_ret_ty(output) } - } - V::Result::output() -} -pub fn walk_contract<'a, V: Visitor<'a>>(visitor: &mut V, c: &'a FnContract) -> V::Result { - let FnContract { requires, ensures } = c; - if let Some(pred) = requires { - visitor.visit_expr(pred); - } - if let Some(pred) = ensures { - visitor.visit_expr(pred); - } - V::Result::output() -} + pub fn walk_fn_ret_ty<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, ret_ty: &$($lt)? $($mut)? FnRetTy) -> V::Result { + match ret_ty { + FnRetTy::Default(span) => visit_span(vis, span), + FnRetTy::Ty(output_ty) => vis.visit_ty(output_ty), + } + } -pub fn walk_where_predicate<'a, V: Visitor<'a>>( - visitor: &mut V, - predicate: &'a WherePredicate, -) -> V::Result { - let WherePredicate { attrs, kind, id: _, span: _, is_placeholder: _ } = predicate; - walk_list!(visitor, visit_attribute, attrs); - visitor.visit_where_predicate_kind(kind) -} + pub fn walk_fn<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, kind: FnKind<$($lt)? $(${ignore($mut)} '_)?>) -> V::Result { + match kind { + FnKind::Fn( + _ctxt, + _vis, + Fn { + defaultness, + ident, + sig: FnSig { header, decl, span }, + generics, + contract, + body, + define_opaque, + }, + ) => { + // Visibility is visited as a part of the item. + try_visit!(visit_defaultness(vis, defaultness)); + try_visit!(vis.visit_ident(ident)); + try_visit!(vis.visit_fn_header(header)); + try_visit!(vis.visit_generics(generics)); + try_visit!(vis.visit_fn_decl(decl)); + visit_opt!(vis, visit_contract, contract); + visit_opt!(vis, visit_block, body); + try_visit!(visit_span(vis, span)); + walk_define_opaques(vis, define_opaque) + } + FnKind::Closure(binder, coroutine_kind, decl, body) => { + try_visit!(vis.visit_closure_binder(binder)); + visit_opt!(vis, visit_coroutine_kind, coroutine_kind); + try_visit!(vis.visit_fn_decl(decl)); + vis.visit_expr(body) + } + } + } -pub fn walk_where_predicate_kind<'a, V: Visitor<'a>>( - visitor: &mut V, - kind: &'a WherePredicateKind, -) -> V::Result { - match kind { - WherePredicateKind::BoundPredicate(WhereBoundPredicate { - bounded_ty, - bounds, - bound_generic_params, - }) => { - walk_list!(visitor, visit_generic_param, bound_generic_params); - try_visit!(visitor.visit_ty(bounded_ty)); - walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); - } - WherePredicateKind::RegionPredicate(WhereRegionPredicate { lifetime, bounds }) => { - try_visit!(visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound)); - walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); - } - WherePredicateKind::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty }) => { - try_visit!(visitor.visit_ty(lhs_ty)); - try_visit!(visitor.visit_ty(rhs_ty)); + pub fn walk_variant_data<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, data: &$($lt)? $($mut)? VariantData) -> V::Result { + match data { + VariantData::Struct { fields, recovered: _ } => { + visit_field_defs(vis, fields) + } + VariantData::Tuple(fields, id) => { + try_visit!(visit_id(vis, id)); + visit_field_defs(vis, fields) + } + VariantData::Unit(id) => visit_id(vis, id), + } } - } - V::Result::output() -} -pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FnRetTy) -> V::Result { - match ret_ty { - FnRetTy::Default(_span) => {} - FnRetTy::Ty(output_ty) => try_visit!(visitor.visit_ty(output_ty)), - } - V::Result::output() -} + pub fn walk_field_def<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, field: &$($lt)? $($mut)? FieldDef) -> V::Result { + let FieldDef { attrs, id, span, vis: visibility, ident, ty, is_placeholder: _, safety: _, default } = + field; + try_visit!(visit_id(vis, id)); + walk_list!(vis, visit_attribute, attrs); + try_visit!(vis.visit_vis(visibility)); + visit_opt!(vis, visit_ident, ident); + try_visit!(vis.visit_ty(ty)); + visit_opt!(vis, visit_anon_const, default); + visit_span(vis, span) + } -pub fn walk_fn_decl<'a, V: Visitor<'a>>( - visitor: &mut V, - FnDecl { inputs, output }: &'a FnDecl, -) -> V::Result { - walk_list!(visitor, visit_param, inputs); - visitor.visit_fn_ret_ty(output) -} + fn visit_delim_args<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, args: &$($lt)? $($mut)? DelimArgs) -> V::Result { + let DelimArgs { dspan, delim: _, tokens: _ } = args; + let DelimSpan { open, close } = dspan; + try_visit!(visit_span(vis, open)); + visit_span(vis, close) + } -pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Result { - match kind { - FnKind::Fn( - _ctxt, - _vis, - Fn { - defaultness: _, - ident, - sig: FnSig { header, decl, span: _ }, - generics, - contract, - body, - define_opaque, - }, - ) => { - // Visibility is visited as a part of the item. - try_visit!(visitor.visit_ident(ident)); - try_visit!(visitor.visit_fn_header(header)); - try_visit!(visitor.visit_generics(generics)); - try_visit!(visitor.visit_fn_decl(decl)); - visit_opt!(visitor, visit_contract, contract); - visit_opt!(visitor, visit_block, body); - try_visit!(walk_define_opaques(visitor, define_opaque)); - } - FnKind::Closure(binder, coroutine_kind, decl, body) => { - try_visit!(visitor.visit_closure_binder(binder)); - visit_opt!(visitor, visit_coroutine_kind, coroutine_kind.as_ref()); - try_visit!(visitor.visit_fn_decl(decl)); - try_visit!(visitor.visit_expr(body)); + pub fn walk_mac<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, mac: &$($lt)? $($mut)? MacCall) -> V::Result { + let MacCall { path, args } = mac; + try_visit!(vis.visit_path(path)); + visit_delim_args(vis, args) + } + + fn walk_macro_def<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, macro_def: &$($lt)? $($mut)? MacroDef) -> V::Result { + let MacroDef { body, macro_rules: _ } = macro_def; + visit_delim_args(vis, body) + } + + pub fn walk_inline_asm<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, asm: &$($lt)? $($mut)? InlineAsm) -> V::Result { + // FIXME: Visit spans inside all this currently ignored stuff. + let InlineAsm { + asm_macro: _, + template: _, + template_strs: _, + operands, + clobber_abis: _, + options: _, + line_spans: _, + } = asm; + for (op, span) in operands { + match op { + InlineAsmOperand::In { expr, reg: _ } + | InlineAsmOperand::Out { expr: Some(expr), reg: _, late: _ } + | InlineAsmOperand::InOut { expr, reg: _, late: _ } => { + try_visit!(vis.visit_expr(expr)) + } + InlineAsmOperand::Out { expr: None, reg: _, late: _ } => {} + InlineAsmOperand::SplitInOut { in_expr, out_expr, reg: _, late: _ } => { + try_visit!(vis.visit_expr(in_expr)); + visit_opt!(vis, visit_expr, out_expr); + } + InlineAsmOperand::Const { anon_const } => { + try_visit!(vis.visit_anon_const(anon_const)) + } + InlineAsmOperand::Sym { sym } => try_visit!(vis.visit_inline_asm_sym(sym)), + InlineAsmOperand::Label { block } => try_visit!(vis.visit_block(block)), + } + try_visit!(visit_span(vis, span)); + } + V::Result::output() } - } - V::Result::output() -} -pub fn walk_variant_data<'a, V: Visitor<'a>>(visitor: &mut V, data: &'a VariantData) -> V::Result { - visit_opt!(visitor, visit_id, data.ctor_node_id()); - walk_list!(visitor, visit_field_def, data.fields()); - V::Result::output() -} + pub fn walk_inline_asm_sym<$($lt,)? V: $Visitor$(<$lt>)?>( + vis: &mut V, + InlineAsmSym { id, qself, path }: &$($lt)? $($mut)? InlineAsmSym, + ) -> V::Result { + try_visit!(visit_id(vis, id)); + try_visit!(vis.visit_qself(qself)); + vis.visit_path(path) + } + + // FIXME: visit the template exhaustively. + pub fn walk_format_args<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, fmt: &$($lt)? $($mut)? FormatArgs) -> V::Result { + let FormatArgs { span, template: _, arguments, uncooked_fmt_str: _, is_source_literal: _ } = fmt; + let args = $(${ignore($mut)} arguments.all_args_mut())? $(${ignore($lt)} arguments.all_args())? ; + for FormatArgument { kind, expr } in args { + match kind { + FormatArgumentKind::Named(ident) | FormatArgumentKind::Captured(ident) => { + try_visit!(vis.visit_ident(ident)) + } + FormatArgumentKind::Normal => {} + } + try_visit!(vis.visit_expr(expr)); + } + visit_span(vis, span) + } -pub fn walk_field_def<'a, V: Visitor<'a>>(visitor: &mut V, field: &'a FieldDef) -> V::Result { - let FieldDef { attrs, id: _, span: _, vis, ident, ty, is_placeholder: _, safety: _, default } = - field; - walk_list!(visitor, visit_attribute, attrs); - try_visit!(visitor.visit_vis(vis)); - visit_opt!(visitor, visit_ident, ident); - try_visit!(visitor.visit_ty(ty)); - visit_opt!(visitor, visit_anon_const, &*default); - V::Result::output() -} + pub fn walk_expr<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, expression: &$($lt)? $($mut)? Expr) -> V::Result { + let Expr { id, kind, span, attrs, tokens: _ } = expression; + try_visit!(visit_id(vis, id)); + walk_list!(vis, visit_attribute, attrs); + match kind { + ExprKind::Array(exprs) => { + try_visit!(visit_exprs(vis, exprs)); + } + ExprKind::ConstBlock(anon_const) => try_visit!(vis.visit_anon_const(anon_const)), + ExprKind::Repeat(element, count) => { + try_visit!(vis.visit_expr(element)); + try_visit!(vis.visit_anon_const(count)); + } + ExprKind::Struct(se) => { + let StructExpr { qself, path, fields, rest } = &$($mut)?**se; + try_visit!(vis.visit_qself(qself)); + try_visit!(vis.visit_path(path)); + try_visit!(visit_expr_fields(vis, fields)); + match rest { + StructRest::Base(expr) => try_visit!(vis.visit_expr(expr)), + StructRest::Rest(_span) => {} + StructRest::None => {} + } + } + ExprKind::Tup(exprs) => { + try_visit!(visit_exprs(vis, exprs)); + } + ExprKind::Call(callee_expression, arguments) => { + try_visit!(vis.visit_expr(callee_expression)); + try_visit!(visit_exprs(vis, arguments)); + } + ExprKind::MethodCall(box MethodCall { seg, receiver, args, span }) => { + try_visit!(vis.visit_method_receiver_expr(receiver)); + try_visit!(vis.visit_path_segment(seg)); + try_visit!(visit_exprs(vis, args)); + try_visit!(visit_span(vis, span)); + } + ExprKind::Binary(Spanned { span, node: _ }, left_expression, right_expression) => { + try_visit!(vis.visit_expr(left_expression)); + try_visit!(vis.visit_expr(right_expression)); + try_visit!(visit_span(vis, span)) + } + ExprKind::AddrOf(_kind, _mutbl, subexpression) => { + try_visit!(vis.visit_expr(subexpression)); + } + ExprKind::Unary(_op, subexpression) => { + try_visit!(vis.visit_expr(subexpression)); + } + ExprKind::Cast(subexpression, typ) | ExprKind::Type(subexpression, typ) => { + try_visit!(vis.visit_expr(subexpression)); + try_visit!(vis.visit_ty(typ)); + } + ExprKind::Let(pat, expr, span, _recovered) => { + try_visit!(vis.visit_pat(pat)); + try_visit!(vis.visit_expr(expr)); + try_visit!(visit_span(vis, span)) + } + ExprKind::If(head_expression, if_block, optional_else) => { + try_visit!(vis.visit_expr(head_expression)); + try_visit!(vis.visit_block(if_block)); + visit_opt!(vis, visit_expr, optional_else); + } + ExprKind::While(subexpression, block, opt_label) => { + visit_opt!(vis, visit_label, opt_label); + try_visit!(vis.visit_expr(subexpression)); + try_visit!(vis.visit_block(block)); + } + ExprKind::ForLoop { pat, iter, body, label, kind: _ } => { + visit_opt!(vis, visit_label, label); + try_visit!(vis.visit_pat(pat)); + try_visit!(vis.visit_expr(iter)); + try_visit!(vis.visit_block(body)); + } + ExprKind::Loop(block, opt_label, span) => { + visit_opt!(vis, visit_label, opt_label); + try_visit!(vis.visit_block(block)); + try_visit!(visit_span(vis, span)) + } + ExprKind::Match(subexpression, arms, _kind) => { + try_visit!(vis.visit_expr(subexpression)); + try_visit!(visit_arms(vis, arms)); + } + ExprKind::Closure(box Closure { + binder, + capture_clause, + coroutine_kind, + constness, + movability: _, + fn_decl, + body, + fn_decl_span, + fn_arg_span, + }) => { + try_visit!(visit_constness(vis, constness)); + try_visit!(vis.visit_capture_by(capture_clause)); + try_visit!(vis.visit_fn( + FnKind::Closure(binder, coroutine_kind, fn_decl, body), + *span, + *id + )); + try_visit!(visit_span(vis, fn_decl_span)); + try_visit!(visit_span(vis, fn_arg_span)); + } + ExprKind::Block(block, opt_label) => { + visit_opt!(vis, visit_label, opt_label); + try_visit!(vis.visit_block(block)); + } + ExprKind::Gen(_capt, body, _kind, decl_span) => { + try_visit!(vis.visit_block(body)); + try_visit!(visit_span(vis, decl_span)); + } + ExprKind::Await(expr, span) => { + try_visit!(vis.visit_expr(expr)); + try_visit!(visit_span(vis, span)); + } + ExprKind::Use(expr, span) => { + try_visit!(vis.visit_expr(expr)); + try_visit!(visit_span(vis, span)); + } + ExprKind::Assign(lhs, rhs, span) => { + try_visit!(vis.visit_expr(lhs)); + try_visit!(vis.visit_expr(rhs)); + try_visit!(visit_span(vis, span)); + } + ExprKind::AssignOp(_op, left_expression, right_expression) => { + try_visit!(vis.visit_expr(left_expression)); + try_visit!(vis.visit_expr(right_expression)); + } + ExprKind::Field(subexpression, ident) => { + try_visit!(vis.visit_expr(subexpression)); + try_visit!(vis.visit_ident(ident)); + } + ExprKind::Index(main_expression, index_expression, span) => { + try_visit!(vis.visit_expr(main_expression)); + try_visit!(vis.visit_expr(index_expression)); + try_visit!(visit_span(vis, span)); + } + ExprKind::Range(start, end, _limit) => { + visit_opt!(vis, visit_expr, start); + visit_opt!(vis, visit_expr, end); + } + ExprKind::Underscore => {} + ExprKind::Path(maybe_qself, path) => { + try_visit!(vis.visit_qself(maybe_qself)); + try_visit!(vis.visit_path(path)); + } + ExprKind::Break(opt_label, opt_expr) => { + visit_opt!(vis, visit_label, opt_label); + visit_opt!(vis, visit_expr, opt_expr); + } + ExprKind::Continue(opt_label) => { + visit_opt!(vis, visit_label, opt_label); + } + ExprKind::Ret(optional_expression) => { + visit_opt!(vis, visit_expr, optional_expression); + } + ExprKind::Yeet(optional_expression) => { + visit_opt!(vis, visit_expr, optional_expression); + } + ExprKind::Become(expr) => try_visit!(vis.visit_expr(expr)), + ExprKind::MacCall(mac) => try_visit!(vis.visit_mac_call(mac)), + ExprKind::Paren(subexpression) => try_visit!(vis.visit_expr(subexpression)), + ExprKind::InlineAsm(asm) => try_visit!(vis.visit_inline_asm(asm)), + ExprKind::FormatArgs(f) => try_visit!(vis.visit_format_args(f)), + ExprKind::OffsetOf(container, fields) => { + try_visit!(vis.visit_ty(container)); + walk_list!(vis, visit_ident, fields); + } + ExprKind::Yield(kind) => { + match kind { + YieldKind::Postfix(expr) => { + try_visit!(vis.visit_expr(expr)); + } + YieldKind::Prefix(expr) => { + visit_opt!(vis, visit_expr, expr); + } + } + } + ExprKind::Try(subexpression) => try_visit!(vis.visit_expr(subexpression)), + ExprKind::TryBlock(body) => try_visit!(vis.visit_block(body)), + ExprKind::Lit(_token) => {} + ExprKind::IncludedBytes(_bytes) => {} + ExprKind::UnsafeBinderCast(_kind, expr, ty) => { + try_visit!(vis.visit_expr(expr)); + visit_opt!(vis, visit_ty, ty); + } + ExprKind::Err(_guar) => {} + ExprKind::Dummy => {} + } -pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V::Result { - let Stmt { id: _, kind, span: _ } = statement; - match kind { - StmtKind::Let(local) => try_visit!(visitor.visit_local(local)), - StmtKind::Item(item) => try_visit!(visitor.visit_item(item)), - StmtKind::Expr(expr) | StmtKind::Semi(expr) => try_visit!(visitor.visit_expr(expr)), - StmtKind::Empty => {} - StmtKind::MacCall(mac) => { - let MacCallStmt { mac, attrs, style: _, tokens: _ } = &**mac; - walk_list!(visitor, visit_attribute, attrs); - try_visit!(visitor.visit_mac_call(mac)); + visit_span(vis, span) } - } - V::Result::output() -} - -pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a MacCall) -> V::Result { - let MacCall { path, args: _ } = mac; - visitor.visit_path(path) -} -pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) -> V::Result { - let InlineAsm { - asm_macro: _, - template: _, - template_strs: _, - operands, - clobber_abis: _, - options: _, - line_spans: _, - } = asm; - for (op, _span) in operands { - match op { - InlineAsmOperand::In { expr, reg: _ } - | InlineAsmOperand::Out { expr: Some(expr), reg: _, late: _ } - | InlineAsmOperand::InOut { expr, reg: _, late: _ } => { - try_visit!(visitor.visit_expr(expr)) - } - InlineAsmOperand::Out { expr: None, reg: _, late: _ } => {} - InlineAsmOperand::SplitInOut { in_expr, out_expr, reg: _, late: _ } => { - try_visit!(visitor.visit_expr(in_expr)); - visit_opt!(visitor, visit_expr, out_expr); - } - InlineAsmOperand::Const { anon_const } => { - try_visit!(visitor.visit_anon_const(anon_const)) - } - InlineAsmOperand::Sym { sym } => try_visit!(visitor.visit_inline_asm_sym(sym)), - InlineAsmOperand::Label { block } => try_visit!(visitor.visit_block(block)), + pub fn walk_param<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, param: &$($lt)? $($mut)? Param) -> V::Result { + let Param { attrs, ty, pat, id, span, is_placeholder: _ } = param; + try_visit!(visit_id(vis, id)); + walk_list!(vis, visit_attribute, attrs); + try_visit!(vis.visit_pat(pat)); + try_visit!(vis.visit_ty(ty)); + visit_span(vis, span) } - } - V::Result::output() -} -pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>( - visitor: &mut V, - InlineAsmSym { id, qself, path }: &'a InlineAsmSym, -) -> V::Result { - try_visit!(visitor.visit_qself(qself)); - try_visit!(visitor.visit_id(*id)); - visitor.visit_path(path) -} + pub fn walk_arm<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, arm: &$($lt)? $($mut)? Arm) -> V::Result { + let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = arm; + try_visit!(visit_id(vis, id)); + walk_list!(vis, visit_attribute, attrs); + try_visit!(vis.visit_pat(pat)); + visit_opt!(vis, visit_expr, guard); + visit_opt!(vis, visit_expr, body); + visit_span(vis, span) + } -pub fn walk_format_args<'a, V: Visitor<'a>>(visitor: &mut V, fmt: &'a FormatArgs) -> V::Result { - let FormatArgs { span: _, template: _, arguments, uncooked_fmt_str: _ } = fmt; - for FormatArgument { kind, expr } in arguments.all_args() { - match kind { - FormatArgumentKind::Named(ident) | FormatArgumentKind::Captured(ident) => { - try_visit!(visitor.visit_ident(ident)) + pub fn walk_vis<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, visibility: &$($lt)? $($mut)? Visibility) -> V::Result { + let Visibility { kind, span, tokens: _ } = visibility; + match kind { + VisibilityKind::Restricted { path, id, shorthand: _ } => { + try_visit!(visit_id(vis, id)); + try_visit!(vis.visit_path(path)); + } + VisibilityKind::Public | VisibilityKind::Inherited => {} } - FormatArgumentKind::Normal => {} + visit_span(vis, span) } - try_visit!(visitor.visit_expr(expr)); - } - V::Result::output() -} -pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V::Result { - let Expr { id, kind, span, attrs, tokens: _ } = expression; - walk_list!(visitor, visit_attribute, attrs); - match kind { - ExprKind::Array(subexpressions) => { - walk_list!(visitor, visit_expr, subexpressions); - } - ExprKind::ConstBlock(anon_const) => try_visit!(visitor.visit_anon_const(anon_const)), - ExprKind::Repeat(element, count) => { - try_visit!(visitor.visit_expr(element)); - try_visit!(visitor.visit_anon_const(count)); - } - ExprKind::Struct(se) => { - let StructExpr { qself, path, fields, rest } = &**se; - try_visit!(visitor.visit_qself(qself)); - try_visit!(visitor.visit_id(*id)); - try_visit!(visitor.visit_path(path)); - walk_list!(visitor, visit_expr_field, fields); - match rest { - StructRest::Base(expr) => try_visit!(visitor.visit_expr(expr)), - StructRest::Rest(_span) => {} - StructRest::None => {} - } - } - ExprKind::Tup(subexpressions) => { - walk_list!(visitor, visit_expr, subexpressions); - } - ExprKind::Call(callee_expression, arguments) => { - try_visit!(visitor.visit_expr(callee_expression)); - walk_list!(visitor, visit_expr, arguments); - } - ExprKind::MethodCall(box MethodCall { seg, receiver, args, span: _ }) => { - try_visit!(visitor.visit_expr(receiver)); - try_visit!(visitor.visit_path_segment(seg)); - walk_list!(visitor, visit_expr, args); - } - ExprKind::Binary(_op, left_expression, right_expression) => { - try_visit!(visitor.visit_expr(left_expression)); - try_visit!(visitor.visit_expr(right_expression)); - } - ExprKind::AddrOf(_kind, _mutbl, subexpression) => { - try_visit!(visitor.visit_expr(subexpression)); - } - ExprKind::Unary(_op, subexpression) => { - try_visit!(visitor.visit_expr(subexpression)); - } - ExprKind::Cast(subexpression, typ) | ExprKind::Type(subexpression, typ) => { - try_visit!(visitor.visit_expr(subexpression)); - try_visit!(visitor.visit_ty(typ)); - } - ExprKind::Let(pat, expr, _span, _recovered) => { - try_visit!(visitor.visit_pat(pat)); - try_visit!(visitor.visit_expr(expr)); - } - ExprKind::If(head_expression, if_block, optional_else) => { - try_visit!(visitor.visit_expr(head_expression)); - try_visit!(visitor.visit_block(if_block)); - visit_opt!(visitor, visit_expr, optional_else); - } - ExprKind::While(subexpression, block, opt_label) => { - visit_opt!(visitor, visit_label, opt_label); - try_visit!(visitor.visit_expr(subexpression)); - try_visit!(visitor.visit_block(block)); - } - ExprKind::ForLoop { pat, iter, body, label, kind: _ } => { - visit_opt!(visitor, visit_label, label); - try_visit!(visitor.visit_pat(pat)); - try_visit!(visitor.visit_expr(iter)); - try_visit!(visitor.visit_block(body)); - } - ExprKind::Loop(block, opt_label, _span) => { - visit_opt!(visitor, visit_label, opt_label); - try_visit!(visitor.visit_block(block)); - } - ExprKind::Match(subexpression, arms, _kind) => { - try_visit!(visitor.visit_expr(subexpression)); - walk_list!(visitor, visit_arm, arms); - } - ExprKind::Closure(box Closure { - binder, - capture_clause, - coroutine_kind, - constness: _, - movability: _, - fn_decl, - body, - fn_decl_span: _, - fn_arg_span: _, - }) => { - try_visit!(visitor.visit_capture_by(capture_clause)); - try_visit!(visitor.visit_fn( - FnKind::Closure(binder, coroutine_kind, fn_decl, body), - *span, - *id - )); - } - ExprKind::Block(block, opt_label) => { - visit_opt!(visitor, visit_label, opt_label); - try_visit!(visitor.visit_block(block)); - } - ExprKind::Gen(_capt, body, _kind, _decl_span) => try_visit!(visitor.visit_block(body)), - ExprKind::Await(expr, _span) => try_visit!(visitor.visit_expr(expr)), - ExprKind::Use(expr, _span) => try_visit!(visitor.visit_expr(expr)), - ExprKind::Assign(lhs, rhs, _span) => { - try_visit!(visitor.visit_expr(lhs)); - try_visit!(visitor.visit_expr(rhs)); - } - ExprKind::AssignOp(_op, left_expression, right_expression) => { - try_visit!(visitor.visit_expr(left_expression)); - try_visit!(visitor.visit_expr(right_expression)); - } - ExprKind::Field(subexpression, ident) => { - try_visit!(visitor.visit_expr(subexpression)); - try_visit!(visitor.visit_ident(ident)); - } - ExprKind::Index(main_expression, index_expression, _span) => { - try_visit!(visitor.visit_expr(main_expression)); - try_visit!(visitor.visit_expr(index_expression)); - } - ExprKind::Range(start, end, _limit) => { - visit_opt!(visitor, visit_expr, start); - visit_opt!(visitor, visit_expr, end); - } - ExprKind::Underscore => {} - ExprKind::Path(maybe_qself, path) => { - try_visit!(visitor.visit_qself(maybe_qself)); - try_visit!(visitor.visit_id(*id)); - try_visit!(visitor.visit_path(path)); - } - ExprKind::Break(opt_label, opt_expr) => { - visit_opt!(visitor, visit_label, opt_label); - visit_opt!(visitor, visit_expr, opt_expr); - } - ExprKind::Continue(opt_label) => { - visit_opt!(visitor, visit_label, opt_label); - } - ExprKind::Ret(optional_expression) => { - visit_opt!(visitor, visit_expr, optional_expression); - } - ExprKind::Yeet(optional_expression) => { - visit_opt!(visitor, visit_expr, optional_expression); - } - ExprKind::Become(expr) => try_visit!(visitor.visit_expr(expr)), - ExprKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)), - ExprKind::Paren(subexpression) => try_visit!(visitor.visit_expr(subexpression)), - ExprKind::InlineAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)), - ExprKind::FormatArgs(f) => try_visit!(visitor.visit_format_args(f)), - ExprKind::OffsetOf(container, fields) => { - try_visit!(visitor.visit_ty(container)); - walk_list!(visitor, visit_ident, fields.iter()); - } - ExprKind::Yield(kind) => { - visit_opt!(visitor, visit_expr, kind.expr()); - } - ExprKind::Try(subexpression) => try_visit!(visitor.visit_expr(subexpression)), - ExprKind::TryBlock(body) => try_visit!(visitor.visit_block(body)), - ExprKind::Lit(_token) => {} - ExprKind::IncludedBytes(_bytes) => {} - ExprKind::UnsafeBinderCast(_kind, expr, ty) => { - try_visit!(visitor.visit_expr(expr)); - visit_opt!(visitor, visit_ty, ty); - } - ExprKind::Err(_guar) => {} - ExprKind::Dummy => {} - } + pub fn walk_attribute<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, attr: &$($lt)? $($mut)? Attribute) -> V::Result { + let Attribute { kind, id: _, style: _, span } = attr; + match kind { + AttrKind::Normal(normal) => { + let NormalAttr { item, tokens: _ } = &$($mut)?**normal; + let AttrItem { unsafety: _, path, args, tokens: _ } = item; + try_visit!(vis.visit_path(path)); + try_visit!(walk_attr_args(vis, args)); + } + AttrKind::DocComment(_kind, _sym) => {} + } + visit_span(vis, span) + } - V::Result::output() + pub fn walk_attr_args<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, args: &$($lt)? $($mut)? AttrArgs) -> V::Result { + match args { + AttrArgs::Empty => {} + AttrArgs::Delimited(args) => try_visit!(visit_delim_args(vis, args)), + AttrArgs::Eq { eq_span, expr } => { + try_visit!(vis.visit_expr(expr)); + try_visit!(visit_span(vis, eq_span)); + } + } + V::Result::output() + } + }; } -pub fn walk_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Param) -> V::Result { - let Param { attrs, ty, pat, id: _, span: _, is_placeholder: _ } = param; - walk_list!(visitor, visit_attribute, attrs); - try_visit!(visitor.visit_pat(pat)); - try_visit!(visitor.visit_ty(ty)); - V::Result::output() +common_visitor_and_walkers!(Visitor<'a>); + +macro_rules! generate_list_visit_fns { + ($($name:ident, $Ty:ty, $visit_fn:ident$(, $param:ident: $ParamTy:ty)*;)+) => { + $( + fn $name<'a, V: Visitor<'a>>( + vis: &mut V, + values: &'a ThinVec<$Ty>, + $( + $param: $ParamTy, + )* + ) -> V::Result { + walk_list!(vis, $visit_fn, values$(,$param)*); + V::Result::output() + } + )+ + } } -pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) -> V::Result { - let Arm { attrs, pat, guard, body, span: _, id: _, is_placeholder: _ } = arm; - walk_list!(visitor, visit_attribute, attrs); - try_visit!(visitor.visit_pat(pat)); - visit_opt!(visitor, visit_expr, guard); - visit_opt!(visitor, visit_expr, body); - V::Result::output() +generate_list_visit_fns! { + visit_items, P<Item>, visit_item; + visit_foreign_items, P<ForeignItem>, visit_foreign_item; + visit_generic_params, GenericParam, visit_generic_param; + visit_stmts, Stmt, visit_stmt; + visit_exprs, P<Expr>, visit_expr; + visit_expr_fields, ExprField, visit_expr_field; + visit_pat_fields, PatField, visit_pat_field; + visit_variants, Variant, visit_variant; + visit_assoc_items, P<AssocItem>, visit_assoc_item, ctxt: AssocCtxt; + visit_where_predicates, WherePredicate, visit_where_predicate; + visit_params, Param, visit_param; + visit_field_defs, FieldDef, visit_field_def; + visit_arms, Arm, visit_arm; } -pub fn walk_vis<'a, V: Visitor<'a>>(visitor: &mut V, vis: &'a Visibility) -> V::Result { - let Visibility { kind, span: _, tokens: _ } = vis; - match kind { - VisibilityKind::Restricted { path, id, shorthand: _ } => { - try_visit!(visitor.visit_id(*id)); - try_visit!(visitor.visit_path(path)); - } - VisibilityKind::Public | VisibilityKind::Inherited => {} - } - V::Result::output() +#[expect(rustc::pass_by_value)] // needed for symmetry with mut_visit +fn visit_nested_use_tree<'a, V: Visitor<'a>>( + vis: &mut V, + nested_tree: &'a UseTree, + &nested_id: &NodeId, +) -> V::Result { + vis.visit_nested_use_tree(nested_tree, nested_id) } -pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) -> V::Result { - let Attribute { kind, id: _, style: _, span: _ } = attr; +pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V::Result { + let Stmt { id, kind, span: _ } = statement; + try_visit!(visit_id(visitor, id)); match kind { - AttrKind::Normal(normal) => { - let NormalAttr { item, tokens: _ } = &**normal; - let AttrItem { unsafety: _, path, args, tokens: _ } = item; - try_visit!(visitor.visit_path(path)); - try_visit!(walk_attr_args(visitor, args)); + StmtKind::Let(local) => try_visit!(visitor.visit_local(local)), + StmtKind::Item(item) => try_visit!(visitor.visit_item(item)), + StmtKind::Expr(expr) | StmtKind::Semi(expr) => try_visit!(visitor.visit_expr(expr)), + StmtKind::Empty => {} + StmtKind::MacCall(mac) => { + let MacCallStmt { mac, attrs, style: _, tokens: _ } = &**mac; + walk_list!(visitor, visit_attribute, attrs); + try_visit!(visitor.visit_mac_call(mac)); } - AttrKind::DocComment(_kind, _sym) => {} - } - V::Result::output() -} - -pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) -> V::Result { - match args { - AttrArgs::Empty => {} - AttrArgs::Delimited(_args) => {} - AttrArgs::Eq { expr, .. } => try_visit!(visitor.visit_expr(expr)), } V::Result::output() } |
