use helper macro for flat_map vs visit_list, initial dedups

This commit is contained in:
Deadbeef 2025-06-05 13:47:21 +00:00
parent 425e142686
commit 91b77e080f
2 changed files with 139 additions and 153 deletions

View file

@ -211,10 +211,6 @@ pub trait MutVisitor: Sized {
walk_ident(self, i);
}
fn visit_modifiers(&mut self, m: &mut TraitBoundModifiers) {
walk_modifiers(self, m);
}
fn visit_path(&mut self, p: &mut Path) {
walk_path(self, p);
}
@ -367,6 +363,28 @@ pub trait MutVisitor: Sized {
super::common_visitor_and_walkers!((mut) MutVisitor);
macro_rules! generate_flat_map_visitor_fns {
($($name:ident, $Ty:ty, $flat_map_fn:ident;)+) => {
$(
fn $name<V: MutVisitor>(
vis: &mut V,
values: &mut ThinVec<$Ty>,
) {
values.flat_map_in_place(|value| vis.$flat_map_fn(value));
}
)+
}
}
generate_flat_map_visitor_fns! {
visit_items, P<Item>, flat_map_item;
visit_foreign_items, P<ForeignItem>, flat_map_foreign_item;
visit_generic_params, GenericParam, flat_map_generic_param;
visit_stmts, Stmt, flat_map_stmt;
visit_exprs, P<Expr>, filter_map_expr;
visit_pat_fields, PatField, flat_map_pat_field;
}
#[inline]
fn visit_vec<T, F>(elems: &mut Vec<T>, mut visit_elem: F)
where
@ -403,15 +421,6 @@ fn visit_attrs<T: MutVisitor>(vis: &mut T, attrs: &mut AttrVec) {
}
}
#[allow(unused)]
fn visit_exprs<T: MutVisitor>(vis: &mut T, exprs: &mut Vec<P<Expr>>) {
exprs.flat_map_in_place(|expr| vis.filter_map_expr(expr))
}
fn visit_thin_exprs<T: MutVisitor>(vis: &mut T, exprs: &mut ThinVec<P<Expr>>) {
exprs.flat_map_in_place(|expr| vis.filter_map_expr(expr))
}
fn visit_attr_args<T: MutVisitor>(vis: &mut T, args: &mut AttrArgs) {
match args {
AttrArgs::Empty => {}
@ -583,27 +592,6 @@ fn walk_parenthesized_parameter_data<T: MutVisitor>(vis: &mut T, args: &mut Pare
vis.visit_span(inputs_span);
}
fn walk_local<T: MutVisitor>(vis: &mut T, local: &mut Local) {
let Local { id, super_, pat, ty, kind, span, colon_sp, attrs, tokens: _ } = local;
visit_opt(super_, |sp| vis.visit_span(sp));
vis.visit_id(id);
visit_attrs(vis, attrs);
vis.visit_pat(pat);
visit_opt(ty, |ty| vis.visit_ty(ty));
match kind {
LocalKind::Decl => {}
LocalKind::Init(init) => {
vis.visit_expr(init);
}
LocalKind::InitElse(init, els) => {
vis.visit_expr(init);
vis.visit_block(els);
}
}
visit_opt(colon_sp, |sp| vis.visit_span(sp));
vis.visit_span(span);
}
fn walk_attribute<T: MutVisitor>(vis: &mut T, attr: &mut Attribute) {
let Attribute { kind, id: _, style: _, span } = attr;
match kind {
@ -858,30 +846,6 @@ fn walk_trait_ref<T: MutVisitor>(vis: &mut T, TraitRef { path, ref_id }: &mut Tr
vis.visit_path(path);
}
fn walk_poly_trait_ref<T: MutVisitor>(vis: &mut T, p: &mut PolyTraitRef) {
let PolyTraitRef { bound_generic_params, modifiers, trait_ref, span } = p;
vis.visit_modifiers(modifiers);
bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
vis.visit_trait_ref(trait_ref);
vis.visit_span(span);
}
fn walk_modifiers<V: MutVisitor>(vis: &mut V, m: &mut TraitBoundModifiers) {
let TraitBoundModifiers { constness, asyncness, polarity } = m;
match constness {
BoundConstness::Never => {}
BoundConstness::Always(span) | BoundConstness::Maybe(span) => vis.visit_span(span),
}
match asyncness {
BoundAsyncness::Normal => {}
BoundAsyncness::Async(span) => vis.visit_span(span),
}
match polarity {
BoundPolarity::Positive => {}
BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => vis.visit_span(span),
}
}
pub fn walk_field_def<T: MutVisitor>(visitor: &mut T, fd: &mut FieldDef) {
let FieldDef { span, ident, vis, id, ty, attrs, is_placeholder: _, safety, default } = fd;
visitor.visit_id(id);
@ -930,16 +894,6 @@ pub fn walk_item_kind<K: WalkItemKind>(
kind.walk(span, id, visibility, ctxt, vis)
}
pub fn walk_crate<T: MutVisitor>(vis: &mut T, krate: &mut Crate) {
let Crate { attrs, items, spans, id, is_placeholder: _ } = krate;
vis.visit_id(id);
visit_attrs(vis, attrs);
items.flat_map_in_place(|item| vis.flat_map_item(item));
let ModSpans { inner_span, inject_use_span } = spans;
vis.visit_span(inner_span);
vis.visit_span(inject_use_span);
}
pub fn walk_flat_map_item(vis: &mut impl MutVisitor, mut item: P<Item>) -> SmallVec<[P<Item>; 1]> {
vis.visit_item(&mut item);
smallvec![item]
@ -1021,7 +975,7 @@ pub fn walk_expr<T: MutVisitor>(vis: &mut T, Expr { kind, id, span, attrs, token
vis.visit_id(id);
visit_attrs(vis, attrs);
match kind {
ExprKind::Array(exprs) => visit_thin_exprs(vis, exprs),
ExprKind::Array(exprs) => visit_exprs(vis, exprs),
ExprKind::ConstBlock(anon_const) => {
vis.visit_anon_const(anon_const);
}
@ -1029,10 +983,10 @@ pub fn walk_expr<T: MutVisitor>(vis: &mut T, Expr { kind, id, span, attrs, token
vis.visit_expr(expr);
vis.visit_anon_const(count);
}
ExprKind::Tup(exprs) => visit_thin_exprs(vis, exprs),
ExprKind::Tup(exprs) => visit_exprs(vis, exprs),
ExprKind::Call(f, args) => {
vis.visit_expr(f);
visit_thin_exprs(vis, args);
visit_exprs(vis, args);
}
ExprKind::MethodCall(box MethodCall {
seg: PathSegment { ident, id, args: seg_args },
@ -1044,7 +998,7 @@ pub fn walk_expr<T: MutVisitor>(vis: &mut T, Expr { kind, id, span, attrs, token
vis.visit_id(id);
vis.visit_ident(ident);
visit_opt(seg_args, |args| vis.visit_generic_args(args));
visit_thin_exprs(vis, call_args);
visit_exprs(vis, call_args);
vis.visit_span(span);
}
ExprKind::Binary(binop, lhs, rhs) => {

View file

@ -378,13 +378,39 @@ 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)? {
fn visit_polarity<$($lt,)? V: $Visitor$(<$lt>)?>(
vis: &mut V,
polarity: &$($lt)? $($mut)? ImplPolarity,
) $(-> <V as Visitor<$lt>>::Result)? {
match polarity {
ImplPolarity::Positive => { $(<V as Visitor<$lt>>::Result::output())? }
ImplPolarity::Negative(span) => visit_span(vis, span),
}
}
$(${ignore($lt)}
#[inline]
)?
fn visit_modifiers<$($lt,)? V: $Visitor$(<$lt>)?>(
vis: &mut V,
m: &$($lt)? $($mut)? TraitBoundModifiers
) $(-> <V as Visitor<$lt>>::Result)? {
let TraitBoundModifiers { constness, asyncness, polarity } = m;
match constness {
BoundConstness::Never => {}
BoundConstness::Always(span) | BoundConstness::Maybe(span) => try_visit!(visit_span(vis, span)),
}
match asyncness {
BoundAsyncness::Normal => {}
BoundAsyncness::Async(span) => try_visit!(visit_span(vis, span)),
}
match polarity {
BoundPolarity::Positive => {}
BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => try_visit!(visit_span(vis, span)),
}
$(<V as Visitor<$lt>>::Result::output())?
}
fn visit_bounds<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, bounds: &$($lt)? $($mut)? GenericBounds, ctxt: BoundKind) $(-> <V as Visitor<$lt>>::Result)? {
walk_list!(visitor, visit_param_bound, bounds, ctxt);
$(<V as Visitor<$lt>>::Result::output())?
@ -478,12 +504,7 @@ macro_rules! common_visitor_and_walkers {
ModSpans { inner_span, inject_use_span },
_,
) => {
$(${ignore($mut)}
items.flat_map_in_place(|item| vis.flat_map_item(item));
)?
$(${ignore($lt)}
walk_list!(vis, visit_item, items);
)?
try_visit!(visit_items(vis, items));
try_visit!(visit_span(vis, inner_span));
try_visit!(visit_span(vis, inject_use_span));
}
@ -616,7 +637,10 @@ 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)? {
fn walk_const_item<$($lt,)? V: $Visitor$(<$lt>)?>(
vis: &mut V,
item: &$($lt)? $($mut)? ConstItem,
) $(-> <V as Visitor<$lt>>::Result)? {
let ConstItem { defaultness, ident, generics, ty, expr, define_opaque } = item;
try_visit!(visit_defaultness(vis, defaultness));
try_visit!(vis.visit_ident(ident));
@ -629,13 +653,7 @@ macro_rules! common_visitor_and_walkers {
fn walk_foreign_mod<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, foreign_mod: &$($lt)? $($mut)? ForeignMod) $(-> <V as Visitor<$lt>>::Result)? {
let ForeignMod { extern_span: _, safety, abi: _, items } = foreign_mod;
try_visit!(visit_safety(vis, safety));
$(${ignore($mut)}
items.flat_map_in_place(|item| vis.flat_map_foreign_item(item));
)?
$(
walk_list!(vis, visit_foreign_item, items);
<V as Visitor<$lt>>::Result::output()
)?
visit_foreign_items(vis, items)
}
fn walk_define_opaques<$($lt,)? V: $Visitor$(<$lt>)?>(
@ -780,15 +798,13 @@ macro_rules! common_visitor_and_walkers {
vis: &mut V,
coroutine_kind: &$($lt)? $($mut)? CoroutineKind,
) $(-> <V as Visitor<$lt>>::Result)? {
match coroutine_kind {
CoroutineKind::Async { span, closure_id, return_impl_trait_id }
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 } => {
try_visit!(visit_id(vis, closure_id));
try_visit!(visit_id(vis, return_impl_trait_id));
visit_span(vis, span)
}
}
| CoroutineKind::AsyncGen { span, closure_id, return_impl_trait_id })
= coroutine_kind;
try_visit!(visit_id(vis, closure_id));
try_visit!(visit_id(vis, return_impl_trait_id));
visit_span(vis, span)
}
pub fn walk_pat<$($lt,)? V: $Visitor$(<$lt>)?>(
@ -817,15 +833,7 @@ macro_rules! common_visitor_and_walkers {
PatKind::Struct(opt_qself, path, fields, _rest) => {
try_visit!(vis.visit_qself(opt_qself));
try_visit!(vis.visit_path(path));
$(
${ignore($lt)}
walk_list!(vis, visit_pat_field, fields);
)?
$(
${ignore($mut)}
fields.flat_map_in_place(|field| vis.flat_map_pat_field(field));
)?
try_visit!(visit_pat_fields(vis, fields));
}
PatKind::Box(subpattern) | PatKind::Deref(subpattern) | PatKind::Paren(subpattern) => {
try_visit!(vis.visit_pat(subpattern));
@ -876,14 +884,7 @@ macro_rules! common_visitor_and_walkers {
) $(-> <V as Visitor<$lt>>::Result)? {
let Block { stmts, id, rules: _, span, tokens: _ } = block;
try_visit!(visit_id(vis, id));
$(
${ignore($lt)}
walk_list!(vis, visit_stmt, stmts);
)?
$(
${ignore($mut)}
stmts.flat_map_in_place(|stmt| vis.flat_map_stmt(stmt));
)?
try_visit!(visit_stmts(vis, stmts));
visit_span(vis, span)
}
@ -911,28 +912,13 @@ macro_rules! common_visitor_and_walkers {
let BareFnTy { safety, ext: _, generic_params, decl, decl_span } =
&$($mut)? **function_declaration;
visit_safety(vis, safety);
$(
${ignore($lt)}
walk_list!(vis, visit_generic_param, generic_params);
)?
$(
${ignore($mut)}
generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
)?
try_visit!(visit_generic_params(vis, generic_params));
try_visit!(vis.visit_fn_decl(decl));
try_visit!(visit_span(vis, decl_span));
}
TyKind::UnsafeBinder(binder) => {
$(
${ignore($lt)}
walk_list!(vis, visit_generic_param, &binder.generic_params);
)?
$(
${ignore($mut)}
binder.generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
)?
try_visit!(vis.visit_ty(&$($mut)?binder.inner_ty));
try_visit!(visit_generic_params(vis, &$($mut)? binder.generic_params));
try_visit!(vis.visit_ty(&$($mut)? binder.inner_ty));
}
TyKind::Path(maybe_qself, path) => {
try_visit!(vis.visit_qself(maybe_qself));
@ -959,37 +945,83 @@ macro_rules! common_visitor_and_walkers {
}
visit_span(vis, span)
}
pub fn walk_crate<$($lt,)? V: $Visitor$(<$lt>)?>(
vis: &mut V,
krate: &$($lt)? $($mut)? Crate,
) $(-> <V as Visitor<$lt>>::Result)? {
let Crate { attrs, items, spans, id, is_placeholder: _ } = krate;
try_visit!(visit_id(vis, id));
walk_list!(vis, visit_attribute, attrs);
try_visit!(visit_items(vis, items));
let ModSpans { inner_span, inject_use_span } = spans;
try_visit!(visit_span(vis, inner_span));
visit_span(vis, inject_use_span)
}
pub fn walk_local<$($lt,)? V: $Visitor$(<$lt>)?>(
vis: &mut V,
local: &$($lt)? $($mut)? Local,
) $(-> <V as Visitor<$lt>>::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));
}
try_visit!(visit_id(vis, id));
walk_list!(vis, visit_attribute, attrs);
try_visit!(vis.visit_pat(pat));
visit_opt!(vis, visit_ty, ty);
match kind {
LocalKind::Decl => {}
LocalKind::Init(init) => {
try_visit!(vis.visit_expr(init))
}
LocalKind::InitElse(init, els) => {
try_visit!(vis.visit_expr(init));
try_visit!(vis.visit_block(els));
}
}
if let Some(sp) = colon_sp {
try_visit!(visit_span(vis, sp));
}
visit_span(vis, span)
}
fn walk_poly_trait_ref<$($lt,)? V: $Visitor$(<$lt>)?>(
vis: &mut V,
p: &$($lt)? $($mut)? PolyTraitRef,
) $(-> <V as Visitor<$lt>>::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));
try_visit!(vis.visit_trait_ref(trait_ref));
visit_span(vis, span)
}
};
}
common_visitor_and_walkers!(Visitor<'a>);
pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) -> V::Result {
let Crate { attrs, items, spans: _, id: _, is_placeholder: _ } = krate;
walk_list!(visitor, visit_attribute, attrs);
walk_list!(visitor, visit_item, items);
V::Result::output()
}
pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) -> V::Result {
let Local { id: _, super_: _, pat, ty, kind, span: _, colon_sp: _, attrs, tokens: _ } = local;
walk_list!(visitor, visit_attribute, attrs);
try_visit!(visitor.visit_pat(pat));
visit_opt!(visitor, visit_ty, ty);
if let Some((init, els)) = kind.init_else_opt() {
try_visit!(visitor.visit_expr(init));
visit_opt!(visitor, visit_block, els);
macro_rules! generate_list_visit_fns {
($($name:ident, $Ty:ty, $visit_fn:ident;)+) => {
$(
fn $name<'a, V: Visitor<'a>>(
vis: &mut V,
values: &'a ThinVec<$Ty>,
) -> V::Result {
walk_list!(vis, $visit_fn, values);
V::Result::output()
}
)+
}
V::Result::output()
}
pub fn walk_poly_trait_ref<'a, V>(visitor: &mut V, trait_ref: &'a PolyTraitRef) -> V::Result
where
V: Visitor<'a>,
{
let PolyTraitRef { bound_generic_params, modifiers: _, trait_ref, span: _ } = trait_ref;
walk_list!(visitor, visit_generic_param, bound_generic_params);
visitor.visit_trait_ref(trait_ref)
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;
}
pub fn walk_trait_ref<'a, V: Visitor<'a>>(visitor: &mut V, trait_ref: &'a TraitRef) -> V::Result {