From 9b0ad97287c877c992ff15307adcb20c3583cbfb Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Mon, 9 Jun 2025 19:28:11 +0800 Subject: [PATCH] deduplicate the rest of AST walker functions --- compiler/rustc_ast/src/mut_visit.rs | 616 +------------ compiler/rustc_ast/src/visit.rs | 1215 ++++++++++++++------------ tests/crashes/139825.rs | 5 - tests/ui/check-cfg/hrtb-crash.rs | 7 + tests/ui/check-cfg/hrtb-crash.stderr | 13 + 5 files changed, 686 insertions(+), 1170 deletions(-) delete mode 100644 tests/crashes/139825.rs create mode 100644 tests/ui/check-cfg/hrtb-crash.rs create mode 100644 tests/ui/check-cfg/hrtb-crash.stderr diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 77cbdde61a426..71a47dcfcba2b 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -11,7 +11,7 @@ use std::ops::DerefMut; use std::panic; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; -use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_span::source_map::Spanned; use rustc_span::{Ident, Span}; use smallvec::{Array, SmallVec, smallvec}; use thin_vec::ThinVec; @@ -19,7 +19,7 @@ use thin_vec::ThinVec; use crate::ast::*; use crate::ptr::P; use crate::tokenstream::*; -use crate::visit::{AssocCtxt, BoundKind, FnCtxt, try_visit, visit_opt, walk_list}; +use crate::visit::{AssocCtxt, BoundKind, FnCtxt, VisitorResult, try_visit, visit_opt, walk_list}; pub trait ExpectOne { fn expect_one(self, err: &'static str) -> A::Item; @@ -32,7 +32,22 @@ impl ExpectOne for SmallVec { } } -pub trait MutVisitor: Sized { +mod sealed { + use rustc_ast_ir::visit::VisitorResult; + + /// This is for compatibility with the regular `Visitor`. + pub trait MutVisitorResult { + type Result: VisitorResult; + } + + impl MutVisitorResult for T { + type Result = (); + } +} + +use sealed::MutVisitorResult; + +pub trait MutVisitor: Sized + MutVisitorResult { // Methods in this trait have one of three forms: // // fn visit_t(&mut self, t: &mut T); // common @@ -227,14 +242,6 @@ pub trait MutVisitor: Sized { walk_generic_args(self, p); } - fn visit_angle_bracketed_parameter_data(&mut self, p: &mut AngleBracketedArgs) { - walk_angle_bracketed_parameter_data(self, p); - } - - fn visit_parenthesized_parameter_data(&mut self, p: &mut ParenthesizedArgs) { - walk_parenthesized_parameter_data(self, p); - } - fn visit_local(&mut self, l: &mut Local) { walk_local(self, l); } @@ -303,10 +310,6 @@ pub trait MutVisitor: Sized { walk_flat_map_expr_field(self, f) } - fn visit_where_clause(&mut self, where_clause: &mut WhereClause) { - walk_where_clause(self, where_clause); - } - fn flat_map_where_predicate( &mut self, where_predicate: WherePredicate, @@ -385,19 +388,14 @@ generate_flat_map_visitor_fns! { visit_generic_params, GenericParam, flat_map_generic_param; visit_stmts, Stmt, flat_map_stmt; visit_exprs, P, filter_map_expr; + visit_expr_fields, ExprField, flat_map_expr_field; visit_pat_fields, PatField, flat_map_pat_field; visit_variants, Variant, flat_map_variant; visit_assoc_items, P, flat_map_assoc_item, ctxt: AssocCtxt; -} - -#[inline] -fn visit_vec(elems: &mut Vec, mut visit_elem: F) -where - F: FnMut(&mut T), -{ - for elem in elems { - visit_elem(elem); - } + visit_where_predicates, WherePredicate, flat_map_where_predicate; + visit_params, Param, flat_map_param; + visit_field_defs, FieldDef, flat_map_field_def; + visit_arms, Arm, flat_map_arm; } #[inline] @@ -410,40 +408,12 @@ where } } -#[inline] -fn visit_opt(opt: &mut Option, mut visit_elem: F) -where - F: FnMut(&mut T), -{ - if let Some(elem) = opt { - visit_elem(elem); - } -} - fn visit_attrs(vis: &mut T, attrs: &mut AttrVec) { for attr in attrs.iter_mut() { vis.visit_attribute(attr); } } -fn visit_attr_args(vis: &mut T, args: &mut AttrArgs) { - match args { - AttrArgs::Empty => {} - AttrArgs::Delimited(args) => visit_delim_args(vis, args), - AttrArgs::Eq { eq_span, expr } => { - vis.visit_expr(expr); - vis.visit_span(eq_span); - } - } -} - -fn visit_delim_args(vis: &mut T, args: &mut DelimArgs) { - let DelimArgs { dspan, delim: _, tokens: _ } = args; - let DelimSpan { open, close } = dspan; - vis.visit_span(open); - vis.visit_span(close); -} - pub fn walk_flat_map_pat_field( vis: &mut T, mut fp: PatField, @@ -461,40 +431,11 @@ fn visit_nested_use_tree( vis.visit_use_tree(nested_tree); } -pub fn walk_arm(vis: &mut T, arm: &mut Arm) { - let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = arm; - vis.visit_id(id); - visit_attrs(vis, attrs); - vis.visit_pat(pat); - visit_opt(guard, |guard| vis.visit_expr(guard)); - visit_opt(body, |body| vis.visit_expr(body)); - vis.visit_span(span); -} - pub fn walk_flat_map_arm(vis: &mut T, mut arm: Arm) -> SmallVec<[Arm; 1]> { vis.visit_arm(&mut arm); smallvec![arm] } -fn walk_assoc_item_constraint( - vis: &mut T, - AssocItemConstraint { id, ident, gen_args, kind, span }: &mut AssocItemConstraint, -) { - vis.visit_id(id); - vis.visit_ident(ident); - if let Some(gen_args) = gen_args { - vis.visit_generic_args(gen_args); - } - match kind { - AssocItemConstraintKind::Equality { term } => match term { - Term::Ty(ty) => vis.visit_ty(ty), - Term::Const(c) => vis.visit_anon_const(c), - }, - AssocItemConstraintKind::Bound { bounds } => visit_bounds(vis, bounds, BoundKind::Bound), - } - vis.visit_span(span); -} - pub fn walk_flat_map_variant( vis: &mut T, mut variant: Variant, @@ -503,64 +444,6 @@ pub fn walk_flat_map_variant( smallvec![variant] } -fn walk_generic_args(vis: &mut T, generic_args: &mut GenericArgs) { - match generic_args { - GenericArgs::AngleBracketed(data) => vis.visit_angle_bracketed_parameter_data(data), - GenericArgs::Parenthesized(data) => vis.visit_parenthesized_parameter_data(data), - GenericArgs::ParenthesizedElided(span) => vis.visit_span(span), - } -} - -fn walk_generic_arg(vis: &mut T, arg: &mut GenericArg) { - match arg { - GenericArg::Lifetime(lt) => vis.visit_lifetime(lt), - GenericArg::Type(ty) => vis.visit_ty(ty), - GenericArg::Const(ct) => vis.visit_anon_const(ct), - } -} - -fn walk_angle_bracketed_parameter_data(vis: &mut T, data: &mut AngleBracketedArgs) { - let AngleBracketedArgs { args, span } = data; - visit_thin_vec(args, |arg| match arg { - AngleBracketedArg::Arg(arg) => vis.visit_generic_arg(arg), - AngleBracketedArg::Constraint(constraint) => vis.visit_assoc_item_constraint(constraint), - }); - vis.visit_span(span); -} - -fn walk_parenthesized_parameter_data(vis: &mut T, args: &mut ParenthesizedArgs) { - let ParenthesizedArgs { inputs, output, span, inputs_span } = args; - visit_thin_vec(inputs, |input| vis.visit_ty(input)); - vis.visit_fn_ret_ty(output); - vis.visit_span(span); - vis.visit_span(inputs_span); -} - -fn walk_attribute(vis: &mut T, attr: &mut Attribute) { - let Attribute { kind, id: _, style: _, span } = attr; - match kind { - AttrKind::Normal(normal) => { - let NormalAttr { item: AttrItem { unsafety: _, path, args, tokens: _ }, tokens: _ } = - &mut **normal; - vis.visit_path(path); - visit_attr_args(vis, args); - } - AttrKind::DocComment(_kind, _sym) => {} - } - vis.visit_span(span); -} - -fn walk_mac(vis: &mut T, mac: &mut MacCall) { - let MacCall { path, args } = mac; - vis.visit_path(path); - visit_delim_args(vis, args); -} - -fn walk_macro_def(vis: &mut T, macro_def: &mut MacroDef) { - let MacroDef { body, macro_rules: _ } = macro_def; - visit_delim_args(vis, body); -} - fn walk_meta_list_item(vis: &mut T, li: &mut MetaItemInner) { match li { MetaItemInner::MetaItem(mi) => vis.visit_meta_item(mi), @@ -578,138 +461,11 @@ fn walk_meta_item(vis: &mut T, mi: &mut MetaItem) { vis.visit_span(span); } -pub fn walk_param(vis: &mut T, param: &mut Param) { - let Param { attrs, id, pat, span, ty, is_placeholder: _ } = param; - vis.visit_id(id); - visit_attrs(vis, attrs); - vis.visit_pat(pat); - vis.visit_ty(ty); - vis.visit_span(span); -} - pub fn walk_flat_map_param(vis: &mut T, mut param: Param) -> SmallVec<[Param; 1]> { vis.visit_param(&mut param); smallvec![param] } -fn walk_closure_binder(vis: &mut T, binder: &mut ClosureBinder) { - match binder { - ClosureBinder::NotPresent => {} - ClosureBinder::For { span: _, generic_params } => { - generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); - } - } -} - -fn walk_fn(vis: &mut T, kind: FnKind<'_>) { - match kind { - FnKind::Fn( - _ctxt, - _vis, - Fn { - defaultness, - ident, - generics, - contract, - body, - sig: FnSig { header, decl, span }, - define_opaque, - }, - ) => { - // Visibility is visited as a part of the item. - visit_defaultness(vis, defaultness); - vis.visit_ident(ident); - vis.visit_fn_header(header); - vis.visit_generics(generics); - vis.visit_fn_decl(decl); - if let Some(contract) = contract { - vis.visit_contract(contract); - } - if let Some(body) = body { - vis.visit_block(body); - } - vis.visit_span(span); - - walk_define_opaques(vis, define_opaque); - } - FnKind::Closure(binder, coroutine_kind, decl, body) => { - vis.visit_closure_binder(binder); - coroutine_kind.as_mut().map(|coroutine_kind| vis.visit_coroutine_kind(coroutine_kind)); - vis.visit_fn_decl(decl); - vis.visit_expr(body); - } - } -} - -fn walk_contract(vis: &mut T, contract: &mut FnContract) { - let FnContract { requires, ensures } = contract; - if let Some(pred) = requires { - vis.visit_expr(pred); - } - if let Some(pred) = ensures { - vis.visit_expr(pred); - } -} - -fn walk_fn_decl(vis: &mut T, decl: &mut FnDecl) { - let FnDecl { inputs, output } = decl; - inputs.flat_map_in_place(|param| vis.flat_map_param(param)); - vis.visit_fn_ret_ty(output); -} - -fn walk_fn_ret_ty(vis: &mut T, fn_ret_ty: &mut FnRetTy) { - match fn_ret_ty { - FnRetTy::Default(span) => vis.visit_span(span), - FnRetTy::Ty(ty) => vis.visit_ty(ty), - } -} - -fn walk_param_bound(vis: &mut T, pb: &mut GenericBound) { - match pb { - GenericBound::Trait(trait_ref) => vis.visit_poly_trait_ref(trait_ref), - GenericBound::Outlives(lifetime) => walk_lifetime(vis, lifetime), - GenericBound::Use(args, span) => { - for arg in args { - vis.visit_precise_capturing_arg(arg); - } - vis.visit_span(span); - } - } -} - -fn walk_precise_capturing_arg(vis: &mut T, arg: &mut PreciseCapturingArg) { - match arg { - PreciseCapturingArg::Lifetime(lt) => { - vis.visit_lifetime(lt); - } - PreciseCapturingArg::Arg(path, id) => { - vis.visit_id(id); - vis.visit_path(path); - } - } -} - -pub fn walk_generic_param(vis: &mut T, param: &mut GenericParam) { - let GenericParam { id, ident, attrs, bounds, kind, colon_span, is_placeholder: _ } = param; - vis.visit_id(id); - visit_attrs(vis, attrs); - vis.visit_ident(ident); - visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::Bound)); - match kind { - GenericParamKind::Lifetime => {} - GenericParamKind::Type { default } => { - visit_opt(default, |default| vis.visit_ty(default)); - } - GenericParamKind::Const { ty, kw_span: _, default } => { - vis.visit_ty(ty); - visit_opt(default, |default| vis.visit_anon_const(default)); - } - } - if let Some(colon_span) = colon_span { - vis.visit_span(colon_span); - } -} - pub fn walk_flat_map_generic_param( vis: &mut T, mut param: GenericParam, @@ -718,13 +474,6 @@ pub fn walk_flat_map_generic_param( smallvec![param] } -fn walk_generics(vis: &mut T, generics: &mut Generics) { - let Generics { params, where_clause, span } = generics; - params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); - vis.visit_where_clause(where_clause); - vis.visit_span(span); -} - fn walk_ty_alias_where_clauses(vis: &mut T, tawcs: &mut TyAliasWhereClauses) { let TyAliasWhereClauses { before, after, split: _ } = tawcs; let TyAliasWhereClause { has_where_token: _, span: span_before } = before; @@ -733,70 +482,14 @@ fn walk_ty_alias_where_clauses(vis: &mut T, tawcs: &mut TyAliasWh vis.visit_span(span_after); } -fn walk_where_clause(vis: &mut T, wc: &mut WhereClause) { - let WhereClause { has_where_token: _, predicates, span } = wc; - predicates.flat_map_in_place(|predicate| vis.flat_map_where_predicate(predicate)); - vis.visit_span(span); -} - pub fn walk_flat_map_where_predicate( vis: &mut T, mut pred: WherePredicate, ) -> SmallVec<[WherePredicate; 1]> { - let WherePredicate { attrs, kind, id, span, is_placeholder: _ } = &mut pred; - vis.visit_id(id); - visit_attrs(vis, attrs); - vis.visit_where_predicate_kind(kind); - vis.visit_span(span); + walk_where_predicate(vis, &mut pred); smallvec![pred] } -pub fn walk_where_predicate_kind(vis: &mut T, kind: &mut WherePredicateKind) { - match kind { - WherePredicateKind::BoundPredicate(bp) => { - let WhereBoundPredicate { bound_generic_params, bounded_ty, bounds } = bp; - bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); - vis.visit_ty(bounded_ty); - visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::Bound)); - } - WherePredicateKind::RegionPredicate(rp) => { - let WhereRegionPredicate { lifetime, bounds } = rp; - vis.visit_lifetime(lifetime); - visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::Bound)); - } - WherePredicateKind::EqPredicate(ep) => { - let WhereEqPredicate { lhs_ty, rhs_ty } = ep; - vis.visit_ty(lhs_ty); - vis.visit_ty(rhs_ty); - } - } -} - -fn walk_variant_data(vis: &mut T, vdata: &mut VariantData) { - match vdata { - VariantData::Struct { fields, recovered: _ } => { - fields.flat_map_in_place(|field| vis.flat_map_field_def(field)); - } - VariantData::Tuple(fields, id) => { - vis.visit_id(id); - fields.flat_map_in_place(|field| vis.flat_map_field_def(field)); - } - VariantData::Unit(id) => vis.visit_id(id), - } -} - -pub fn walk_field_def(visitor: &mut T, fd: &mut FieldDef) { - let FieldDef { span, ident, vis, id, ty, attrs, is_placeholder: _, safety, default } = fd; - visitor.visit_id(id); - visit_attrs(visitor, attrs); - visitor.visit_vis(vis); - visit_safety(visitor, safety); - visit_opt(ident, |ident| visitor.visit_ident(ident)); - visitor.visit_ty(ty); - visit_opt(default, |default| visitor.visit_anon_const(default)); - visitor.visit_span(span); -} - pub fn walk_flat_map_field_def( vis: &mut T, mut fd: FieldDef, @@ -846,255 +539,6 @@ pub fn walk_flat_map_assoc_item( smallvec![item] } -fn walk_inline_asm(vis: &mut T, asm: &mut InlineAsm) { - // 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: _ } => vis.visit_expr(expr), - InlineAsmOperand::Out { expr: None, reg: _, late: _ } => {} - InlineAsmOperand::SplitInOut { in_expr, out_expr, reg: _, late: _ } => { - vis.visit_expr(in_expr); - if let Some(out_expr) = out_expr { - vis.visit_expr(out_expr); - } - } - InlineAsmOperand::Const { anon_const } => vis.visit_anon_const(anon_const), - InlineAsmOperand::Sym { sym } => vis.visit_inline_asm_sym(sym), - InlineAsmOperand::Label { block } => vis.visit_block(block), - } - vis.visit_span(span); - } -} - -fn walk_inline_asm_sym( - vis: &mut T, - InlineAsmSym { id, qself, path }: &mut InlineAsmSym, -) { - vis.visit_id(id); - vis.visit_qself(qself); - vis.visit_path(path); -} - -fn walk_format_args(vis: &mut T, fmt: &mut FormatArgs) { - // FIXME: visit the template exhaustively. - let FormatArgs { span, template: _, arguments, uncooked_fmt_str: _ } = fmt; - for FormatArgument { kind, expr } in arguments.all_args_mut() { - match kind { - FormatArgumentKind::Named(ident) | FormatArgumentKind::Captured(ident) => { - vis.visit_ident(ident) - } - FormatArgumentKind::Normal => {} - } - vis.visit_expr(expr); - } - vis.visit_span(span); -} - -pub fn walk_expr(vis: &mut T, Expr { kind, id, span, attrs, tokens: _ }: &mut Expr) { - vis.visit_id(id); - visit_attrs(vis, attrs); - match kind { - ExprKind::Array(exprs) => visit_exprs(vis, exprs), - ExprKind::ConstBlock(anon_const) => { - vis.visit_anon_const(anon_const); - } - ExprKind::Repeat(expr, count) => { - vis.visit_expr(expr); - vis.visit_anon_const(count); - } - ExprKind::Tup(exprs) => visit_exprs(vis, exprs), - ExprKind::Call(f, args) => { - vis.visit_expr(f); - visit_exprs(vis, args); - } - ExprKind::MethodCall(box MethodCall { - seg: PathSegment { ident, id, args: seg_args }, - receiver, - args: call_args, - span, - }) => { - vis.visit_method_receiver_expr(receiver); - vis.visit_id(id); - vis.visit_ident(ident); - visit_opt(seg_args, |args| vis.visit_generic_args(args)); - visit_exprs(vis, call_args); - vis.visit_span(span); - } - ExprKind::Binary(binop, lhs, rhs) => { - vis.visit_expr(lhs); - vis.visit_expr(rhs); - vis.visit_span(&mut binop.span); - } - ExprKind::Unary(_unop, ohs) => vis.visit_expr(ohs), - ExprKind::Cast(expr, ty) => { - vis.visit_expr(expr); - vis.visit_ty(ty); - } - ExprKind::Type(expr, ty) => { - vis.visit_expr(expr); - vis.visit_ty(ty); - } - ExprKind::AddrOf(_kind, _mut, ohs) => vis.visit_expr(ohs), - ExprKind::Let(pat, scrutinee, span, _recovered) => { - vis.visit_pat(pat); - vis.visit_expr(scrutinee); - vis.visit_span(span); - } - ExprKind::If(cond, tr, fl) => { - vis.visit_expr(cond); - vis.visit_block(tr); - visit_opt(fl, |fl| ensure_sufficient_stack(|| vis.visit_expr(fl))); - } - ExprKind::While(cond, body, label) => { - visit_opt(label, |label| vis.visit_label(label)); - vis.visit_expr(cond); - vis.visit_block(body); - } - ExprKind::ForLoop { pat, iter, body, label, kind: _ } => { - visit_opt(label, |label| vis.visit_label(label)); - vis.visit_pat(pat); - vis.visit_expr(iter); - vis.visit_block(body); - } - ExprKind::Loop(body, label, span) => { - visit_opt(label, |label| vis.visit_label(label)); - vis.visit_block(body); - vis.visit_span(span); - } - ExprKind::Match(expr, arms, _kind) => { - vis.visit_expr(expr); - arms.flat_map_in_place(|arm| vis.flat_map_arm(arm)); - } - ExprKind::Closure(box Closure { - binder, - capture_clause, - constness, - coroutine_kind, - movability: _, - fn_decl, - body, - fn_decl_span, - fn_arg_span, - }) => { - visit_constness(vis, constness); - vis.visit_capture_by(capture_clause); - vis.visit_fn(FnKind::Closure(binder, coroutine_kind, fn_decl, body), *span, *id); - vis.visit_span(fn_decl_span); - vis.visit_span(fn_arg_span); - } - ExprKind::Block(blk, label) => { - visit_opt(label, |label| vis.visit_label(label)); - vis.visit_block(blk); - } - ExprKind::Gen(_capture_by, body, _kind, decl_span) => { - vis.visit_block(body); - vis.visit_span(decl_span); - } - ExprKind::Await(expr, await_kw_span) => { - vis.visit_expr(expr); - vis.visit_span(await_kw_span); - } - ExprKind::Use(expr, use_kw_span) => { - vis.visit_expr(expr); - vis.visit_span(use_kw_span); - } - ExprKind::Assign(el, er, span) => { - vis.visit_expr(el); - vis.visit_expr(er); - vis.visit_span(span); - } - ExprKind::AssignOp(_op, el, er) => { - vis.visit_expr(el); - vis.visit_expr(er); - } - ExprKind::Field(el, ident) => { - vis.visit_expr(el); - vis.visit_ident(ident); - } - ExprKind::Index(el, er, brackets_span) => { - vis.visit_expr(el); - vis.visit_expr(er); - vis.visit_span(brackets_span); - } - ExprKind::Range(e1, e2, _lim) => { - visit_opt(e1, |e1| vis.visit_expr(e1)); - visit_opt(e2, |e2| vis.visit_expr(e2)); - } - ExprKind::Underscore => {} - ExprKind::Path(qself, path) => { - vis.visit_qself(qself); - vis.visit_path(path); - } - ExprKind::Break(label, expr) => { - visit_opt(label, |label| vis.visit_label(label)); - visit_opt(expr, |expr| vis.visit_expr(expr)); - } - ExprKind::Continue(label) => { - visit_opt(label, |label| vis.visit_label(label)); - } - ExprKind::Ret(expr) => { - visit_opt(expr, |expr| vis.visit_expr(expr)); - } - ExprKind::Yeet(expr) => { - visit_opt(expr, |expr| vis.visit_expr(expr)); - } - ExprKind::Become(expr) => vis.visit_expr(expr), - ExprKind::InlineAsm(asm) => vis.visit_inline_asm(asm), - ExprKind::FormatArgs(fmt) => vis.visit_format_args(fmt), - ExprKind::OffsetOf(container, fields) => { - vis.visit_ty(container); - for field in fields.iter_mut() { - vis.visit_ident(field); - } - } - ExprKind::MacCall(mac) => vis.visit_mac_call(mac), - ExprKind::Struct(se) => { - let StructExpr { qself, path, fields, rest } = se.deref_mut(); - vis.visit_qself(qself); - vis.visit_path(path); - fields.flat_map_in_place(|field| vis.flat_map_expr_field(field)); - match rest { - StructRest::Base(expr) => vis.visit_expr(expr), - StructRest::Rest(_span) => {} - StructRest::None => {} - } - } - ExprKind::Paren(expr) => { - vis.visit_expr(expr); - } - ExprKind::Yield(kind) => { - let expr = kind.expr_mut(); - if let Some(expr) = expr { - vis.visit_expr(expr); - } - } - ExprKind::Try(expr) => vis.visit_expr(expr), - ExprKind::TryBlock(body) => vis.visit_block(body), - ExprKind::Lit(_token) => {} - ExprKind::IncludedBytes(_bytes) => {} - ExprKind::UnsafeBinderCast(_kind, expr, ty) => { - vis.visit_expr(expr); - if let Some(ty) = ty { - vis.visit_ty(ty); - } - } - ExprKind::Err(_guar) => {} - ExprKind::Dummy => {} - } - vis.visit_span(span); -} - pub fn walk_filter_map_expr(vis: &mut T, mut e: P) -> Option> { vis.visit_expr(&mut e); Some(e) @@ -1139,18 +583,6 @@ fn walk_flat_map_stmt_kind(vis: &mut T, kind: StmtKind) -> SmallV } } -fn walk_vis(vis: &mut T, visibility: &mut Visibility) { - let Visibility { kind, span, tokens: _ } = visibility; - match kind { - VisibilityKind::Public | VisibilityKind::Inherited => {} - VisibilityKind::Restricted { path, id, shorthand: _ } => { - vis.visit_id(id); - vis.visit_path(path); - } - } - vis.visit_span(span); -} - fn walk_capture_by(vis: &mut T, capture_by: &mut CaptureBy) { match capture_by { CaptureBy::Ref => {} diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index d2f22b04a671f..c88aa5c33ea90 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 { @@ -237,8 +239,8 @@ pub trait Visitor<'ast>: Sized { 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_macro_def(&mut self, macro_def: &'ast MacroDef) -> Self::Result { + walk_macro_def(self, macro_def) } fn visit_path(&mut self, path: &'ast Path) -> Self::Result { walk_path(self, path) @@ -320,8 +322,8 @@ macro_rules! common_visitor_and_walkers { id: NodeId, visibility: &$($lt)? $($mut)? Visibility, ctxt: Self::Ctxt, - visitor: &mut V, - ) $(-> >::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 +331,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) $(-> >::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 +344,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) $(-> >::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) $(-> >::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) $(-> >::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 => { - $(>::Result::output())? + V::Result::output() } } } - fn visit_defaultness<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, defaultness: &$($lt)? $($mut)? Defaultness) $(-> >::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 => { - $(>::Result::output())? + V::Result::output() } } } @@ -377,9 +379,9 @@ macro_rules! common_visitor_and_walkers { fn visit_polarity<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, polarity: &$($lt)? $($mut)? ImplPolarity, - ) $(-> >::Result)? { + ) -> V::Result { match polarity { - ImplPolarity::Positive => { $(>::Result::output())? } + ImplPolarity::Positive => { V::Result::output() } ImplPolarity::Negative(span) => visit_span(vis, span), } } @@ -390,7 +392,7 @@ macro_rules! common_visitor_and_walkers { fn visit_modifiers<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, m: &$($lt)? $($mut)? TraitBoundModifiers - ) $(-> >::Result)? { + ) -> V::Result { let TraitBoundModifiers { constness, asyncness, polarity } = m; match constness { BoundConstness::Never => {} @@ -404,26 +406,26 @@ macro_rules! common_visitor_and_walkers { BoundPolarity::Positive => {} BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => try_visit!(visit_span(vis, span)), } - $(>::Result::output())? + V::Result::output() } - fn visit_bounds<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, bounds: &$($lt)? $($mut)? GenericBounds, ctxt: BoundKind) $(-> >::Result)? { + 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); - $(>::Result::output())? + V::Result::output() } - pub fn walk_label<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, Label { ident }: &$($lt)? $($mut)? Label) $(-> >::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) $(-> >::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) $(-> >::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 +434,7 @@ macro_rules! common_visitor_and_walkers { visitor: &mut V, item: &$($mut)? $($lt)? Item, ctxt: K::Ctxt, - ) $(-> >::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 +446,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_item<$($lt,)? V: $Visitor$(<$lt>)?, K: WalkItemKind>( visitor: &mut V, item: &$($mut)? $($lt)? Item, - ) $(-> >::Result)? { + ) -> V::Result { walk_item_ctxt(visitor, item, ()) } @@ -452,7 +454,7 @@ macro_rules! common_visitor_and_walkers { visitor: &mut V, item: &$($mut)? $($lt)? AssocItem, ctxt: AssocCtxt, - ) $(-> >::Result)? { + ) -> V::Result { walk_item_ctxt(visitor, item, ctxt) } @@ -465,7 +467,7 @@ macro_rules! common_visitor_and_walkers { visibility: &$($lt)? $($mut)? Visibility, _ctxt: Self::Ctxt, vis: &mut V, - ) $(-> >::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 +507,7 @@ macro_rules! common_visitor_and_walkers { } ModKind::Unloaded => {} } - $(>::Result::output())? + V::Result::output() } ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm), ItemKind::GlobalAsm(asm) => vis.visit_inline_asm(asm), @@ -526,7 +528,7 @@ macro_rules! common_visitor_and_walkers { $(${ignore($mut)} walk_ty_alias_where_clauses(vis, where_clauses); )? - $(>::Result::output())? + V::Result::output() } ItemKind::Enum(ident, generics, enum_definition) => { try_visit!(vis.visit_ident(ident)); @@ -590,7 +592,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); - $(>::Result::output())? + V::Result::output() } ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => { try_visit!(vis.visit_qself(qself)); @@ -602,7 +604,7 @@ macro_rules! common_visitor_and_walkers { } } visit_opt!(vis, visit_block, body); - $(>::Result::output())? + V::Result::output() } } } @@ -611,7 +613,7 @@ macro_rules! common_visitor_and_walkers { fn walk_const_item<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, item: &$($lt)? $($mut)? ConstItem, - ) $(-> >::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 +623,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) $(-> >::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 +632,14 @@ macro_rules! common_visitor_and_walkers { fn walk_define_opaques<$($lt,)? V: $Visitor$(<$lt>)?>( visitor: &mut V, define_opaque: &$($lt)? $($mut)? Option>, - ) $(-> >::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)); } } - $(>::Result::output())? + V::Result::output() } impl WalkItemKind for AssocItemKind { @@ -649,7 +651,7 @@ macro_rules! common_visitor_and_walkers { visibility: &$($lt)? $($mut)? Visibility, ctxt: Self::Ctxt, vis: &mut V, - ) $(-> >::Result)? { + ) -> V::Result { match self { AssocItemKind::Const(item) => { walk_const_item(vis, item) @@ -674,7 +676,7 @@ macro_rules! common_visitor_and_walkers { $(${ignore($mut)} walk_ty_alias_where_clauses(vis, where_clauses); )? - $(>::Result::output())? + V::Result::output() } AssocItemKind::MacCall(mac) => { vis.visit_mac_call(mac) @@ -694,7 +696,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); - $(>::Result::output())? + V::Result::output() } AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => { try_visit!(vis.visit_qself(qself)); @@ -706,7 +708,7 @@ macro_rules! common_visitor_and_walkers { } } visit_opt!(vis, visit_block, body); - $(>::Result::output())? + V::Result::output() } } } @@ -721,7 +723,7 @@ macro_rules! common_visitor_and_walkers { visibility: &$($lt)? $($mut)? Visibility, _ctxt: Self::Ctxt, vis: &mut V, - ) $(-> >::Result)? { + ) -> V::Result { match self { ForeignItemKind::Static(box StaticItem { ident, @@ -756,7 +758,7 @@ macro_rules! common_visitor_and_walkers { $(${ignore($mut)} walk_ty_alias_where_clauses(vis, where_clauses); )? - $(>::Result::output())? + V::Result::output() } ForeignItemKind::MacCall(mac) => { vis.visit_mac_call(mac) @@ -768,7 +770,7 @@ macro_rules! common_visitor_and_walkers { fn walk_coroutine_kind<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, coroutine_kind: &$($lt)? $($mut)? CoroutineKind, - ) $(-> >::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 +783,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_pat<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, pattern: &$($lt)? $($mut)? Pat - ) $(-> >::Result)? { + ) -> V::Result { let Pat { id, kind, span, tokens: _ } = pattern; try_visit!(visit_id(vis, id)); match kind { @@ -832,7 +834,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_anon_const<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, constant: &$($lt)? $($mut)? AnonConst, - ) $(-> >::Result)? { + ) -> V::Result { let AnonConst { id, value } = constant; try_visit!(visit_id(vis, id)); vis.visit_expr(value) @@ -841,18 +843,18 @@ macro_rules! common_visitor_and_walkers { pub fn walk_path_segment<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, segment: &$($lt)? $($mut)? PathSegment, - ) $(-> >::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); - $(>::Result::output())? + V::Result::output() } pub fn walk_block<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, block: &$($lt)? $($mut)? Block - ) $(-> >::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 +864,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_ty<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, ty: &$($lt)? $($mut)? Ty - ) $(-> >::Result)? { + ) -> V::Result { let Ty { id, kind, span, tokens: _ } = ty; try_visit!(visit_id(vis, id)); match kind { @@ -920,7 +922,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_crate<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, krate: &$($lt)? $($mut)? Crate, - ) $(-> >::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 +935,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_local<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, local: &$($lt)? $($mut)? Local, - ) $(-> >::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 +963,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_poly_trait_ref<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, p: &$($lt)? $($mut)? PolyTraitRef, - ) $(-> >::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 +974,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, - ) $(-> >::Result)? { + ) -> V::Result { try_visit!(vis.visit_path(path)); visit_id(vis, ref_id) } @@ -980,7 +982,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_variant<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, variant: &$($lt)? $($mut)? Variant, - ) $(-> >::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); @@ -995,7 +997,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_expr_field<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, f: &$($lt)? $($mut)? ExprField, - ) $(-> >::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 +1009,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_pat_field<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, fp: &$($lt)? $($mut)? PatField, - ) $(-> >::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 +1021,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_ty_pat<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, tp: &$($lt)? $($mut)? TyPat, - ) $(-> >::Result)? { + ) -> V::Result { let TyPat { id, kind, span, tokens: _ } = tp; try_visit!(visit_id(vis, id)); match kind { @@ -1036,19 +1038,19 @@ macro_rules! common_visitor_and_walkers { fn walk_qself<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, qself: &$($lt)? $($mut)? Option>, - ) $(-> >::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)); } - $(>::Result::output())? + V::Result::output() } pub fn walk_path<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, path: &$($lt)? $($mut)? Path, - ) $(-> >::Result)? { + ) -> V::Result { let Path { span, segments, tokens: _ } = path; walk_list!(vis, visit_path_segment, segments); visit_span(vis, span) @@ -1057,7 +1059,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_use_tree<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, use_tree: &$($lt)? $($mut)? UseTree, - ) $(-> >::Result)? { + ) -> V::Result { let UseTree { prefix, kind, span } = use_tree; try_visit!(vis.visit_path(prefix)); match kind { @@ -1075,573 +1077,640 @@ 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, visit_item; - visit_foreign_items, P, 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, 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_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_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, + }) => { + 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() } - } - 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_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) + } -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_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_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); + 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) + } + } } - WherePredicateKind::RegionPredicate(WhereRegionPredicate { lifetime, bounds }) => { - try_visit!(visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound)); - walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); + + 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), + } } - WherePredicateKind::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty }) => { - try_visit!(visitor.visit_ty(lhs_ty)); - try_visit!(visitor.visit_ty(rhs_ty)); + + 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) } - } - 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() -} + 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_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) -} + 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() + } -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_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: _ } = 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) } - } - 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_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)); + 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_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() -} + visit_span(vis, span) + } -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)); + 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_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_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_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)) + 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 => {} } - InlineAsmOperand::Sym { sym } => try_visit!(visitor.visit_inline_asm_sym(sym)), - InlineAsmOperand::Label { block } => try_visit!(visitor.visit_block(block)), + 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_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_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) => {} } - 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 => {} + 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() } - 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 => {} - } - - 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, visit_item; + visit_foreign_items, P, visit_foreign_item; + visit_generic_params, GenericParam, visit_generic_param; + visit_stmts, Stmt, visit_stmt; + visit_exprs, P, 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, 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; 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() } diff --git a/tests/crashes/139825.rs b/tests/crashes/139825.rs deleted file mode 100644 index 8c5b6b80f0bad..0000000000000 --- a/tests/crashes/139825.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ known-bug: #139825 -//@compile-flags: --check-cfg=cfg(docsrs,test) --crate-type lib -struct a -where - for<#[cfg(b)] c> u8:; diff --git a/tests/ui/check-cfg/hrtb-crash.rs b/tests/ui/check-cfg/hrtb-crash.rs new file mode 100644 index 0000000000000..f2bce33f9f9ad --- /dev/null +++ b/tests/ui/check-cfg/hrtb-crash.rs @@ -0,0 +1,7 @@ +// https://github.com/rust-lang/rust/issues/139825 +//@ compile-flags: --check-cfg=cfg(docsrs,test) --crate-type lib +//@ check-pass +struct A +where + for<#[cfg(b)] c> u8:; +//~^ WARN: unexpected `cfg` condition name diff --git a/tests/ui/check-cfg/hrtb-crash.stderr b/tests/ui/check-cfg/hrtb-crash.stderr new file mode 100644 index 0000000000000..431cf9cf53e25 --- /dev/null +++ b/tests/ui/check-cfg/hrtb-crash.stderr @@ -0,0 +1,13 @@ +warning: unexpected `cfg` condition name: `b` + --> $DIR/hrtb-crash.rs:6:15 + | +LL | for<#[cfg(b)] c> u8:; + | ^ help: found config with similar value: `target_feature = "b"` + | + = help: expected names are: `FALSE`, `docsrs`, and `test` and 31 more + = help: to expect this configuration use `--check-cfg=cfg(b)` + = note: see for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted +