Skip to main content

flux_syntax/surface/
visit.rs

1//! A visitor for types in [`surface`]
2//!
3//! In general there's no specific order except that [refinement parameters] should be
4//! visited in an order that matches their scope. Name resolution relies on this gurantee.
5//!
6//! [`surface`]: crate::surface
7//! [refinement parameters]: crate::surface::RefineParam
8use rustc_span::symbol::Ident;
9
10use super::{
11    Async, BaseSort, BaseTy, BaseTyKind, ConstArg, ConstArgKind, ConstantInfo, ConstructorArg,
12    Ensures, EnumDef, Expr, ExprKind, ExprPath, ExprPathSegment, FieldExpr, FnInput, FnOutput,
13    FnRetTy, FnSig, GenericArg, GenericArgKind, GenericParam, Generics, Impl, ImplAssocReft,
14    Indices, ItemKind, Lit, Path, PathSegment, Qualifier, RefineArg, RefineParam, Sort, SortPath,
15    SpecFunc, StructDef, Trait, TraitAssocReft, TraitRef, Ty, TyAlias, TyKind, UseTreeKind,
16    VariantDef, VariantRet, WhereBoundPredicate,
17};
18use crate::surface::{FluxItem, ImplItemFn, Item, PrimOpProp, SortDecl, TraitItemFn, UseTree};
19
20#[macro_export]
21macro_rules! walk_list {
22    ($visitor: expr, $method: ident, $list: expr $(, $($extra_args: expr),* )?) => {
23        {
24            #[allow(for_loops_over_fallibles)]
25            for elem in $list {
26                $visitor.$method(elem $(, $($extra_args,)* )?)
27            }
28        }
29    }
30}
31
32pub trait Visitor: Sized {
33    fn visit_flux_item(&mut self, item: &FluxItem) {
34        walk_flux_item(self, item);
35    }
36
37    fn visit_qualifier(&mut self, qualifier: &Qualifier) {
38        walk_qualifier(self, qualifier);
39    }
40
41    fn visit_sort_decl(&mut self, sort_decl: &SortDecl) {
42        walk_sort_decl(self, sort_decl);
43    }
44
45    fn visit_defn(&mut self, defn: &SpecFunc) {
46        walk_defn(self, defn);
47    }
48
49    fn visit_primop_prop(&mut self, prop: &PrimOpProp) {
50        walk_primop_prop(self, prop);
51    }
52
53    fn visit_refine_param(&mut self, param: &RefineParam) {
54        walk_refine_param(self, param);
55    }
56
57    fn visit_generic_param(&mut self, param: &GenericParam) {
58        walk_generic_param(self, param);
59    }
60
61    fn visit_sort(&mut self, sort: &Sort) {
62        walk_sort(self, sort);
63    }
64
65    fn visit_item(&mut self, item: &Item) {
66        walk_item(self, item);
67    }
68
69    fn visit_trait_item(&mut self, item: &TraitItemFn) {
70        walk_trait_item(self, item);
71    }
72
73    fn visit_impl_item(&mut self, item: &ImplItemFn) {
74        walk_impl_item(self, item);
75    }
76
77    fn visit_trait(&mut self, trait_: &Trait) {
78        walk_trait(self, trait_);
79    }
80
81    fn visit_trait_assoc_reft(&mut self, assoc_reft: &TraitAssocReft) {
82        walk_trait_assoc_reft(self, assoc_reft);
83    }
84
85    fn visit_impl(&mut self, impl_: &Impl) {
86        walk_impl(self, impl_);
87    }
88
89    fn visit_impl_assoc_reft(&mut self, assoc_reft: &ImplAssocReft) {
90        walk_impl_assoc_reft(self, assoc_reft);
91    }
92
93    fn visit_trait_ref(&mut self, trait_ref: &TraitRef) {
94        walk_trait_ref(self, trait_ref);
95    }
96
97    fn visit_base_sort(&mut self, bsort: &BaseSort) {
98        walk_base_sort(self, bsort);
99    }
100
101    fn visit_sort_path(&mut self, path: &SortPath) {
102        walk_sort_path(self, path);
103    }
104
105    fn visit_ty_alias(&mut self, ty_alias: &TyAlias) {
106        walk_ty_alias(self, ty_alias);
107    }
108
109    fn visit_struct_def(&mut self, struct_def: &StructDef) {
110        walk_struct_def(self, struct_def);
111    }
112
113    fn visit_constant(&mut self, _constant: &ConstantInfo) {
114        walk_constant(self, _constant);
115    }
116
117    fn visit_enum_def(&mut self, enum_def: &EnumDef) {
118        walk_enum_def(self, enum_def);
119    }
120
121    fn visit_variant(&mut self, variant: &VariantDef) {
122        walk_variant(self, variant);
123    }
124
125    fn visit_variant_ret(&mut self, ret: &VariantRet) {
126        walk_variant_ret(self, ret);
127    }
128
129    fn visit_fn_sig(&mut self, fn_sig: &FnSig) {
130        walk_fn_sig(self, fn_sig);
131    }
132
133    fn visit_fn_output(&mut self, fn_output: &FnOutput) {
134        walk_fn_output(self, fn_output);
135    }
136
137    fn visit_async(&mut self, _asyncness: &Async) {}
138
139    fn visit_generics(&mut self, generics: &Generics) {
140        walk_generics(self, generics);
141    }
142
143    fn visit_fn_input(&mut self, input: &FnInput) {
144        walk_fn_input(self, input);
145    }
146
147    fn visit_fn_ret_ty(&mut self, fn_ret_ty: &FnRetTy) {
148        walk_fn_ret_ty(self, fn_ret_ty);
149    }
150
151    fn visit_ensures(&mut self, ensures: &Ensures) {
152        walk_ensures(self, ensures);
153    }
154
155    fn visit_where_predicate(&mut self, predicate: &WhereBoundPredicate) {
156        walk_where_predicate(self, predicate);
157    }
158
159    fn visit_generic_arg(&mut self, arg: &GenericArg) {
160        walk_generic_arg(self, arg);
161    }
162
163    fn visit_refine_arg(&mut self, arg: &RefineArg) {
164        walk_refine_arg(self, arg);
165    }
166
167    fn visit_indices(&mut self, indices: &Indices) {
168        walk_indices(self, indices);
169    }
170
171    fn visit_ty(&mut self, ty: &Ty) {
172        walk_ty(self, ty);
173    }
174
175    fn visit_const_arg(&mut self, const_arg: &ConstArg) {
176        walk_const_arg(self, const_arg);
177    }
178
179    fn visit_bty(&mut self, bty: &BaseTy) {
180        walk_bty(self, bty);
181    }
182
183    fn visit_path(&mut self, path: &Path) {
184        walk_path(self, path);
185    }
186
187    fn visit_path_segment(&mut self, segment: &PathSegment) {
188        walk_path_segment(self, segment);
189    }
190
191    fn visit_expr(&mut self, expr: &Expr) {
192        walk_expr(self, expr);
193    }
194
195    fn visit_constructor_args(&mut self, expr: &ConstructorArg) {
196        match expr {
197            ConstructorArg::FieldExpr(field_expr) => walk_field_expr(self, field_expr),
198            ConstructorArg::Spread(spread) => self.visit_expr(&spread.expr),
199        }
200    }
201
202    fn visit_path_expr(&mut self, qpath: &ExprPath) {
203        walk_path_expr(self, qpath);
204    }
205
206    fn visit_path_expr_segment(&mut self, segment: &ExprPathSegment) {
207        walk_path_expr_segment(self, segment);
208    }
209
210    fn visit_ident(&mut self, _ident: Ident) {}
211
212    fn visit_literal(&mut self, _lit: Lit) {}
213}
214
215pub fn walk_flux_item<V: Visitor>(vis: &mut V, item: &FluxItem) {
216    match item {
217        FluxItem::Qualifier(qualifier) => vis.visit_qualifier(qualifier),
218        FluxItem::FuncDef(spec_func) => vis.visit_defn(spec_func),
219        FluxItem::SortDecl(sort_decl) => vis.visit_sort_decl(sort_decl),
220        FluxItem::PrimOpProp(prim_op_prop) => vis.visit_primop_prop(prim_op_prop),
221        FluxItem::Use(use_tree) => walk_use_tree(vis, use_tree),
222    }
223}
224
225pub fn walk_use_tree<V: Visitor>(vis: &mut V, use_tree: &UseTree) {
226    vis.visit_path_expr(&use_tree.prefix);
227    match &use_tree.kind {
228        UseTreeKind::Simple => {}
229        UseTreeKind::Nested(items) => {
230            for item in items {
231                walk_use_tree(vis, item);
232            }
233        }
234    }
235}
236
237pub fn walk_qualifier<V: Visitor>(vis: &mut V, qualifier: &Qualifier) {
238    vis.visit_ident(qualifier.name);
239    walk_list!(vis, visit_refine_param, &qualifier.params);
240    vis.visit_expr(&qualifier.expr);
241}
242
243pub fn walk_sort_decl<V: Visitor>(vis: &mut V, sort_decl: &SortDecl) {
244    vis.visit_ident(sort_decl.name);
245    walk_list!(vis, visit_ident, sort_decl.sort_vars.iter().copied());
246}
247
248pub fn walk_defn<V: Visitor>(vis: &mut V, defn: &SpecFunc) {
249    vis.visit_ident(defn.name);
250    walk_list!(vis, visit_ident, defn.sort_vars.iter().copied());
251    walk_list!(vis, visit_refine_param, &defn.params);
252    vis.visit_sort(&defn.output);
253    if let Some(body) = &defn.body {
254        vis.visit_expr(body);
255    }
256}
257
258pub fn walk_primop_prop<V: Visitor>(vis: &mut V, prop: &PrimOpProp) {
259    vis.visit_ident(prop.name);
260    walk_list!(vis, visit_refine_param, &prop.params);
261    vis.visit_expr(&prop.body);
262}
263
264pub fn walk_refine_param<V: Visitor>(vis: &mut V, param: &RefineParam) {
265    vis.visit_ident(param.ident);
266    vis.visit_sort(&param.sort);
267}
268
269pub fn walk_generic_param<V: Visitor>(vis: &mut V, param: &GenericParam) {
270    vis.visit_ident(param.name);
271}
272
273pub fn walk_sort<V: Visitor>(vis: &mut V, sort: &Sort) {
274    match sort {
275        Sort::Base(bsort) => vis.visit_base_sort(bsort),
276        Sort::Func { inputs, output } => {
277            walk_list!(vis, visit_base_sort, inputs);
278            vis.visit_base_sort(output);
279        }
280        Sort::Infer => {}
281    }
282}
283
284pub fn walk_item<V: Visitor>(vis: &mut V, item: &Item) {
285    match &item.kind {
286        ItemKind::Fn(fn_sig) => {
287            if let Some(fn_sig) = fn_sig {
288                vis.visit_fn_sig(fn_sig);
289            }
290        }
291        ItemKind::Struct(struct_def) => vis.visit_struct_def(struct_def),
292        ItemKind::Enum(enum_def) => vis.visit_enum_def(enum_def),
293        ItemKind::Trait(trait_) => vis.visit_trait(trait_),
294        ItemKind::Impl(impl_) => vis.visit_impl(impl_),
295        ItemKind::Const(cst) => vis.visit_constant(cst),
296        ItemKind::Static(static_info) => vis.visit_ty(&static_info.ty),
297        ItemKind::TyAlias(ty_alias) => vis.visit_ty_alias(ty_alias),
298        ItemKind::Mod => {}
299    }
300}
301
302pub fn walk_trait_item<V: Visitor>(vis: &mut V, item: &TraitItemFn) {
303    if let Some(fn_sig) = item.sig.as_ref() {
304        vis.visit_fn_sig(fn_sig);
305    }
306}
307
308pub fn walk_impl_item<V: Visitor>(vis: &mut V, item: &ImplItemFn) {
309    if let Some(fn_sig) = item.sig.as_ref() {
310        vis.visit_fn_sig(fn_sig);
311    }
312}
313
314pub fn walk_trait<V: Visitor>(vis: &mut V, trait_: &Trait) {
315    if let Some(generics) = &trait_.generics {
316        vis.visit_generics(generics);
317    }
318    walk_list!(vis, visit_trait_assoc_reft, &trait_.assoc_refinements);
319}
320
321pub fn walk_trait_assoc_reft<V: Visitor>(vis: &mut V, assoc_reft: &TraitAssocReft) {
322    vis.visit_ident(assoc_reft.name);
323    walk_list!(vis, visit_refine_param, &assoc_reft.params);
324    vis.visit_base_sort(&assoc_reft.output);
325    if let Some(expr) = &assoc_reft.body {
326        vis.visit_expr(expr);
327    }
328}
329
330pub fn walk_impl<V: Visitor>(vis: &mut V, impl_: &Impl) {
331    if let Some(generics) = &impl_.generics {
332        vis.visit_generics(generics);
333    }
334    walk_list!(vis, visit_impl_assoc_reft, &impl_.assoc_refinements);
335}
336
337pub fn walk_impl_assoc_reft<V: Visitor>(vis: &mut V, assoc_reft: &ImplAssocReft) {
338    vis.visit_ident(assoc_reft.name);
339    walk_list!(vis, visit_refine_param, &assoc_reft.params);
340    vis.visit_expr(&assoc_reft.body);
341    vis.visit_base_sort(&assoc_reft.output);
342}
343
344pub fn walk_trait_ref<V: Visitor>(vis: &mut V, trait_ref: &TraitRef) {
345    vis.visit_path(&trait_ref.path);
346}
347
348pub fn walk_base_sort<V: Visitor>(vis: &mut V, bsort: &BaseSort) {
349    match bsort {
350        BaseSort::BitVec(_len) => {}
351        BaseSort::Path(path) => vis.visit_sort_path(path),
352        BaseSort::SortOf(qself, path) => {
353            vis.visit_ty(qself);
354            vis.visit_path(path);
355        }
356        BaseSort::Tuple(sorts) => {
357            walk_list!(vis, visit_base_sort, sorts);
358        }
359    }
360}
361
362pub fn walk_sort_path<V: Visitor>(vis: &mut V, path: &SortPath) {
363    walk_list!(vis, visit_ident, path.segments.iter().copied());
364    walk_list!(vis, visit_base_sort, &path.args);
365}
366
367pub fn walk_ty_alias<V: Visitor>(vis: &mut V, ty_alias: &TyAlias) {
368    vis.visit_ident(ty_alias.ident);
369    vis.visit_generics(&ty_alias.generics);
370    walk_list!(vis, visit_refine_param, &ty_alias.params);
371    if let Some(index) = &ty_alias.index {
372        vis.visit_refine_param(index);
373    }
374    vis.visit_ty(&ty_alias.ty);
375}
376pub fn walk_constant<V: Visitor>(vis: &mut V, constant_info: &ConstantInfo) {
377    if let Some(expr) = &constant_info.expr {
378        vis.visit_expr(expr);
379    }
380}
381
382pub fn walk_struct_def<V: Visitor>(vis: &mut V, struct_def: &StructDef) {
383    if let Some(generics) = &struct_def.generics {
384        vis.visit_generics(generics);
385    }
386    if let Some(refined_by) = &struct_def.refined_by {
387        walk_list!(vis, visit_refine_param, refined_by);
388    }
389    walk_list!(vis, visit_expr, &struct_def.invariants);
390    struct_def.fields.iter().flatten().for_each(|field| {
391        vis.visit_ty(field);
392    });
393}
394
395pub fn walk_enum_def<V: Visitor>(vis: &mut V, enum_def: &EnumDef) {
396    if let Some(refined_by) = &enum_def.refined_by {
397        walk_list!(vis, visit_refine_param, refined_by);
398    }
399    walk_list!(vis, visit_expr, &enum_def.invariants);
400    enum_def
401        .variants
402        .iter()
403        .flatten()
404        .for_each(|variant| vis.visit_variant(variant));
405}
406
407pub fn walk_variant<V: Visitor>(vis: &mut V, variant: &VariantDef) {
408    walk_list!(vis, visit_ty, &variant.fields);
409    if let Some(ret) = &variant.ret {
410        vis.visit_variant_ret(ret);
411    }
412}
413
414pub fn walk_fn_trait_ref<V: Visitor>(vis: &mut V, in_arg: &GenericArg, out_arg: &GenericArg) {
415    vis.visit_generic_arg(in_arg);
416    vis.visit_generic_arg(out_arg);
417}
418
419pub fn walk_variant_ret<V: Visitor>(vis: &mut V, ret: &VariantRet) {
420    vis.visit_path(&ret.path);
421    vis.visit_indices(&ret.indices);
422}
423
424// Explicit refinement params must be brought into scope *before* the generics, because a
425// `where` clause lives in `generics.predicates` and may mention them, e.g. an `hrn` parameter
426// used in the refinement of an `Fn`-trait bound e.g. tests/tests/pos/abstract_refinements/test05.rs
427// Implicit params (named inputs, `@`/`#` binders) are already pre-collected in `on_fn_sig`
428// before the walk, so only the explicit ones need this.
429
430pub fn walk_fn_sig<V: Visitor>(vis: &mut V, fn_sig: &FnSig) {
431    vis.visit_async(&fn_sig.asyncness);
432
433    walk_list!(vis, visit_refine_param, &fn_sig.params);
434    vis.visit_generics(&fn_sig.generics);
435    for requires in &fn_sig.requires {
436        walk_list!(vis, visit_refine_param, &requires.params);
437        vis.visit_expr(&requires.pred);
438    }
439    walk_list!(vis, visit_fn_input, &fn_sig.inputs);
440    if let Some(no_panic_expr) = &fn_sig.no_panic {
441        vis.visit_expr(no_panic_expr);
442    }
443    vis.visit_fn_output(&fn_sig.output);
444}
445
446pub fn walk_fn_output<V: Visitor>(vis: &mut V, fn_output: &FnOutput) {
447    vis.visit_fn_ret_ty(&fn_output.returns);
448    walk_list!(vis, visit_ensures, &fn_output.ensures);
449}
450
451pub fn walk_generics<V: Visitor>(vis: &mut V, generics: &Generics) {
452    walk_list!(vis, visit_generic_param, &generics.params);
453    if let Some(predicates) = &generics.predicates {
454        walk_list!(vis, visit_where_predicate, predicates);
455    }
456}
457
458pub fn walk_fn_input<V: Visitor>(vis: &mut V, arg: &FnInput) {
459    match arg {
460        FnInput::Constr(bind, path, pred, _node_id) => {
461            vis.visit_ident(*bind);
462            vis.visit_path(path);
463            vis.visit_expr(pred);
464        }
465        FnInput::StrgRef(bind, ty, _node_id) => {
466            vis.visit_ident(*bind);
467            vis.visit_ty(ty);
468        }
469        FnInput::Ty(bind, ty, _node_id) => {
470            if let Some(bind) = bind {
471                vis.visit_ident(*bind);
472            }
473            vis.visit_ty(ty);
474        }
475    }
476}
477
478pub fn walk_fn_ret_ty<V: Visitor>(vis: &mut V, fn_ret_ty: &FnRetTy) {
479    match fn_ret_ty {
480        FnRetTy::Default(_span) => {}
481        FnRetTy::Ty(ty) => vis.visit_ty(ty),
482    }
483}
484
485pub fn walk_ensures<V: Visitor>(vis: &mut V, ensures: &Ensures) {
486    match ensures {
487        Ensures::Type(bind, ty, _node_id) => {
488            vis.visit_ident(*bind);
489            vis.visit_ty(ty);
490        }
491        Ensures::Pred(pred) => {
492            vis.visit_expr(pred);
493        }
494    }
495}
496
497pub fn walk_where_predicate<V: Visitor>(vis: &mut V, predicate: &WhereBoundPredicate) {
498    vis.visit_ty(&predicate.bounded_ty);
499    walk_list!(vis, visit_trait_ref, &predicate.bounds);
500}
501
502pub fn walk_generic_arg<V: Visitor>(vis: &mut V, arg: &GenericArg) {
503    match &arg.kind {
504        GenericArgKind::Type(ty) => {
505            vis.visit_ty(ty);
506        }
507        GenericArgKind::Constraint(ident, ty) => {
508            vis.visit_ident(*ident);
509            vis.visit_ty(ty);
510        }
511    }
512}
513
514pub fn walk_refine_arg<V: Visitor>(vis: &mut V, arg: &RefineArg) {
515    match arg {
516        RefineArg::Bind(ident, _kind, _span, _node_id) => {
517            vis.visit_ident(*ident);
518        }
519        RefineArg::Expr(e) => {
520            vis.visit_expr(e);
521        }
522        RefineArg::Abs(params, e, _node_id, _span) => {
523            walk_list!(vis, visit_refine_param, params);
524            vis.visit_expr(e);
525        }
526    }
527}
528
529pub fn walk_indices<V: Visitor>(vis: &mut V, indices: &Indices) {
530    walk_list!(vis, visit_refine_arg, &indices.indices);
531}
532
533pub fn walk_ty<V: Visitor>(vis: &mut V, ty: &Ty) {
534    match &ty.kind {
535        TyKind::Base(bty) => vis.visit_bty(bty),
536        TyKind::Indexed { bty, indices } => {
537            vis.visit_indices(indices);
538            vis.visit_bty(bty);
539        }
540
541        TyKind::Exists { bind, bty, pred } => {
542            vis.visit_ident(*bind);
543            vis.visit_bty(bty);
544            vis.visit_expr(pred);
545        }
546        TyKind::GeneralExists { params, ty, pred } => {
547            walk_list!(vis, visit_refine_param, params);
548            vis.visit_ty(ty);
549            if let Some(pred) = pred {
550                vis.visit_expr(pred);
551            }
552        }
553        TyKind::Ref(_mutbl, ty) => {
554            vis.visit_ty(ty);
555        }
556        TyKind::Constr(pred, ty) => {
557            vis.visit_expr(pred);
558            vis.visit_ty(ty);
559        }
560        TyKind::Tuple(tys) => {
561            walk_list!(vis, visit_ty, tys);
562        }
563        TyKind::Array(ty, len) => {
564            vis.visit_const_arg(len);
565            vis.visit_ty(ty);
566        }
567        TyKind::ImplTrait(_node_id, trait_ref) => {
568            walk_list!(vis, visit_trait_ref, trait_ref);
569        }
570        TyKind::Hole => {}
571    }
572}
573
574pub fn walk_const_arg<V: Visitor>(vis: &mut V, const_arg: &ConstArg) {
575    if let ConstArgKind::Path(path) = &const_arg.kind {
576        vis.visit_path(path);
577    }
578}
579
580pub fn walk_bty<V: Visitor>(vis: &mut V, bty: &BaseTy) {
581    match &bty.kind {
582        BaseTyKind::Path(qself, path) => {
583            if let Some(qself) = qself {
584                vis.visit_ty(qself);
585            }
586            vis.visit_path(path);
587        }
588        BaseTyKind::Slice(ty) => vis.visit_ty(ty),
589        BaseTyKind::Ptr(_, ty) => vis.visit_ty(ty),
590    }
591}
592
593pub fn walk_path<V: Visitor>(vis: &mut V, path: &Path) {
594    walk_list!(vis, visit_path_segment, &path.segments);
595    walk_list!(vis, visit_refine_arg, &path.refine);
596}
597
598pub fn walk_path_segment<V: Visitor>(vis: &mut V, segment: &PathSegment) {
599    vis.visit_ident(segment.ident);
600    walk_list!(vis, visit_generic_arg, &segment.args);
601}
602
603pub fn walk_field_expr<V: Visitor>(vis: &mut V, expr: &FieldExpr) {
604    vis.visit_ident(expr.ident);
605    vis.visit_refine_arg(&expr.expr);
606}
607
608pub fn walk_expr<V: Visitor>(vis: &mut V, expr: &Expr) {
609    match &expr.kind {
610        ExprKind::Path(qpath) => vis.visit_path_expr(qpath),
611        ExprKind::Dot(base, fld) => {
612            vis.visit_expr(base);
613            vis.visit_ident(*fld);
614        }
615        ExprKind::Literal(lit) => {
616            vis.visit_literal(*lit);
617        }
618        ExprKind::BinaryOp(_bin_op, box exprs) => {
619            walk_list!(vis, visit_expr, exprs);
620        }
621        ExprKind::UnaryOp(_un_op, e) => {
622            vis.visit_expr(e);
623        }
624        ExprKind::PrimUIF(_) => {}
625        ExprKind::Call(callee, args) => {
626            vis.visit_expr(callee);
627            walk_list!(vis, visit_expr, args);
628        }
629        ExprKind::AssocReft(qself, path, name) => {
630            vis.visit_ty(qself);
631            vis.visit_path(path);
632            vis.visit_ident(*name);
633        }
634        ExprKind::IfThenElse(box exprs) => {
635            walk_list!(vis, visit_expr, exprs);
636        }
637        ExprKind::Constructor(path, exprs) => {
638            if let Some(path) = path {
639                vis.visit_path_expr(path);
640            }
641            walk_list!(vis, visit_constructor_args, exprs);
642        }
643        ExprKind::Quant(_, i, _, e) => {
644            vis.visit_refine_param(i);
645            vis.visit_expr(e);
646        }
647        ExprKind::Block(decls, body) => {
648            for decl in decls {
649                // the order here is important because the parameter is not in scope
650                // in the initializer
651                vis.visit_expr(&decl.init);
652                vis.visit_refine_param(&decl.param);
653            }
654            vis.visit_expr(body);
655        }
656        ExprKind::SetLiteral(exprs) => {
657            walk_list!(vis, visit_expr, exprs);
658        }
659        ExprKind::Tuple(exprs) => {
660            walk_list!(vis, visit_expr, exprs);
661        }
662    }
663}
664
665pub fn walk_path_expr<V: Visitor>(vis: &mut V, qpath: &ExprPath) {
666    walk_list!(vis, visit_path_expr_segment, &qpath.segments);
667}
668
669pub fn walk_path_expr_segment<V: Visitor>(vis: &mut V, segment: &ExprPathSegment) {
670    vis.visit_ident(segment.ident);
671}