rustc_ast/
mut_visit.rs

1//! A `MutVisitor` represents an AST modification; it accepts an AST piece and
2//! mutates it in place. So, for instance, macro expansion is a `MutVisitor`
3//! that walks over an AST and modifies it.
4//!
5//! Note: using a `MutVisitor` (other than the `MacroExpander` `MutVisitor`) on
6//! an AST before macro expansion is probably a bad idea. For instance,
7//! a `MutVisitor` renaming item names in a module will miss all of those
8//! that are created by the expansion of a macro.
9
10use std::ops::DerefMut;
11use std::panic;
12use std::sync::Arc;
13
14use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
15use rustc_data_structures::stack::ensure_sufficient_stack;
16use rustc_span::source_map::Spanned;
17use rustc_span::{Ident, Span};
18use smallvec::{Array, SmallVec, smallvec};
19use thin_vec::ThinVec;
20
21use crate::ast::*;
22use crate::ptr::P;
23use crate::token::{self, Token};
24use crate::tokenstream::*;
25use crate::visit::{AssocCtxt, BoundKind, FnCtxt};
26
27pub trait ExpectOne<A: Array> {
28    fn expect_one(self, err: &'static str) -> A::Item;
29}
30
31impl<A: Array> ExpectOne<A> for SmallVec<A> {
32    fn expect_one(self, err: &'static str) -> A::Item {
33        assert!(self.len() == 1, "{}", err);
34        self.into_iter().next().unwrap()
35    }
36}
37
38pub trait WalkItemKind {
39    type Ctxt;
40    fn walk(
41        &mut self,
42        span: Span,
43        id: NodeId,
44        ident: &mut Ident,
45        visibility: &mut Visibility,
46        ctxt: Self::Ctxt,
47        visitor: &mut impl MutVisitor,
48    );
49}
50
51pub trait MutVisitor: Sized {
52    /// Mutable token visiting only exists for the `macro_rules` token marker and should not be
53    /// used otherwise. Token visitor would be entirely separate from the regular visitor if
54    /// the marker didn't have to visit AST fragments in nonterminal tokens.
55    const VISIT_TOKENS: bool = false;
56
57    // Methods in this trait have one of three forms:
58    //
59    //   fn visit_t(&mut self, t: &mut T);                      // common
60    //   fn flat_map_t(&mut self, t: T) -> SmallVec<[T; 1]>;    // rare
61    //   fn filter_map_t(&mut self, t: T) -> Option<T>;         // rarest
62    //
63    // Any additions to this trait should happen in form of a call to a public
64    // `noop_*` function that only calls out to the visitor again, not other
65    // `noop_*` functions. This is a necessary API workaround to the problem of
66    // not being able to call out to the super default method in an overridden
67    // default method.
68    //
69    // When writing these methods, it is better to use destructuring like this:
70    //
71    //   fn visit_abc(&mut self, ABC { a, b, c: _ }: &mut ABC) {
72    //       visit_a(a);
73    //       visit_b(b);
74    //   }
75    //
76    // than to use field access like this:
77    //
78    //   fn visit_abc(&mut self, abc: &mut ABC) {
79    //       visit_a(&mut abc.a);
80    //       visit_b(&mut abc.b);
81    //       // ignore abc.c
82    //   }
83    //
84    // As well as being more concise, the former is explicit about which fields
85    // are skipped. Furthermore, if a new field is added, the destructuring
86    // version will cause a compile error, which is good. In comparison, the
87    // field access version will continue working and it would be easy to
88    // forget to add handling for it.
89
90    fn visit_crate(&mut self, c: &mut Crate) {
91        walk_crate(self, c)
92    }
93
94    fn visit_meta_list_item(&mut self, list_item: &mut MetaItemInner) {
95        walk_meta_list_item(self, list_item);
96    }
97
98    fn visit_meta_item(&mut self, meta_item: &mut MetaItem) {
99        walk_meta_item(self, meta_item);
100    }
101
102    fn visit_use_tree(&mut self, use_tree: &mut UseTree) {
103        walk_use_tree(self, use_tree);
104    }
105
106    fn visit_foreign_item(&mut self, ni: &mut P<ForeignItem>) {
107        walk_item(self, ni);
108    }
109
110    fn flat_map_foreign_item(&mut self, ni: P<ForeignItem>) -> SmallVec<[P<ForeignItem>; 1]> {
111        walk_flat_map_foreign_item(self, ni)
112    }
113
114    fn visit_item(&mut self, i: &mut P<Item>) {
115        walk_item(self, i);
116    }
117
118    fn flat_map_item(&mut self, i: P<Item>) -> SmallVec<[P<Item>; 1]> {
119        walk_flat_map_item(self, i)
120    }
121
122    fn visit_fn_header(&mut self, header: &mut FnHeader) {
123        walk_fn_header(self, header);
124    }
125
126    fn visit_field_def(&mut self, fd: &mut FieldDef) {
127        walk_field_def(self, fd);
128    }
129
130    fn flat_map_field_def(&mut self, fd: FieldDef) -> SmallVec<[FieldDef; 1]> {
131        walk_flat_map_field_def(self, fd)
132    }
133
134    fn visit_assoc_item(&mut self, i: &mut P<AssocItem>, ctxt: AssocCtxt) {
135        walk_assoc_item(self, i, ctxt)
136    }
137
138    fn flat_map_assoc_item(
139        &mut self,
140        i: P<AssocItem>,
141        ctxt: AssocCtxt,
142    ) -> SmallVec<[P<AssocItem>; 1]> {
143        walk_flat_map_assoc_item(self, i, ctxt)
144    }
145
146    fn visit_contract(&mut self, c: &mut P<FnContract>) {
147        walk_contract(self, c);
148    }
149
150    fn visit_fn_decl(&mut self, d: &mut P<FnDecl>) {
151        walk_fn_decl(self, d);
152    }
153
154    /// `Span` and `NodeId` are mutated at the caller site.
155    fn visit_fn(&mut self, fk: FnKind<'_>, _: Span, _: NodeId) {
156        walk_fn(self, fk)
157    }
158
159    fn visit_coroutine_kind(&mut self, a: &mut CoroutineKind) {
160        walk_coroutine_kind(self, a);
161    }
162
163    fn visit_closure_binder(&mut self, b: &mut ClosureBinder) {
164        walk_closure_binder(self, b);
165    }
166
167    fn visit_block(&mut self, b: &mut P<Block>) {
168        walk_block(self, b);
169    }
170
171    fn flat_map_stmt(&mut self, s: Stmt) -> SmallVec<[Stmt; 1]> {
172        walk_flat_map_stmt(self, s)
173    }
174
175    fn visit_arm(&mut self, arm: &mut Arm) {
176        walk_arm(self, arm);
177    }
178
179    fn flat_map_arm(&mut self, arm: Arm) -> SmallVec<[Arm; 1]> {
180        walk_flat_map_arm(self, arm)
181    }
182
183    fn visit_pat(&mut self, p: &mut P<Pat>) {
184        walk_pat(self, p);
185    }
186
187    fn visit_anon_const(&mut self, c: &mut AnonConst) {
188        walk_anon_const(self, c);
189    }
190
191    fn visit_expr(&mut self, e: &mut P<Expr>) {
192        walk_expr(self, e);
193    }
194
195    /// This method is a hack to workaround unstable of `stmt_expr_attributes`.
196    /// It can be removed once that feature is stabilized.
197    fn visit_method_receiver_expr(&mut self, ex: &mut P<Expr>) {
198        self.visit_expr(ex)
199    }
200
201    fn filter_map_expr(&mut self, e: P<Expr>) -> Option<P<Expr>> {
202        noop_filter_map_expr(self, e)
203    }
204
205    fn visit_generic_arg(&mut self, arg: &mut GenericArg) {
206        walk_generic_arg(self, arg);
207    }
208
209    fn visit_ty(&mut self, t: &mut P<Ty>) {
210        walk_ty(self, t);
211    }
212
213    fn visit_ty_pat(&mut self, t: &mut P<TyPat>) {
214        walk_ty_pat(self, t);
215    }
216
217    fn visit_lifetime(&mut self, l: &mut Lifetime) {
218        walk_lifetime(self, l);
219    }
220
221    fn visit_assoc_item_constraint(&mut self, c: &mut AssocItemConstraint) {
222        walk_assoc_item_constraint(self, c);
223    }
224
225    fn visit_foreign_mod(&mut self, nm: &mut ForeignMod) {
226        walk_foreign_mod(self, nm);
227    }
228
229    fn visit_variant(&mut self, v: &mut Variant) {
230        walk_variant(self, v);
231    }
232
233    fn flat_map_variant(&mut self, v: Variant) -> SmallVec<[Variant; 1]> {
234        walk_flat_map_variant(self, v)
235    }
236
237    fn visit_ident(&mut self, i: &mut Ident) {
238        walk_ident(self, i);
239    }
240
241    fn visit_modifiers(&mut self, m: &mut TraitBoundModifiers) {
242        walk_modifiers(self, m);
243    }
244
245    fn visit_path(&mut self, p: &mut Path) {
246        walk_path(self, p);
247    }
248
249    fn visit_path_segment(&mut self, p: &mut PathSegment) {
250        walk_path_segment(self, p)
251    }
252
253    fn visit_qself(&mut self, qs: &mut Option<P<QSelf>>) {
254        walk_qself(self, qs);
255    }
256
257    fn visit_generic_args(&mut self, p: &mut GenericArgs) {
258        walk_generic_args(self, p);
259    }
260
261    fn visit_angle_bracketed_parameter_data(&mut self, p: &mut AngleBracketedArgs) {
262        walk_angle_bracketed_parameter_data(self, p);
263    }
264
265    fn visit_parenthesized_parameter_data(&mut self, p: &mut ParenthesizedArgs) {
266        walk_parenthesized_parameter_data(self, p);
267    }
268
269    fn visit_local(&mut self, l: &mut P<Local>) {
270        walk_local(self, l);
271    }
272
273    fn visit_mac_call(&mut self, mac: &mut MacCall) {
274        walk_mac(self, mac);
275    }
276
277    fn visit_macro_def(&mut self, def: &mut MacroDef) {
278        walk_macro_def(self, def);
279    }
280
281    fn visit_label(&mut self, label: &mut Label) {
282        walk_label(self, label);
283    }
284
285    fn visit_attribute(&mut self, at: &mut Attribute) {
286        walk_attribute(self, at);
287    }
288
289    fn visit_param(&mut self, param: &mut Param) {
290        walk_param(self, param);
291    }
292
293    fn flat_map_param(&mut self, param: Param) -> SmallVec<[Param; 1]> {
294        walk_flat_map_param(self, param)
295    }
296
297    fn visit_generics(&mut self, generics: &mut Generics) {
298        walk_generics(self, generics);
299    }
300
301    fn visit_trait_ref(&mut self, tr: &mut TraitRef) {
302        walk_trait_ref(self, tr);
303    }
304
305    fn visit_poly_trait_ref(&mut self, p: &mut PolyTraitRef) {
306        walk_poly_trait_ref(self, p);
307    }
308
309    fn visit_variant_data(&mut self, vdata: &mut VariantData) {
310        walk_variant_data(self, vdata);
311    }
312
313    fn visit_generic_param(&mut self, param: &mut GenericParam) {
314        walk_generic_param(self, param)
315    }
316
317    fn flat_map_generic_param(&mut self, param: GenericParam) -> SmallVec<[GenericParam; 1]> {
318        walk_flat_map_generic_param(self, param)
319    }
320
321    fn visit_param_bound(&mut self, tpb: &mut GenericBound, _ctxt: BoundKind) {
322        walk_param_bound(self, tpb);
323    }
324
325    fn visit_precise_capturing_arg(&mut self, arg: &mut PreciseCapturingArg) {
326        walk_precise_capturing_arg(self, arg);
327    }
328
329    fn visit_mt(&mut self, mt: &mut MutTy) {
330        walk_mt(self, mt);
331    }
332
333    fn visit_expr_field(&mut self, f: &mut ExprField) {
334        walk_expr_field(self, f);
335    }
336
337    fn flat_map_expr_field(&mut self, f: ExprField) -> SmallVec<[ExprField; 1]> {
338        walk_flat_map_expr_field(self, f)
339    }
340
341    fn visit_where_clause(&mut self, where_clause: &mut WhereClause) {
342        walk_where_clause(self, where_clause);
343    }
344
345    fn flat_map_where_predicate(
346        &mut self,
347        where_predicate: WherePredicate,
348    ) -> SmallVec<[WherePredicate; 1]> {
349        walk_flat_map_where_predicate(self, where_predicate)
350    }
351
352    fn visit_where_predicate_kind(&mut self, kind: &mut WherePredicateKind) {
353        walk_where_predicate_kind(self, kind)
354    }
355
356    fn visit_vis(&mut self, vis: &mut Visibility) {
357        walk_vis(self, vis);
358    }
359
360    fn visit_id(&mut self, _id: &mut NodeId) {
361        // Do nothing.
362    }
363
364    fn visit_span(&mut self, _sp: &mut Span) {
365        // Do nothing.
366    }
367
368    fn visit_pat_field(&mut self, fp: &mut PatField) {
369        walk_pat_field(self, fp)
370    }
371
372    fn flat_map_pat_field(&mut self, fp: PatField) -> SmallVec<[PatField; 1]> {
373        walk_flat_map_pat_field(self, fp)
374    }
375
376    fn visit_inline_asm(&mut self, asm: &mut InlineAsm) {
377        walk_inline_asm(self, asm)
378    }
379
380    fn visit_inline_asm_sym(&mut self, sym: &mut InlineAsmSym) {
381        walk_inline_asm_sym(self, sym)
382    }
383
384    fn visit_format_args(&mut self, fmt: &mut FormatArgs) {
385        walk_format_args(self, fmt)
386    }
387
388    fn visit_capture_by(&mut self, capture_by: &mut CaptureBy) {
389        walk_capture_by(self, capture_by)
390    }
391
392    fn visit_fn_ret_ty(&mut self, fn_ret_ty: &mut FnRetTy) {
393        walk_fn_ret_ty(self, fn_ret_ty)
394    }
395}
396
397/// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
398/// when using a `flat_map_*` or `filter_map_*` method within a `visit_`
399/// method.
400//
401// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
402pub fn visit_clobber<T: DummyAstNode>(t: &mut T, f: impl FnOnce(T) -> T) {
403    let old_t = std::mem::replace(t, T::dummy());
404    *t = f(old_t);
405}
406
407// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
408#[inline]
409fn visit_vec<T, F>(elems: &mut Vec<T>, mut visit_elem: F)
410where
411    F: FnMut(&mut T),
412{
413    for elem in elems {
414        visit_elem(elem);
415    }
416}
417
418// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
419#[inline]
420fn visit_thin_vec<T, F>(elems: &mut ThinVec<T>, mut visit_elem: F)
421where
422    F: FnMut(&mut T),
423{
424    for elem in elems {
425        visit_elem(elem);
426    }
427}
428
429// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
430#[inline]
431fn visit_opt<T, F>(opt: &mut Option<T>, mut visit_elem: F)
432where
433    F: FnMut(&mut T),
434{
435    if let Some(elem) = opt {
436        visit_elem(elem);
437    }
438}
439
440// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
441fn visit_attrs<T: MutVisitor>(vis: &mut T, attrs: &mut AttrVec) {
442    for attr in attrs.iter_mut() {
443        vis.visit_attribute(attr);
444    }
445}
446
447// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
448#[allow(unused)]
449fn visit_exprs<T: MutVisitor>(vis: &mut T, exprs: &mut Vec<P<Expr>>) {
450    exprs.flat_map_in_place(|expr| vis.filter_map_expr(expr))
451}
452
453// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
454fn visit_thin_exprs<T: MutVisitor>(vis: &mut T, exprs: &mut ThinVec<P<Expr>>) {
455    exprs.flat_map_in_place(|expr| vis.filter_map_expr(expr))
456}
457
458// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
459fn visit_bounds<T: MutVisitor>(vis: &mut T, bounds: &mut GenericBounds, ctxt: BoundKind) {
460    visit_vec(bounds, |bound| vis.visit_param_bound(bound, ctxt));
461}
462
463// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
464fn visit_attr_args<T: MutVisitor>(vis: &mut T, args: &mut AttrArgs) {
465    match args {
466        AttrArgs::Empty => {}
467        AttrArgs::Delimited(args) => visit_delim_args(vis, args),
468        AttrArgs::Eq { eq_span, expr } => {
469            vis.visit_expr(expr);
470            vis.visit_span(eq_span);
471        }
472    }
473}
474
475// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
476fn visit_delim_args<T: MutVisitor>(vis: &mut T, args: &mut DelimArgs) {
477    let DelimArgs { dspan, delim: _, tokens } = args;
478    visit_tts(vis, tokens);
479    visit_delim_span(vis, dspan);
480}
481
482pub fn visit_delim_span<T: MutVisitor>(vis: &mut T, DelimSpan { open, close }: &mut DelimSpan) {
483    vis.visit_span(open);
484    vis.visit_span(close);
485}
486
487pub fn walk_pat_field<T: MutVisitor>(vis: &mut T, fp: &mut PatField) {
488    let PatField { attrs, id, ident, is_placeholder: _, is_shorthand: _, pat, span } = fp;
489    vis.visit_id(id);
490    visit_attrs(vis, attrs);
491    vis.visit_ident(ident);
492    vis.visit_pat(pat);
493    vis.visit_span(span);
494}
495
496pub fn walk_flat_map_pat_field<T: MutVisitor>(
497    vis: &mut T,
498    mut fp: PatField,
499) -> SmallVec<[PatField; 1]> {
500    vis.visit_pat_field(&mut fp);
501    smallvec![fp]
502}
503
504fn walk_use_tree<T: MutVisitor>(vis: &mut T, use_tree: &mut UseTree) {
505    let UseTree { prefix, kind, span } = use_tree;
506    vis.visit_path(prefix);
507    match kind {
508        UseTreeKind::Simple(rename) => visit_opt(rename, |rename| vis.visit_ident(rename)),
509        UseTreeKind::Nested { items, span } => {
510            for (tree, id) in items {
511                vis.visit_id(id);
512                vis.visit_use_tree(tree);
513            }
514            vis.visit_span(span);
515        }
516        UseTreeKind::Glob => {}
517    }
518    vis.visit_span(span);
519}
520
521pub fn walk_arm<T: MutVisitor>(vis: &mut T, arm: &mut Arm) {
522    let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = arm;
523    vis.visit_id(id);
524    visit_attrs(vis, attrs);
525    vis.visit_pat(pat);
526    visit_opt(guard, |guard| vis.visit_expr(guard));
527    visit_opt(body, |body| vis.visit_expr(body));
528    vis.visit_span(span);
529}
530
531pub fn walk_flat_map_arm<T: MutVisitor>(vis: &mut T, mut arm: Arm) -> SmallVec<[Arm; 1]> {
532    vis.visit_arm(&mut arm);
533    smallvec![arm]
534}
535
536fn walk_assoc_item_constraint<T: MutVisitor>(
537    vis: &mut T,
538    AssocItemConstraint { id, ident, gen_args, kind, span }: &mut AssocItemConstraint,
539) {
540    vis.visit_id(id);
541    vis.visit_ident(ident);
542    if let Some(gen_args) = gen_args {
543        vis.visit_generic_args(gen_args);
544    }
545    match kind {
546        AssocItemConstraintKind::Equality { term } => match term {
547            Term::Ty(ty) => vis.visit_ty(ty),
548            Term::Const(c) => vis.visit_anon_const(c),
549        },
550        AssocItemConstraintKind::Bound { bounds } => visit_bounds(vis, bounds, BoundKind::Bound),
551    }
552    vis.visit_span(span);
553}
554
555pub fn walk_ty<T: MutVisitor>(vis: &mut T, ty: &mut P<Ty>) {
556    let Ty { id, kind, span, tokens } = ty.deref_mut();
557    vis.visit_id(id);
558    match kind {
559        TyKind::Err(_guar) => {}
560        TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy | TyKind::Never | TyKind::CVarArgs => {
561        }
562        TyKind::Slice(ty) => vis.visit_ty(ty),
563        TyKind::Ptr(mt) => vis.visit_mt(mt),
564        TyKind::Ref(lt, mt) | TyKind::PinnedRef(lt, mt) => {
565            visit_opt(lt, |lt| vis.visit_lifetime(lt));
566            vis.visit_mt(mt);
567        }
568        TyKind::BareFn(bft) => {
569            let BareFnTy { safety, ext: _, generic_params, decl, decl_span } = bft.deref_mut();
570            visit_safety(vis, safety);
571            generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
572            vis.visit_fn_decl(decl);
573            vis.visit_span(decl_span);
574        }
575        TyKind::UnsafeBinder(binder) => {
576            let UnsafeBinderTy { generic_params, inner_ty } = binder.deref_mut();
577            generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
578            vis.visit_ty(inner_ty);
579        }
580        TyKind::Tup(tys) => visit_thin_vec(tys, |ty| vis.visit_ty(ty)),
581        TyKind::Paren(ty) => vis.visit_ty(ty),
582        TyKind::Pat(ty, pat) => {
583            vis.visit_ty(ty);
584            vis.visit_ty_pat(pat);
585        }
586        TyKind::Path(qself, path) => {
587            vis.visit_qself(qself);
588            vis.visit_path(path);
589        }
590        TyKind::Array(ty, length) => {
591            vis.visit_ty(ty);
592            vis.visit_anon_const(length);
593        }
594        TyKind::Typeof(expr) => vis.visit_anon_const(expr),
595        TyKind::TraitObject(bounds, _syntax) => {
596            visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::TraitObject))
597        }
598        TyKind::ImplTrait(id, bounds) => {
599            vis.visit_id(id);
600            visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::Impl));
601        }
602        TyKind::MacCall(mac) => vis.visit_mac_call(mac),
603    }
604    visit_lazy_tts(vis, tokens);
605    vis.visit_span(span);
606}
607
608pub fn walk_ty_pat<T: MutVisitor>(vis: &mut T, ty: &mut P<TyPat>) {
609    let TyPat { id, kind, span, tokens } = ty.deref_mut();
610    vis.visit_id(id);
611    match kind {
612        TyPatKind::Range(start, end, _include_end) => {
613            visit_opt(start, |c| vis.visit_anon_const(c));
614            visit_opt(end, |c| vis.visit_anon_const(c));
615        }
616        TyPatKind::Err(_) => {}
617    }
618    visit_lazy_tts(vis, tokens);
619    vis.visit_span(span);
620}
621
622fn walk_foreign_mod<T: MutVisitor>(vis: &mut T, foreign_mod: &mut ForeignMod) {
623    let ForeignMod { extern_span: _, safety, abi: _, items } = foreign_mod;
624    visit_safety(vis, safety);
625    items.flat_map_in_place(|item| vis.flat_map_foreign_item(item));
626}
627
628pub fn walk_variant<T: MutVisitor>(visitor: &mut T, variant: &mut Variant) {
629    let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = variant;
630    visitor.visit_id(id);
631    visit_attrs(visitor, attrs);
632    visitor.visit_vis(vis);
633    visitor.visit_ident(ident);
634    visitor.visit_variant_data(data);
635    visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr));
636    visitor.visit_span(span);
637}
638
639pub fn walk_flat_map_variant<T: MutVisitor>(
640    vis: &mut T,
641    mut variant: Variant,
642) -> SmallVec<[Variant; 1]> {
643    vis.visit_variant(&mut variant);
644    smallvec![variant]
645}
646
647fn walk_ident<T: MutVisitor>(vis: &mut T, Ident { name: _, span }: &mut Ident) {
648    vis.visit_span(span);
649}
650
651fn walk_path_segment<T: MutVisitor>(vis: &mut T, segment: &mut PathSegment) {
652    let PathSegment { ident, id, args } = segment;
653    vis.visit_id(id);
654    vis.visit_ident(ident);
655    visit_opt(args, |args| vis.visit_generic_args(args));
656}
657
658fn walk_path<T: MutVisitor>(vis: &mut T, Path { segments, span, tokens }: &mut Path) {
659    for segment in segments {
660        vis.visit_path_segment(segment);
661    }
662    visit_lazy_tts(vis, tokens);
663    vis.visit_span(span);
664}
665
666fn walk_qself<T: MutVisitor>(vis: &mut T, qself: &mut Option<P<QSelf>>) {
667    visit_opt(qself, |qself| {
668        let QSelf { ty, path_span, position: _ } = &mut **qself;
669        vis.visit_ty(ty);
670        vis.visit_span(path_span);
671    })
672}
673
674fn walk_generic_args<T: MutVisitor>(vis: &mut T, generic_args: &mut GenericArgs) {
675    match generic_args {
676        GenericArgs::AngleBracketed(data) => vis.visit_angle_bracketed_parameter_data(data),
677        GenericArgs::Parenthesized(data) => vis.visit_parenthesized_parameter_data(data),
678        GenericArgs::ParenthesizedElided(span) => vis.visit_span(span),
679    }
680}
681
682fn walk_generic_arg<T: MutVisitor>(vis: &mut T, arg: &mut GenericArg) {
683    match arg {
684        GenericArg::Lifetime(lt) => vis.visit_lifetime(lt),
685        GenericArg::Type(ty) => vis.visit_ty(ty),
686        GenericArg::Const(ct) => vis.visit_anon_const(ct),
687    }
688}
689
690fn walk_angle_bracketed_parameter_data<T: MutVisitor>(vis: &mut T, data: &mut AngleBracketedArgs) {
691    let AngleBracketedArgs { args, span } = data;
692    visit_thin_vec(args, |arg| match arg {
693        AngleBracketedArg::Arg(arg) => vis.visit_generic_arg(arg),
694        AngleBracketedArg::Constraint(constraint) => vis.visit_assoc_item_constraint(constraint),
695    });
696    vis.visit_span(span);
697}
698
699fn walk_parenthesized_parameter_data<T: MutVisitor>(vis: &mut T, args: &mut ParenthesizedArgs) {
700    let ParenthesizedArgs { inputs, output, span, inputs_span } = args;
701    visit_thin_vec(inputs, |input| vis.visit_ty(input));
702    vis.visit_fn_ret_ty(output);
703    vis.visit_span(span);
704    vis.visit_span(inputs_span);
705}
706
707fn walk_local<T: MutVisitor>(vis: &mut T, local: &mut P<Local>) {
708    let Local { id, pat, ty, kind, span, colon_sp, attrs, tokens } = local.deref_mut();
709    vis.visit_id(id);
710    visit_attrs(vis, attrs);
711    vis.visit_pat(pat);
712    visit_opt(ty, |ty| vis.visit_ty(ty));
713    match kind {
714        LocalKind::Decl => {}
715        LocalKind::Init(init) => {
716            vis.visit_expr(init);
717        }
718        LocalKind::InitElse(init, els) => {
719            vis.visit_expr(init);
720            vis.visit_block(els);
721        }
722    }
723    visit_lazy_tts(vis, tokens);
724    visit_opt(colon_sp, |sp| vis.visit_span(sp));
725    vis.visit_span(span);
726}
727
728fn walk_attribute<T: MutVisitor>(vis: &mut T, attr: &mut Attribute) {
729    let Attribute { kind, id: _, style: _, span } = attr;
730    match kind {
731        AttrKind::Normal(normal) => {
732            let NormalAttr {
733                item: AttrItem { unsafety: _, path, args, tokens },
734                tokens: attr_tokens,
735            } = &mut **normal;
736            vis.visit_path(path);
737            visit_attr_args(vis, args);
738            visit_lazy_tts(vis, tokens);
739            visit_lazy_tts(vis, attr_tokens);
740        }
741        AttrKind::DocComment(_kind, _sym) => {}
742    }
743    vis.visit_span(span);
744}
745
746fn walk_mac<T: MutVisitor>(vis: &mut T, mac: &mut MacCall) {
747    let MacCall { path, args } = mac;
748    vis.visit_path(path);
749    visit_delim_args(vis, args);
750}
751
752fn walk_macro_def<T: MutVisitor>(vis: &mut T, macro_def: &mut MacroDef) {
753    let MacroDef { body, macro_rules: _ } = macro_def;
754    visit_delim_args(vis, body);
755}
756
757fn walk_meta_list_item<T: MutVisitor>(vis: &mut T, li: &mut MetaItemInner) {
758    match li {
759        MetaItemInner::MetaItem(mi) => vis.visit_meta_item(mi),
760        MetaItemInner::Lit(_lit) => {}
761    }
762}
763
764fn walk_meta_item<T: MutVisitor>(vis: &mut T, mi: &mut MetaItem) {
765    let MetaItem { unsafety: _, path: _, kind, span } = mi;
766    match kind {
767        MetaItemKind::Word => {}
768        MetaItemKind::List(mis) => visit_thin_vec(mis, |mi| vis.visit_meta_list_item(mi)),
769        MetaItemKind::NameValue(_s) => {}
770    }
771    vis.visit_span(span);
772}
773
774pub fn walk_param<T: MutVisitor>(vis: &mut T, param: &mut Param) {
775    let Param { attrs, id, pat, span, ty, is_placeholder: _ } = param;
776    vis.visit_id(id);
777    visit_attrs(vis, attrs);
778    vis.visit_pat(pat);
779    vis.visit_ty(ty);
780    vis.visit_span(span);
781}
782
783pub fn walk_flat_map_param<T: MutVisitor>(vis: &mut T, mut param: Param) -> SmallVec<[Param; 1]> {
784    vis.visit_param(&mut param);
785    smallvec![param]
786}
787
788// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
789fn visit_attr_tt<T: MutVisitor>(vis: &mut T, tt: &mut AttrTokenTree) {
790    match tt {
791        AttrTokenTree::Token(token, _spacing) => {
792            visit_token(vis, token);
793        }
794        AttrTokenTree::Delimited(dspan, _spacing, _delim, tts) => {
795            visit_attr_tts(vis, tts);
796            visit_delim_span(vis, dspan);
797        }
798        AttrTokenTree::AttrsTarget(AttrsTarget { attrs, tokens }) => {
799            visit_attrs(vis, attrs);
800            visit_lazy_tts_opt_mut(vis, Some(tokens));
801        }
802    }
803}
804
805// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
806fn visit_tt<T: MutVisitor>(vis: &mut T, tt: &mut TokenTree) {
807    match tt {
808        TokenTree::Token(token, _spacing) => {
809            visit_token(vis, token);
810        }
811        TokenTree::Delimited(dspan, _spacing, _delim, tts) => {
812            visit_tts(vis, tts);
813            visit_delim_span(vis, dspan);
814        }
815    }
816}
817
818// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
819fn visit_tts<T: MutVisitor>(vis: &mut T, TokenStream(tts): &mut TokenStream) {
820    if T::VISIT_TOKENS && !tts.is_empty() {
821        let tts = Arc::make_mut(tts);
822        visit_vec(tts, |tree| visit_tt(vis, tree));
823    }
824}
825
826fn visit_attr_tts<T: MutVisitor>(vis: &mut T, AttrTokenStream(tts): &mut AttrTokenStream) {
827    if T::VISIT_TOKENS && !tts.is_empty() {
828        let tts = Arc::make_mut(tts);
829        visit_vec(tts, |tree| visit_attr_tt(vis, tree));
830    }
831}
832
833fn visit_lazy_tts_opt_mut<T: MutVisitor>(vis: &mut T, lazy_tts: Option<&mut LazyAttrTokenStream>) {
834    if T::VISIT_TOKENS {
835        if let Some(lazy_tts) = lazy_tts {
836            let mut tts = lazy_tts.to_attr_token_stream();
837            visit_attr_tts(vis, &mut tts);
838            *lazy_tts = LazyAttrTokenStream::new(tts);
839        }
840    }
841}
842
843fn visit_lazy_tts<T: MutVisitor>(vis: &mut T, lazy_tts: &mut Option<LazyAttrTokenStream>) {
844    visit_lazy_tts_opt_mut(vis, lazy_tts.as_mut());
845}
846
847/// Applies ident visitor if it's an ident; applies other visits to interpolated nodes.
848/// In practice the ident part is not actually used by specific visitors right now,
849/// but there's a test below checking that it works.
850// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
851pub fn visit_token<T: MutVisitor>(vis: &mut T, t: &mut Token) {
852    let Token { kind, span } = t;
853    match kind {
854        token::Ident(name, _is_raw) | token::Lifetime(name, _is_raw) => {
855            let mut ident = Ident::new(*name, *span);
856            vis.visit_ident(&mut ident);
857            *name = ident.name;
858            *span = ident.span;
859            return; // Avoid visiting the span for the second time.
860        }
861        token::NtIdent(ident, _is_raw) => {
862            vis.visit_ident(ident);
863        }
864        token::NtLifetime(ident, _is_raw) => {
865            vis.visit_ident(ident);
866        }
867        token::Interpolated(nt) => {
868            let nt = Arc::make_mut(nt);
869            visit_nonterminal(vis, nt);
870        }
871        _ => {}
872    }
873    vis.visit_span(span);
874}
875
876// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
877/// Applies the visitor to elements of interpolated nodes.
878//
879// N.B., this can occur only when applying a visitor to partially expanded
880// code, where parsed pieces have gotten implanted ito *other* macro
881// invocations. This is relevant for macro hygiene, but possibly not elsewhere.
882//
883// One problem here occurs because the types for flat_map_item, flat_map_stmt,
884// etc., allow the visitor to return *multiple* items; this is a problem for the
885// nodes here, because they insist on having exactly one piece. One solution
886// would be to mangle the MutVisitor trait to include one-to-many and
887// one-to-one versions of these entry points, but that would probably confuse a
888// lot of people and help very few. Instead, I'm just going to put in dynamic
889// checks. I think the performance impact of this will be pretty much
890// nonexistent. The danger is that someone will apply a `MutVisitor` to a
891// partially expanded node, and will be confused by the fact that their
892// `flat_map_item` or `flat_map_stmt` isn't getting called on `NtItem` or `NtStmt`
893// nodes. Hopefully they'll wind up reading this comment, and doing something
894// appropriate.
895//
896// BTW, design choice: I considered just changing the type of, e.g., `NtItem` to
897// contain multiple items, but decided against it when I looked at
898// `parse_item_or_view_item` and tried to figure out what I would do with
899// multiple items there....
900fn visit_nonterminal<T: MutVisitor>(vis: &mut T, nt: &mut token::Nonterminal) {
901    match nt {
902        token::NtBlock(block) => vis.visit_block(block),
903        token::NtExpr(expr) => vis.visit_expr(expr),
904        token::NtLiteral(expr) => vis.visit_expr(expr),
905    }
906}
907
908// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
909fn visit_defaultness<T: MutVisitor>(vis: &mut T, defaultness: &mut Defaultness) {
910    match defaultness {
911        Defaultness::Default(span) => vis.visit_span(span),
912        Defaultness::Final => {}
913    }
914}
915
916// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
917fn visit_safety<T: MutVisitor>(vis: &mut T, safety: &mut Safety) {
918    match safety {
919        Safety::Unsafe(span) => vis.visit_span(span),
920        Safety::Safe(span) => vis.visit_span(span),
921        Safety::Default => {}
922    }
923}
924
925// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
926fn visit_polarity<T: MutVisitor>(vis: &mut T, polarity: &mut ImplPolarity) {
927    match polarity {
928        ImplPolarity::Positive => {}
929        ImplPolarity::Negative(span) => vis.visit_span(span),
930    }
931}
932
933// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
934fn visit_constness<T: MutVisitor>(vis: &mut T, constness: &mut Const) {
935    match constness {
936        Const::Yes(span) => vis.visit_span(span),
937        Const::No => {}
938    }
939}
940
941fn walk_closure_binder<T: MutVisitor>(vis: &mut T, binder: &mut ClosureBinder) {
942    match binder {
943        ClosureBinder::NotPresent => {}
944        ClosureBinder::For { span: _, generic_params } => {
945            generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
946        }
947    }
948}
949
950fn walk_coroutine_kind<T: MutVisitor>(vis: &mut T, coroutine_kind: &mut CoroutineKind) {
951    match coroutine_kind {
952        CoroutineKind::Async { span, closure_id, return_impl_trait_id }
953        | CoroutineKind::Gen { span, closure_id, return_impl_trait_id }
954        | CoroutineKind::AsyncGen { span, closure_id, return_impl_trait_id } => {
955            vis.visit_id(closure_id);
956            vis.visit_id(return_impl_trait_id);
957            vis.visit_span(span);
958        }
959    }
960}
961
962fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
963    match kind {
964        FnKind::Fn(
965            _ctxt,
966            _ident,
967            _vis,
968            Fn {
969                defaultness,
970                generics,
971                contract,
972                body,
973                sig: FnSig { header, decl, span },
974                define_opaque,
975            },
976        ) => {
977            // Identifier and visibility are visited as a part of the item.
978            visit_defaultness(vis, defaultness);
979            vis.visit_fn_header(header);
980            vis.visit_generics(generics);
981            vis.visit_fn_decl(decl);
982            if let Some(contract) = contract {
983                vis.visit_contract(contract);
984            }
985            if let Some(body) = body {
986                vis.visit_block(body);
987            }
988            vis.visit_span(span);
989
990            for (id, path) in define_opaque.iter_mut().flatten() {
991                vis.visit_id(id);
992                vis.visit_path(path)
993            }
994        }
995        FnKind::Closure(binder, coroutine_kind, decl, body) => {
996            vis.visit_closure_binder(binder);
997            coroutine_kind.as_mut().map(|coroutine_kind| vis.visit_coroutine_kind(coroutine_kind));
998            vis.visit_fn_decl(decl);
999            vis.visit_expr(body);
1000        }
1001    }
1002}
1003
1004fn walk_contract<T: MutVisitor>(vis: &mut T, contract: &mut P<FnContract>) {
1005    let FnContract { requires, ensures } = contract.deref_mut();
1006    if let Some(pred) = requires {
1007        vis.visit_expr(pred);
1008    }
1009    if let Some(pred) = ensures {
1010        vis.visit_expr(pred);
1011    }
1012}
1013
1014fn walk_fn_decl<T: MutVisitor>(vis: &mut T, decl: &mut P<FnDecl>) {
1015    let FnDecl { inputs, output } = decl.deref_mut();
1016    inputs.flat_map_in_place(|param| vis.flat_map_param(param));
1017    vis.visit_fn_ret_ty(output);
1018}
1019
1020fn walk_fn_ret_ty<T: MutVisitor>(vis: &mut T, fn_ret_ty: &mut FnRetTy) {
1021    match fn_ret_ty {
1022        FnRetTy::Default(span) => vis.visit_span(span),
1023        FnRetTy::Ty(ty) => vis.visit_ty(ty),
1024    }
1025}
1026
1027fn walk_param_bound<T: MutVisitor>(vis: &mut T, pb: &mut GenericBound) {
1028    match pb {
1029        GenericBound::Trait(trait_ref) => vis.visit_poly_trait_ref(trait_ref),
1030        GenericBound::Outlives(lifetime) => walk_lifetime(vis, lifetime),
1031        GenericBound::Use(args, span) => {
1032            for arg in args {
1033                vis.visit_precise_capturing_arg(arg);
1034            }
1035            vis.visit_span(span);
1036        }
1037    }
1038}
1039
1040fn walk_precise_capturing_arg<T: MutVisitor>(vis: &mut T, arg: &mut PreciseCapturingArg) {
1041    match arg {
1042        PreciseCapturingArg::Lifetime(lt) => {
1043            vis.visit_lifetime(lt);
1044        }
1045        PreciseCapturingArg::Arg(path, id) => {
1046            vis.visit_id(id);
1047            vis.visit_path(path);
1048        }
1049    }
1050}
1051
1052pub fn walk_generic_param<T: MutVisitor>(vis: &mut T, param: &mut GenericParam) {
1053    let GenericParam { id, ident, attrs, bounds, kind, colon_span, is_placeholder: _ } = param;
1054    vis.visit_id(id);
1055    visit_attrs(vis, attrs);
1056    vis.visit_ident(ident);
1057    visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::Bound));
1058    match kind {
1059        GenericParamKind::Lifetime => {}
1060        GenericParamKind::Type { default } => {
1061            visit_opt(default, |default| vis.visit_ty(default));
1062        }
1063        GenericParamKind::Const { ty, kw_span: _, default } => {
1064            vis.visit_ty(ty);
1065            visit_opt(default, |default| vis.visit_anon_const(default));
1066        }
1067    }
1068    if let Some(colon_span) = colon_span {
1069        vis.visit_span(colon_span);
1070    }
1071}
1072
1073pub fn walk_flat_map_generic_param<T: MutVisitor>(
1074    vis: &mut T,
1075    mut param: GenericParam,
1076) -> SmallVec<[GenericParam; 1]> {
1077    vis.visit_generic_param(&mut param);
1078    smallvec![param]
1079}
1080
1081fn walk_label<T: MutVisitor>(vis: &mut T, Label { ident }: &mut Label) {
1082    vis.visit_ident(ident);
1083}
1084
1085fn walk_lifetime<T: MutVisitor>(vis: &mut T, Lifetime { id, ident }: &mut Lifetime) {
1086    vis.visit_id(id);
1087    vis.visit_ident(ident);
1088}
1089
1090fn walk_generics<T: MutVisitor>(vis: &mut T, generics: &mut Generics) {
1091    let Generics { params, where_clause, span } = generics;
1092    params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
1093    vis.visit_where_clause(where_clause);
1094    vis.visit_span(span);
1095}
1096
1097fn walk_ty_alias_where_clauses<T: MutVisitor>(vis: &mut T, tawcs: &mut TyAliasWhereClauses) {
1098    let TyAliasWhereClauses { before, after, split: _ } = tawcs;
1099    let TyAliasWhereClause { has_where_token: _, span: span_before } = before;
1100    let TyAliasWhereClause { has_where_token: _, span: span_after } = after;
1101    vis.visit_span(span_before);
1102    vis.visit_span(span_after);
1103}
1104
1105fn walk_where_clause<T: MutVisitor>(vis: &mut T, wc: &mut WhereClause) {
1106    let WhereClause { has_where_token: _, predicates, span } = wc;
1107    predicates.flat_map_in_place(|predicate| vis.flat_map_where_predicate(predicate));
1108    vis.visit_span(span);
1109}
1110
1111pub fn walk_flat_map_where_predicate<T: MutVisitor>(
1112    vis: &mut T,
1113    mut pred: WherePredicate,
1114) -> SmallVec<[WherePredicate; 1]> {
1115    let WherePredicate { attrs, kind, id, span, is_placeholder: _ } = &mut pred;
1116    vis.visit_id(id);
1117    visit_attrs(vis, attrs);
1118    vis.visit_where_predicate_kind(kind);
1119    vis.visit_span(span);
1120    smallvec![pred]
1121}
1122
1123pub fn walk_where_predicate_kind<T: MutVisitor>(vis: &mut T, kind: &mut WherePredicateKind) {
1124    match kind {
1125        WherePredicateKind::BoundPredicate(bp) => {
1126            let WhereBoundPredicate { bound_generic_params, bounded_ty, bounds } = bp;
1127            bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
1128            vis.visit_ty(bounded_ty);
1129            visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::Bound));
1130        }
1131        WherePredicateKind::RegionPredicate(rp) => {
1132            let WhereRegionPredicate { lifetime, bounds } = rp;
1133            vis.visit_lifetime(lifetime);
1134            visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::Bound));
1135        }
1136        WherePredicateKind::EqPredicate(ep) => {
1137            let WhereEqPredicate { lhs_ty, rhs_ty } = ep;
1138            vis.visit_ty(lhs_ty);
1139            vis.visit_ty(rhs_ty);
1140        }
1141    }
1142}
1143
1144fn walk_variant_data<T: MutVisitor>(vis: &mut T, vdata: &mut VariantData) {
1145    match vdata {
1146        VariantData::Struct { fields, recovered: _ } => {
1147            fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
1148        }
1149        VariantData::Tuple(fields, id) => {
1150            vis.visit_id(id);
1151            fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
1152        }
1153        VariantData::Unit(id) => vis.visit_id(id),
1154    }
1155}
1156
1157fn walk_trait_ref<T: MutVisitor>(vis: &mut T, TraitRef { path, ref_id }: &mut TraitRef) {
1158    vis.visit_id(ref_id);
1159    vis.visit_path(path);
1160}
1161
1162fn walk_poly_trait_ref<T: MutVisitor>(vis: &mut T, p: &mut PolyTraitRef) {
1163    let PolyTraitRef { bound_generic_params, modifiers, trait_ref, span } = p;
1164    vis.visit_modifiers(modifiers);
1165    bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
1166    vis.visit_trait_ref(trait_ref);
1167    vis.visit_span(span);
1168}
1169
1170fn walk_modifiers<V: MutVisitor>(vis: &mut V, m: &mut TraitBoundModifiers) {
1171    let TraitBoundModifiers { constness, asyncness, polarity } = m;
1172    match constness {
1173        BoundConstness::Never => {}
1174        BoundConstness::Always(span) | BoundConstness::Maybe(span) => vis.visit_span(span),
1175    }
1176    match asyncness {
1177        BoundAsyncness::Normal => {}
1178        BoundAsyncness::Async(span) => vis.visit_span(span),
1179    }
1180    match polarity {
1181        BoundPolarity::Positive => {}
1182        BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => vis.visit_span(span),
1183    }
1184}
1185
1186pub fn walk_field_def<T: MutVisitor>(visitor: &mut T, fd: &mut FieldDef) {
1187    let FieldDef { span, ident, vis, id, ty, attrs, is_placeholder: _, safety, default } = fd;
1188    visitor.visit_id(id);
1189    visit_attrs(visitor, attrs);
1190    visitor.visit_vis(vis);
1191    visit_safety(visitor, safety);
1192    visit_opt(ident, |ident| visitor.visit_ident(ident));
1193    visitor.visit_ty(ty);
1194    visit_opt(default, |default| visitor.visit_anon_const(default));
1195    visitor.visit_span(span);
1196}
1197
1198pub fn walk_flat_map_field_def<T: MutVisitor>(
1199    vis: &mut T,
1200    mut fd: FieldDef,
1201) -> SmallVec<[FieldDef; 1]> {
1202    vis.visit_field_def(&mut fd);
1203    smallvec![fd]
1204}
1205
1206pub fn walk_expr_field<T: MutVisitor>(vis: &mut T, f: &mut ExprField) {
1207    let ExprField { ident, expr, span, is_shorthand: _, attrs, id, is_placeholder: _ } = f;
1208    vis.visit_id(id);
1209    visit_attrs(vis, attrs);
1210    vis.visit_ident(ident);
1211    vis.visit_expr(expr);
1212    vis.visit_span(span);
1213}
1214
1215pub fn walk_flat_map_expr_field<T: MutVisitor>(
1216    vis: &mut T,
1217    mut f: ExprField,
1218) -> SmallVec<[ExprField; 1]> {
1219    vis.visit_expr_field(&mut f);
1220    smallvec![f]
1221}
1222
1223fn walk_mt<T: MutVisitor>(vis: &mut T, MutTy { ty, mutbl: _ }: &mut MutTy) {
1224    vis.visit_ty(ty);
1225}
1226
1227pub fn walk_block<T: MutVisitor>(vis: &mut T, block: &mut P<Block>) {
1228    let Block { id, stmts, rules: _, span, tokens, could_be_bare_literal: _ } = block.deref_mut();
1229    vis.visit_id(id);
1230    stmts.flat_map_in_place(|stmt| vis.flat_map_stmt(stmt));
1231    visit_lazy_tts(vis, tokens);
1232    vis.visit_span(span);
1233}
1234
1235pub fn walk_item_kind<K: WalkItemKind>(
1236    kind: &mut K,
1237    span: Span,
1238    id: NodeId,
1239    ident: &mut Ident,
1240    visibility: &mut Visibility,
1241    ctxt: K::Ctxt,
1242    vis: &mut impl MutVisitor,
1243) {
1244    kind.walk(span, id, ident, visibility, ctxt, vis)
1245}
1246
1247impl WalkItemKind for ItemKind {
1248    type Ctxt = ();
1249    fn walk(
1250        &mut self,
1251        span: Span,
1252        id: NodeId,
1253        ident: &mut Ident,
1254        visibility: &mut Visibility,
1255        _ctxt: Self::Ctxt,
1256        vis: &mut impl MutVisitor,
1257    ) {
1258        match self {
1259            ItemKind::ExternCrate(_orig_name) => {}
1260            ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree),
1261            ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
1262                vis.visit_ty(ty);
1263                visit_opt(expr, |expr| vis.visit_expr(expr));
1264            }
1265            ItemKind::Const(item) => {
1266                visit_const_item(item, vis);
1267            }
1268            ItemKind::Fn(func) => {
1269                vis.visit_fn(FnKind::Fn(FnCtxt::Free, ident, visibility, &mut *func), span, id);
1270            }
1271            ItemKind::Mod(safety, mod_kind) => {
1272                visit_safety(vis, safety);
1273                match mod_kind {
1274                    ModKind::Loaded(
1275                        items,
1276                        _inline,
1277                        ModSpans { inner_span, inject_use_span },
1278                        _,
1279                    ) => {
1280                        items.flat_map_in_place(|item| vis.flat_map_item(item));
1281                        vis.visit_span(inner_span);
1282                        vis.visit_span(inject_use_span);
1283                    }
1284                    ModKind::Unloaded => {}
1285                }
1286            }
1287            ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
1288            ItemKind::GlobalAsm(asm) => vis.visit_inline_asm(asm),
1289            ItemKind::TyAlias(box TyAlias { defaultness, generics, where_clauses, bounds, ty }) => {
1290                visit_defaultness(vis, defaultness);
1291                vis.visit_generics(generics);
1292                visit_bounds(vis, bounds, BoundKind::Bound);
1293                visit_opt(ty, |ty| vis.visit_ty(ty));
1294                walk_ty_alias_where_clauses(vis, where_clauses);
1295            }
1296            ItemKind::Enum(EnumDef { variants }, generics) => {
1297                vis.visit_generics(generics);
1298                variants.flat_map_in_place(|variant| vis.flat_map_variant(variant));
1299            }
1300            ItemKind::Struct(variant_data, generics) | ItemKind::Union(variant_data, generics) => {
1301                vis.visit_generics(generics);
1302                vis.visit_variant_data(variant_data);
1303            }
1304            ItemKind::Impl(box Impl {
1305                defaultness,
1306                safety,
1307                generics,
1308                constness,
1309                polarity,
1310                of_trait,
1311                self_ty,
1312                items,
1313            }) => {
1314                visit_defaultness(vis, defaultness);
1315                visit_safety(vis, safety);
1316                vis.visit_generics(generics);
1317                visit_constness(vis, constness);
1318                visit_polarity(vis, polarity);
1319                visit_opt(of_trait, |trait_ref| vis.visit_trait_ref(trait_ref));
1320                vis.visit_ty(self_ty);
1321                items.flat_map_in_place(|item| vis.flat_map_assoc_item(item, AssocCtxt::Impl));
1322            }
1323            ItemKind::Trait(box Trait { safety, is_auto: _, generics, bounds, items }) => {
1324                visit_safety(vis, safety);
1325                vis.visit_generics(generics);
1326                visit_bounds(vis, bounds, BoundKind::Bound);
1327                items.flat_map_in_place(|item| vis.flat_map_assoc_item(item, AssocCtxt::Trait));
1328            }
1329            ItemKind::TraitAlias(generics, bounds) => {
1330                vis.visit_generics(generics);
1331                visit_bounds(vis, bounds, BoundKind::Bound);
1332            }
1333            ItemKind::MacCall(m) => vis.visit_mac_call(m),
1334            ItemKind::MacroDef(def) => vis.visit_macro_def(def),
1335            ItemKind::Delegation(box Delegation {
1336                id,
1337                qself,
1338                path,
1339                rename,
1340                body,
1341                from_glob: _,
1342            }) => {
1343                vis.visit_id(id);
1344                vis.visit_qself(qself);
1345                vis.visit_path(path);
1346                if let Some(rename) = rename {
1347                    vis.visit_ident(rename);
1348                }
1349                if let Some(body) = body {
1350                    vis.visit_block(body);
1351                }
1352            }
1353            ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
1354                vis.visit_qself(qself);
1355                vis.visit_path(prefix);
1356                if let Some(suffixes) = suffixes {
1357                    for (ident, rename) in suffixes {
1358                        vis.visit_ident(ident);
1359                        if let Some(rename) = rename {
1360                            vis.visit_ident(rename);
1361                        }
1362                    }
1363                }
1364                if let Some(body) = body {
1365                    vis.visit_block(body);
1366                }
1367            }
1368        }
1369    }
1370}
1371
1372impl WalkItemKind for AssocItemKind {
1373    type Ctxt = AssocCtxt;
1374    fn walk(
1375        &mut self,
1376        span: Span,
1377        id: NodeId,
1378        ident: &mut Ident,
1379        visibility: &mut Visibility,
1380        ctxt: Self::Ctxt,
1381        visitor: &mut impl MutVisitor,
1382    ) {
1383        match self {
1384            AssocItemKind::Const(item) => {
1385                visit_const_item(item, visitor);
1386            }
1387            AssocItemKind::Fn(func) => {
1388                visitor.visit_fn(
1389                    FnKind::Fn(FnCtxt::Assoc(ctxt), ident, visibility, &mut *func),
1390                    span,
1391                    id,
1392                );
1393            }
1394            AssocItemKind::Type(box TyAlias {
1395                defaultness,
1396                generics,
1397                where_clauses,
1398                bounds,
1399                ty,
1400            }) => {
1401                visit_defaultness(visitor, defaultness);
1402                visitor.visit_generics(generics);
1403                visit_bounds(visitor, bounds, BoundKind::Bound);
1404                visit_opt(ty, |ty| visitor.visit_ty(ty));
1405                walk_ty_alias_where_clauses(visitor, where_clauses);
1406            }
1407            AssocItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
1408            AssocItemKind::Delegation(box Delegation {
1409                id,
1410                qself,
1411                path,
1412                rename,
1413                body,
1414                from_glob: _,
1415            }) => {
1416                visitor.visit_id(id);
1417                visitor.visit_qself(qself);
1418                visitor.visit_path(path);
1419                if let Some(rename) = rename {
1420                    visitor.visit_ident(rename);
1421                }
1422                if let Some(body) = body {
1423                    visitor.visit_block(body);
1424                }
1425            }
1426            AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
1427                visitor.visit_qself(qself);
1428                visitor.visit_path(prefix);
1429                if let Some(suffixes) = suffixes {
1430                    for (ident, rename) in suffixes {
1431                        visitor.visit_ident(ident);
1432                        if let Some(rename) = rename {
1433                            visitor.visit_ident(rename);
1434                        }
1435                    }
1436                }
1437                if let Some(body) = body {
1438                    visitor.visit_block(body);
1439                }
1440            }
1441        }
1442    }
1443}
1444
1445fn visit_const_item<T: MutVisitor>(
1446    ConstItem { defaultness, generics, ty, expr }: &mut ConstItem,
1447    visitor: &mut T,
1448) {
1449    visit_defaultness(visitor, defaultness);
1450    visitor.visit_generics(generics);
1451    visitor.visit_ty(ty);
1452    visit_opt(expr, |expr| visitor.visit_expr(expr));
1453}
1454
1455fn walk_fn_header<T: MutVisitor>(vis: &mut T, header: &mut FnHeader) {
1456    let FnHeader { safety, coroutine_kind, constness, ext: _ } = header;
1457    visit_constness(vis, constness);
1458    coroutine_kind.as_mut().map(|coroutine_kind| vis.visit_coroutine_kind(coroutine_kind));
1459    visit_safety(vis, safety);
1460}
1461
1462pub fn walk_crate<T: MutVisitor>(vis: &mut T, krate: &mut Crate) {
1463    let Crate { attrs, items, spans, id, is_placeholder: _ } = krate;
1464    vis.visit_id(id);
1465    visit_attrs(vis, attrs);
1466    items.flat_map_in_place(|item| vis.flat_map_item(item));
1467    let ModSpans { inner_span, inject_use_span } = spans;
1468    vis.visit_span(inner_span);
1469    vis.visit_span(inject_use_span);
1470}
1471
1472pub fn walk_item(visitor: &mut impl MutVisitor, item: &mut P<Item<impl WalkItemKind<Ctxt = ()>>>) {
1473    walk_item_ctxt(visitor, item, ())
1474}
1475
1476pub fn walk_assoc_item(visitor: &mut impl MutVisitor, item: &mut P<AssocItem>, ctxt: AssocCtxt) {
1477    walk_item_ctxt(visitor, item, ctxt)
1478}
1479
1480fn walk_item_ctxt<K: WalkItemKind>(
1481    visitor: &mut impl MutVisitor,
1482    item: &mut P<Item<K>>,
1483    ctxt: K::Ctxt,
1484) {
1485    let Item { ident, attrs, id, kind, vis, span, tokens } = item.deref_mut();
1486    visitor.visit_id(id);
1487    visit_attrs(visitor, attrs);
1488    visitor.visit_vis(vis);
1489    visitor.visit_ident(ident);
1490    kind.walk(*span, *id, ident, vis, ctxt, visitor);
1491    visit_lazy_tts(visitor, tokens);
1492    visitor.visit_span(span);
1493}
1494
1495pub fn walk_flat_map_item(vis: &mut impl MutVisitor, mut item: P<Item>) -> SmallVec<[P<Item>; 1]> {
1496    vis.visit_item(&mut item);
1497    smallvec![item]
1498}
1499
1500pub fn walk_flat_map_foreign_item(
1501    vis: &mut impl MutVisitor,
1502    mut item: P<ForeignItem>,
1503) -> SmallVec<[P<ForeignItem>; 1]> {
1504    vis.visit_foreign_item(&mut item);
1505    smallvec![item]
1506}
1507
1508pub fn walk_flat_map_assoc_item(
1509    vis: &mut impl MutVisitor,
1510    mut item: P<AssocItem>,
1511    ctxt: AssocCtxt,
1512) -> SmallVec<[P<AssocItem>; 1]> {
1513    vis.visit_assoc_item(&mut item, ctxt);
1514    smallvec![item]
1515}
1516
1517impl WalkItemKind for ForeignItemKind {
1518    type Ctxt = ();
1519    fn walk(
1520        &mut self,
1521        span: Span,
1522        id: NodeId,
1523        ident: &mut Ident,
1524        visibility: &mut Visibility,
1525        _ctxt: Self::Ctxt,
1526        visitor: &mut impl MutVisitor,
1527    ) {
1528        match self {
1529            ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => {
1530                visitor.visit_ty(ty);
1531                visit_opt(expr, |expr| visitor.visit_expr(expr));
1532            }
1533            ForeignItemKind::Fn(func) => {
1534                visitor.visit_fn(
1535                    FnKind::Fn(FnCtxt::Foreign, ident, visibility, &mut *func),
1536                    span,
1537                    id,
1538                );
1539            }
1540            ForeignItemKind::TyAlias(box TyAlias {
1541                defaultness,
1542                generics,
1543                where_clauses,
1544                bounds,
1545                ty,
1546            }) => {
1547                visit_defaultness(visitor, defaultness);
1548                visitor.visit_generics(generics);
1549                visit_bounds(visitor, bounds, BoundKind::Bound);
1550                visit_opt(ty, |ty| visitor.visit_ty(ty));
1551                walk_ty_alias_where_clauses(visitor, where_clauses);
1552            }
1553            ForeignItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
1554        }
1555    }
1556}
1557
1558pub fn walk_pat<T: MutVisitor>(vis: &mut T, pat: &mut P<Pat>) {
1559    let Pat { id, kind, span, tokens } = pat.deref_mut();
1560    vis.visit_id(id);
1561    match kind {
1562        PatKind::Err(_guar) => {}
1563        PatKind::Wild | PatKind::Rest | PatKind::Never => {}
1564        PatKind::Ident(_binding_mode, ident, sub) => {
1565            vis.visit_ident(ident);
1566            visit_opt(sub, |sub| vis.visit_pat(sub));
1567        }
1568        PatKind::Expr(e) => vis.visit_expr(e),
1569        PatKind::TupleStruct(qself, path, elems) => {
1570            vis.visit_qself(qself);
1571            vis.visit_path(path);
1572            visit_thin_vec(elems, |elem| vis.visit_pat(elem));
1573        }
1574        PatKind::Path(qself, path) => {
1575            vis.visit_qself(qself);
1576            vis.visit_path(path);
1577        }
1578        PatKind::Struct(qself, path, fields, _etc) => {
1579            vis.visit_qself(qself);
1580            vis.visit_path(path);
1581            fields.flat_map_in_place(|field| vis.flat_map_pat_field(field));
1582        }
1583        PatKind::Box(inner) => vis.visit_pat(inner),
1584        PatKind::Deref(inner) => vis.visit_pat(inner),
1585        PatKind::Ref(inner, _mutbl) => vis.visit_pat(inner),
1586        PatKind::Range(e1, e2, Spanned { span: _, node: _ }) => {
1587            visit_opt(e1, |e| vis.visit_expr(e));
1588            visit_opt(e2, |e| vis.visit_expr(e));
1589            vis.visit_span(span);
1590        }
1591        PatKind::Guard(p, e) => {
1592            vis.visit_pat(p);
1593            vis.visit_expr(e);
1594        }
1595        PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
1596            visit_thin_vec(elems, |elem| vis.visit_pat(elem))
1597        }
1598        PatKind::Paren(inner) => vis.visit_pat(inner),
1599        PatKind::MacCall(mac) => vis.visit_mac_call(mac),
1600    }
1601    visit_lazy_tts(vis, tokens);
1602    vis.visit_span(span);
1603}
1604
1605fn walk_anon_const<T: MutVisitor>(vis: &mut T, AnonConst { id, value }: &mut AnonConst) {
1606    vis.visit_id(id);
1607    vis.visit_expr(value);
1608}
1609
1610fn walk_inline_asm<T: MutVisitor>(vis: &mut T, asm: &mut InlineAsm) {
1611    // FIXME: Visit spans inside all this currently ignored stuff.
1612    let InlineAsm {
1613        asm_macro: _,
1614        template: _,
1615        template_strs: _,
1616        operands,
1617        clobber_abis: _,
1618        options: _,
1619        line_spans: _,
1620    } = asm;
1621    for (op, span) in operands {
1622        match op {
1623            InlineAsmOperand::In { expr, reg: _ }
1624            | InlineAsmOperand::Out { expr: Some(expr), reg: _, late: _ }
1625            | InlineAsmOperand::InOut { expr, reg: _, late: _ } => vis.visit_expr(expr),
1626            InlineAsmOperand::Out { expr: None, reg: _, late: _ } => {}
1627            InlineAsmOperand::SplitInOut { in_expr, out_expr, reg: _, late: _ } => {
1628                vis.visit_expr(in_expr);
1629                if let Some(out_expr) = out_expr {
1630                    vis.visit_expr(out_expr);
1631                }
1632            }
1633            InlineAsmOperand::Const { anon_const } => vis.visit_anon_const(anon_const),
1634            InlineAsmOperand::Sym { sym } => vis.visit_inline_asm_sym(sym),
1635            InlineAsmOperand::Label { block } => vis.visit_block(block),
1636        }
1637        vis.visit_span(span);
1638    }
1639}
1640
1641fn walk_inline_asm_sym<T: MutVisitor>(
1642    vis: &mut T,
1643    InlineAsmSym { id, qself, path }: &mut InlineAsmSym,
1644) {
1645    vis.visit_id(id);
1646    vis.visit_qself(qself);
1647    vis.visit_path(path);
1648}
1649
1650fn walk_format_args<T: MutVisitor>(vis: &mut T, fmt: &mut FormatArgs) {
1651    // FIXME: visit the template exhaustively.
1652    let FormatArgs { span, template: _, arguments, uncooked_fmt_str: _ } = fmt;
1653    for FormatArgument { kind, expr } in arguments.all_args_mut() {
1654        match kind {
1655            FormatArgumentKind::Named(ident) | FormatArgumentKind::Captured(ident) => {
1656                vis.visit_ident(ident)
1657            }
1658            FormatArgumentKind::Normal => {}
1659        }
1660        vis.visit_expr(expr);
1661    }
1662    vis.visit_span(span);
1663}
1664
1665pub fn walk_expr<T: MutVisitor>(vis: &mut T, Expr { kind, id, span, attrs, tokens }: &mut Expr) {
1666    vis.visit_id(id);
1667    visit_attrs(vis, attrs);
1668    match kind {
1669        ExprKind::Array(exprs) => visit_thin_exprs(vis, exprs),
1670        ExprKind::ConstBlock(anon_const) => {
1671            vis.visit_anon_const(anon_const);
1672        }
1673        ExprKind::Repeat(expr, count) => {
1674            vis.visit_expr(expr);
1675            vis.visit_anon_const(count);
1676        }
1677        ExprKind::Tup(exprs) => visit_thin_exprs(vis, exprs),
1678        ExprKind::Call(f, args) => {
1679            vis.visit_expr(f);
1680            visit_thin_exprs(vis, args);
1681        }
1682        ExprKind::MethodCall(box MethodCall {
1683            seg: PathSegment { ident, id, args: seg_args },
1684            receiver,
1685            args: call_args,
1686            span,
1687        }) => {
1688            vis.visit_method_receiver_expr(receiver);
1689            vis.visit_id(id);
1690            vis.visit_ident(ident);
1691            visit_opt(seg_args, |args| vis.visit_generic_args(args));
1692            visit_thin_exprs(vis, call_args);
1693            vis.visit_span(span);
1694        }
1695        ExprKind::Binary(binop, lhs, rhs) => {
1696            vis.visit_expr(lhs);
1697            vis.visit_expr(rhs);
1698            vis.visit_span(&mut binop.span);
1699        }
1700        ExprKind::Unary(_unop, ohs) => vis.visit_expr(ohs),
1701        ExprKind::Cast(expr, ty) => {
1702            vis.visit_expr(expr);
1703            vis.visit_ty(ty);
1704        }
1705        ExprKind::Type(expr, ty) => {
1706            vis.visit_expr(expr);
1707            vis.visit_ty(ty);
1708        }
1709        ExprKind::AddrOf(_kind, _mut, ohs) => vis.visit_expr(ohs),
1710        ExprKind::Let(pat, scrutinee, span, _recovered) => {
1711            vis.visit_pat(pat);
1712            vis.visit_expr(scrutinee);
1713            vis.visit_span(span);
1714        }
1715        ExprKind::If(cond, tr, fl) => {
1716            vis.visit_expr(cond);
1717            vis.visit_block(tr);
1718            visit_opt(fl, |fl| ensure_sufficient_stack(|| vis.visit_expr(fl)));
1719        }
1720        ExprKind::While(cond, body, label) => {
1721            visit_opt(label, |label| vis.visit_label(label));
1722            vis.visit_expr(cond);
1723            vis.visit_block(body);
1724        }
1725        ExprKind::ForLoop { pat, iter, body, label, kind: _ } => {
1726            visit_opt(label, |label| vis.visit_label(label));
1727            vis.visit_pat(pat);
1728            vis.visit_expr(iter);
1729            vis.visit_block(body);
1730        }
1731        ExprKind::Loop(body, label, span) => {
1732            visit_opt(label, |label| vis.visit_label(label));
1733            vis.visit_block(body);
1734            vis.visit_span(span);
1735        }
1736        ExprKind::Match(expr, arms, _kind) => {
1737            vis.visit_expr(expr);
1738            arms.flat_map_in_place(|arm| vis.flat_map_arm(arm));
1739        }
1740        ExprKind::Closure(box Closure {
1741            binder,
1742            capture_clause,
1743            constness,
1744            coroutine_kind,
1745            movability: _,
1746            fn_decl,
1747            body,
1748            fn_decl_span,
1749            fn_arg_span,
1750        }) => {
1751            visit_constness(vis, constness);
1752            vis.visit_capture_by(capture_clause);
1753            vis.visit_fn(FnKind::Closure(binder, coroutine_kind, fn_decl, body), *span, *id);
1754            vis.visit_span(fn_decl_span);
1755            vis.visit_span(fn_arg_span);
1756        }
1757        ExprKind::Block(blk, label) => {
1758            visit_opt(label, |label| vis.visit_label(label));
1759            vis.visit_block(blk);
1760        }
1761        ExprKind::Gen(_capture_by, body, _kind, decl_span) => {
1762            vis.visit_block(body);
1763            vis.visit_span(decl_span);
1764        }
1765        ExprKind::Await(expr, await_kw_span) => {
1766            vis.visit_expr(expr);
1767            vis.visit_span(await_kw_span);
1768        }
1769        ExprKind::Use(expr, use_kw_span) => {
1770            vis.visit_expr(expr);
1771            vis.visit_span(use_kw_span);
1772        }
1773        ExprKind::Assign(el, er, span) => {
1774            vis.visit_expr(el);
1775            vis.visit_expr(er);
1776            vis.visit_span(span);
1777        }
1778        ExprKind::AssignOp(_op, el, er) => {
1779            vis.visit_expr(el);
1780            vis.visit_expr(er);
1781        }
1782        ExprKind::Field(el, ident) => {
1783            vis.visit_expr(el);
1784            vis.visit_ident(ident);
1785        }
1786        ExprKind::Index(el, er, brackets_span) => {
1787            vis.visit_expr(el);
1788            vis.visit_expr(er);
1789            vis.visit_span(brackets_span);
1790        }
1791        ExprKind::Range(e1, e2, _lim) => {
1792            visit_opt(e1, |e1| vis.visit_expr(e1));
1793            visit_opt(e2, |e2| vis.visit_expr(e2));
1794        }
1795        ExprKind::Underscore => {}
1796        ExprKind::Path(qself, path) => {
1797            vis.visit_qself(qself);
1798            vis.visit_path(path);
1799        }
1800        ExprKind::Break(label, expr) => {
1801            visit_opt(label, |label| vis.visit_label(label));
1802            visit_opt(expr, |expr| vis.visit_expr(expr));
1803        }
1804        ExprKind::Continue(label) => {
1805            visit_opt(label, |label| vis.visit_label(label));
1806        }
1807        ExprKind::Ret(expr) => {
1808            visit_opt(expr, |expr| vis.visit_expr(expr));
1809        }
1810        ExprKind::Yeet(expr) => {
1811            visit_opt(expr, |expr| vis.visit_expr(expr));
1812        }
1813        ExprKind::Become(expr) => vis.visit_expr(expr),
1814        ExprKind::InlineAsm(asm) => vis.visit_inline_asm(asm),
1815        ExprKind::FormatArgs(fmt) => vis.visit_format_args(fmt),
1816        ExprKind::OffsetOf(container, fields) => {
1817            vis.visit_ty(container);
1818            for field in fields.iter_mut() {
1819                vis.visit_ident(field);
1820            }
1821        }
1822        ExprKind::MacCall(mac) => vis.visit_mac_call(mac),
1823        ExprKind::Struct(se) => {
1824            let StructExpr { qself, path, fields, rest } = se.deref_mut();
1825            vis.visit_qself(qself);
1826            vis.visit_path(path);
1827            fields.flat_map_in_place(|field| vis.flat_map_expr_field(field));
1828            match rest {
1829                StructRest::Base(expr) => vis.visit_expr(expr),
1830                StructRest::Rest(_span) => {}
1831                StructRest::None => {}
1832            }
1833        }
1834        ExprKind::Paren(expr) => {
1835            vis.visit_expr(expr);
1836        }
1837        ExprKind::Yield(kind) => {
1838            let expr = kind.expr_mut();
1839            if let Some(expr) = expr {
1840                vis.visit_expr(expr);
1841            }
1842        }
1843        ExprKind::Try(expr) => vis.visit_expr(expr),
1844        ExprKind::TryBlock(body) => vis.visit_block(body),
1845        ExprKind::Lit(_token) => {}
1846        ExprKind::IncludedBytes(_bytes) => {}
1847        ExprKind::UnsafeBinderCast(_kind, expr, ty) => {
1848            vis.visit_expr(expr);
1849            if let Some(ty) = ty {
1850                vis.visit_ty(ty);
1851            }
1852        }
1853        ExprKind::Err(_guar) => {}
1854        ExprKind::Dummy => {}
1855    }
1856    visit_lazy_tts(vis, tokens);
1857    vis.visit_span(span);
1858}
1859
1860pub fn noop_filter_map_expr<T: MutVisitor>(vis: &mut T, mut e: P<Expr>) -> Option<P<Expr>> {
1861    Some({
1862        vis.visit_expr(&mut e);
1863        e
1864    })
1865}
1866
1867pub fn walk_flat_map_stmt<T: MutVisitor>(
1868    vis: &mut T,
1869    Stmt { kind, span, mut id }: Stmt,
1870) -> SmallVec<[Stmt; 1]> {
1871    vis.visit_id(&mut id);
1872    let mut stmts: SmallVec<[Stmt; 1]> = walk_flat_map_stmt_kind(vis, kind)
1873        .into_iter()
1874        .map(|kind| Stmt { id, kind, span })
1875        .collect();
1876    match &mut stmts[..] {
1877        [] => {}
1878        [stmt] => vis.visit_span(&mut stmt.span),
1879        _ => panic!(
1880            "cloning statement `NodeId`s is prohibited by default, \
1881             the visitor should implement custom statement visiting"
1882        ),
1883    }
1884    stmts
1885}
1886
1887fn walk_flat_map_stmt_kind<T: MutVisitor>(vis: &mut T, kind: StmtKind) -> SmallVec<[StmtKind; 1]> {
1888    match kind {
1889        StmtKind::Let(mut local) => smallvec![StmtKind::Let({
1890            vis.visit_local(&mut local);
1891            local
1892        })],
1893        StmtKind::Item(item) => vis.flat_map_item(item).into_iter().map(StmtKind::Item).collect(),
1894        StmtKind::Expr(expr) => vis.filter_map_expr(expr).into_iter().map(StmtKind::Expr).collect(),
1895        StmtKind::Semi(expr) => vis.filter_map_expr(expr).into_iter().map(StmtKind::Semi).collect(),
1896        StmtKind::Empty => smallvec![StmtKind::Empty],
1897        StmtKind::MacCall(mut mac) => {
1898            let MacCallStmt { mac: mac_, style: _, attrs, tokens } = mac.deref_mut();
1899            visit_attrs(vis, attrs);
1900            vis.visit_mac_call(mac_);
1901            visit_lazy_tts(vis, tokens);
1902            smallvec![StmtKind::MacCall(mac)]
1903        }
1904    }
1905}
1906
1907fn walk_vis<T: MutVisitor>(vis: &mut T, visibility: &mut Visibility) {
1908    let Visibility { kind, span, tokens } = visibility;
1909    match kind {
1910        VisibilityKind::Public | VisibilityKind::Inherited => {}
1911        VisibilityKind::Restricted { path, id, shorthand: _ } => {
1912            vis.visit_id(id);
1913            vis.visit_path(path);
1914        }
1915    }
1916    visit_lazy_tts(vis, tokens);
1917    vis.visit_span(span);
1918}
1919
1920fn walk_capture_by<T: MutVisitor>(vis: &mut T, capture_by: &mut CaptureBy) {
1921    match capture_by {
1922        CaptureBy::Ref => {}
1923        CaptureBy::Value { move_kw } => {
1924            vis.visit_span(move_kw);
1925        }
1926        CaptureBy::Use { use_kw } => {
1927            vis.visit_span(use_kw);
1928        }
1929    }
1930}
1931
1932/// Some value for the AST node that is valid but possibly meaningless. Similar
1933/// to `Default` but not intended for wide use. The value will never be used
1934/// meaningfully, it exists just to support unwinding in `visit_clobber` in the
1935/// case where its closure panics.
1936pub trait DummyAstNode {
1937    fn dummy() -> Self;
1938}
1939
1940impl<T> DummyAstNode for Option<T> {
1941    fn dummy() -> Self {
1942        Default::default()
1943    }
1944}
1945
1946impl<T: DummyAstNode + 'static> DummyAstNode for P<T> {
1947    fn dummy() -> Self {
1948        P(DummyAstNode::dummy())
1949    }
1950}
1951
1952impl DummyAstNode for Item {
1953    fn dummy() -> Self {
1954        Item {
1955            attrs: Default::default(),
1956            id: DUMMY_NODE_ID,
1957            span: Default::default(),
1958            vis: Visibility {
1959                kind: VisibilityKind::Public,
1960                span: Default::default(),
1961                tokens: Default::default(),
1962            },
1963            ident: Ident::dummy(),
1964            kind: ItemKind::ExternCrate(None),
1965            tokens: Default::default(),
1966        }
1967    }
1968}
1969
1970impl DummyAstNode for Expr {
1971    fn dummy() -> Self {
1972        Expr {
1973            id: DUMMY_NODE_ID,
1974            kind: ExprKind::Dummy,
1975            span: Default::default(),
1976            attrs: Default::default(),
1977            tokens: Default::default(),
1978        }
1979    }
1980}
1981
1982impl DummyAstNode for Ty {
1983    fn dummy() -> Self {
1984        Ty {
1985            id: DUMMY_NODE_ID,
1986            kind: TyKind::Dummy,
1987            span: Default::default(),
1988            tokens: Default::default(),
1989        }
1990    }
1991}
1992
1993impl DummyAstNode for Pat {
1994    fn dummy() -> Self {
1995        Pat {
1996            id: DUMMY_NODE_ID,
1997            kind: PatKind::Wild,
1998            span: Default::default(),
1999            tokens: Default::default(),
2000        }
2001    }
2002}
2003
2004impl DummyAstNode for Stmt {
2005    fn dummy() -> Self {
2006        Stmt { id: DUMMY_NODE_ID, kind: StmtKind::Empty, span: Default::default() }
2007    }
2008}
2009
2010impl DummyAstNode for Crate {
2011    fn dummy() -> Self {
2012        Crate {
2013            attrs: Default::default(),
2014            items: Default::default(),
2015            spans: Default::default(),
2016            id: DUMMY_NODE_ID,
2017            is_placeholder: Default::default(),
2018        }
2019    }
2020}
2021
2022impl<N: DummyAstNode, T: DummyAstNode> DummyAstNode for crate::ast_traits::AstNodeWrapper<N, T> {
2023    fn dummy() -> Self {
2024        crate::ast_traits::AstNodeWrapper::new(N::dummy(), T::dummy())
2025    }
2026}
2027
2028#[derive(Debug)]
2029pub enum FnKind<'a> {
2030    /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
2031    Fn(FnCtxt, &'a mut Ident, &'a mut Visibility, &'a mut Fn),
2032
2033    /// E.g., `|x, y| body`.
2034    Closure(
2035        &'a mut ClosureBinder,
2036        &'a mut Option<CoroutineKind>,
2037        &'a mut P<FnDecl>,
2038        &'a mut P<Expr>,
2039    ),
2040}