1use super::{
2 AliasReft, AssocItemConstraint, AssocItemConstraintKind, BaseTy, BaseTyKind, Ensures, EnumDef,
3 Expr, ExprKind, FieldDef, FieldExpr, FluxItem, FnDecl, FnOutput, FnSig, ForeignItem,
4 ForeignItemKind, FuncSort, GenericArg, GenericBound, Generics, Impl, ImplAssocReft, ImplItem,
5 ImplItemKind, Item, ItemKind, Lifetime, Lit, OpaqueTy, OwnerNode, Path, PathExpr, PathSegment,
6 PolyFuncSort, PolyTraitRef, QPath, Qualifier, RefineParam, Requires, Sort, SortPath, SpecFunc,
7 StructDef, TraitAssocReft, TraitItem, TraitItemKind, Ty, TyAlias, TyKind, VariantDef,
8 VariantRet, WhereBoundPredicate,
9};
10use crate::fhir::{PrimOpProp, QPathExpr, QuantDom, SortDecl, StructKind};
11
12#[macro_export]
13macro_rules! walk_list {
14 ($visitor: expr, $method: ident, $list: expr $(, $($extra_args: expr),* )?) => {
15 {
16 #[allow(for_loops_over_fallibles)]
17 for elem in $list {
18 $visitor.$method(elem $(, $($extra_args,)* )?)
19 }
20 }
21 }
22}
23
24pub trait Visitor<'v>: Sized {
25 fn visit_flux_item(&mut self, item: &FluxItem<'v>) {
26 walk_flux_item(self, item);
27 }
28
29 fn visit_qualifier(&mut self, qualifier: &Qualifier<'v>) {
30 walk_qualifier(self, qualifier);
31 }
32
33 fn visit_sort_decl(&mut self, sort_decl: &SortDecl) {
34 walk_sort_decl(self, sort_decl);
35 }
36
37 fn visit_func(&mut self, func: &SpecFunc<'v>) {
38 walk_func(self, func);
39 }
40
41 fn visit_primop_prop(&mut self, prop: &PrimOpProp<'v>) {
42 walk_primop_prop(self, prop);
43 }
44
45 fn visit_node(&mut self, node: &OwnerNode<'v>) {
46 walk_node(self, node);
47 }
48
49 fn visit_item(&mut self, item: &Item<'v>) {
50 walk_item(self, item);
51 }
52
53 fn visit_trait_item(&mut self, trait_item: &TraitItem<'v>) {
54 walk_trait_item(self, trait_item);
55 }
56
57 fn visit_impl_item(&mut self, impl_item: &ImplItem<'v>) {
58 walk_impl_item(self, impl_item);
59 }
60
61 fn visit_foreign_item(&mut self, foreign_item: &ForeignItem<'v>) {
62 walk_foreign_item(self, foreign_item);
63 }
64
65 fn visit_generics(&mut self, generics: &Generics<'v>) {
66 walk_generics(self, generics);
67 }
68
69 fn visit_where_predicate(&mut self, predicate: &WhereBoundPredicate<'v>) {
70 walk_where_predicate(self, predicate);
71 }
72
73 fn visit_impl(&mut self, impl_: &Impl<'v>) {
74 walk_impl(self, impl_);
75 }
76
77 fn visit_impl_assoc_reft(&mut self, assoc_reft: &ImplAssocReft<'v>) {
78 walk_impl_assoc_reft(self, assoc_reft);
79 }
80
81 fn visit_trait_assoc_reft(&mut self, assoc_reft: &TraitAssocReft<'v>) {
82 walk_trait_assoc_reft(self, assoc_reft);
83 }
84
85 fn visit_struct_def(&mut self, struct_def: &StructDef<'v>) {
86 walk_struct_def(self, struct_def);
87 }
88
89 fn visit_enum_def(&mut self, enum_def: &EnumDef<'v>) {
90 walk_enum_def(self, enum_def);
91 }
92
93 fn visit_variant(&mut self, variant: &VariantDef<'v>) {
94 walk_variant(self, variant);
95 }
96
97 fn visit_field_def(&mut self, field: &FieldDef<'v>) {
98 walk_field_def(self, field);
99 }
100
101 fn visit_variant_ret(&mut self, ret: &VariantRet<'v>) {
102 walk_variant_ret(self, ret);
103 }
104
105 fn visit_ty_alias(&mut self, ty_alias: &TyAlias<'v>) {
106 walk_ty_alias(self, ty_alias);
107 }
108
109 fn visit_opaque_ty(&mut self, opaque_ty: &OpaqueTy<'v>) {
110 walk_opaque_ty(self, opaque_ty);
111 }
112
113 fn visit_generic_bound(&mut self, bound: &GenericBound<'v>) {
114 walk_generic_bound(self, bound);
115 }
116
117 fn visit_poly_trait_ref(&mut self, trait_ref: &PolyTraitRef<'v>) {
118 walk_poly_trait_ref(self, trait_ref);
119 }
120
121 fn visit_fn_sig(&mut self, sig: &FnSig<'v>) {
122 walk_fn_sig(self, sig);
123 }
124
125 fn visit_fn_decl(&mut self, decl: &FnDecl<'v>) {
126 walk_fn_decl(self, decl);
127 }
128
129 fn visit_refine_param(&mut self, param: &RefineParam<'v>) {
130 walk_refine_param(self, param);
131 }
132
133 fn visit_requires(&mut self, requires: &Requires<'v>) {
134 walk_requires(self, requires);
135 }
136
137 fn visit_ensures(&mut self, ensures: &Ensures<'v>) {
138 walk_ensures(self, ensures);
139 }
140
141 fn visit_fn_output(&mut self, output: &FnOutput<'v>) {
142 walk_fn_output(self, output);
143 }
144
145 fn visit_generic_arg(&mut self, arg: &GenericArg<'v>) {
146 walk_generic_arg(self, arg);
147 }
148
149 fn visit_lifetime(&mut self, _lft: &Lifetime) {}
150
151 fn visit_ty(&mut self, ty: &Ty<'v>) {
152 walk_ty(self, ty);
153 }
154
155 fn visit_bty(&mut self, bty: &BaseTy<'v>) {
156 walk_bty(self, bty);
157 }
158
159 fn visit_qpath(&mut self, qpath: &QPath<'v>) {
160 walk_qpath(self, qpath);
161 }
162
163 fn visit_path(&mut self, path: &Path<'v>) {
164 walk_path(self, path);
165 }
166
167 fn visit_path_segment(&mut self, segment: &PathSegment<'v>) {
168 walk_path_segment(self, segment);
169 }
170
171 fn visit_assoc_item_constraint(&mut self, constraint: &AssocItemConstraint<'v>) {
172 walk_assoc_item_constraint(self, constraint);
173 }
174
175 fn visit_sort(&mut self, sort: &Sort<'v>) {
176 walk_sort(self, sort);
177 }
178
179 fn visit_sort_path(&mut self, path: &SortPath<'v>) {
180 walk_sort_path(self, path);
181 }
182
183 fn visit_poly_func_sort(&mut self, func: &PolyFuncSort<'v>) {
184 walk_poly_func_sort(self, func);
185 }
186
187 fn visit_func_sort(&mut self, func: &FuncSort<'v>) {
188 walk_func_sort(self, func);
189 }
190
191 fn visit_domain(&mut self, dom: &QuantDom) {
192 walk_domain(self, dom);
193 }
194
195 fn visit_expr(&mut self, expr: &Expr<'v>) {
196 walk_expr(self, expr);
197 }
198
199 fn visit_field_expr(&mut self, expr: &FieldExpr<'v>) {
200 walk_field_expr(self, expr);
201 }
202
203 fn visit_alias_reft(&mut self, alias_reft: &AliasReft<'v>) {
204 walk_alias_reft(self, alias_reft);
205 }
206
207 fn visit_literal(&mut self, _lit: &Lit) {}
208
209 fn visit_path_expr(&mut self, _path: &PathExpr<'v>) {}
210}
211
212fn walk_sort_decl<'v, V: Visitor<'v>>(_vis: &mut V, _sort_decl: &SortDecl) {}
213
214fn walk_func<'v, V: Visitor<'v>>(vis: &mut V, func: &SpecFunc<'v>) {
215 walk_list!(vis, visit_refine_param, func.args);
216 vis.visit_sort(&func.sort);
217 if let Some(body) = &func.body {
218 vis.visit_expr(body);
219 }
220}
221
222fn walk_primop_prop<'v, V: Visitor<'v>>(vis: &mut V, prop: &PrimOpProp<'v>) {
223 walk_list!(vis, visit_refine_param, prop.args);
224 vis.visit_expr(&prop.body);
225}
226
227fn walk_qualifier<'v, V: Visitor<'v>>(vis: &mut V, qualifier: &Qualifier<'v>) {
228 walk_list!(vis, visit_refine_param, qualifier.args);
229 vis.visit_expr(&qualifier.expr);
230}
231
232fn walk_flux_item<'v, V: Visitor<'v>>(vis: &mut V, item: &FluxItem<'v>) {
233 match item {
234 FluxItem::Qualifier(qualifier) => {
235 vis.visit_qualifier(qualifier);
236 }
237 FluxItem::Func(func) => {
238 vis.visit_func(func);
239 }
240 FluxItem::PrimOpProp(prop) => {
241 vis.visit_primop_prop(prop);
242 }
243 FluxItem::SortDecl(sort_decl) => {
244 vis.visit_sort_decl(sort_decl);
245 }
246 }
247}
248
249pub fn walk_impl<'v, V: Visitor<'v>>(vis: &mut V, impl_: &Impl<'v>) {
250 walk_list!(vis, visit_impl_assoc_reft, impl_.assoc_refinements);
251}
252
253pub fn walk_struct_def<'v, V: Visitor<'v>>(vis: &mut V, struct_def: &StructDef<'v>) {
254 walk_list!(vis, visit_refine_param, struct_def.params);
255 walk_list!(vis, visit_expr, struct_def.invariants);
256 if let StructKind::Transparent { fields } = struct_def.kind {
257 walk_list!(vis, visit_field_def, fields);
258 }
259}
260
261pub fn walk_enum_def<'v, V: Visitor<'v>>(vis: &mut V, enum_def: &EnumDef<'v>) {
262 walk_list!(vis, visit_refine_param, enum_def.params);
263 walk_list!(vis, visit_variant, enum_def.variants);
264 walk_list!(vis, visit_expr, enum_def.invariants);
265}
266
267pub fn walk_variant<'v, V: Visitor<'v>>(vis: &mut V, variant: &VariantDef<'v>) {
268 walk_list!(vis, visit_refine_param, variant.params);
269 walk_list!(vis, visit_field_def, variant.fields);
270 vis.visit_variant_ret(&variant.ret);
271}
272
273pub fn walk_field_def<'v, V: Visitor<'v>>(vis: &mut V, field: &FieldDef<'v>) {
274 let FieldDef { ty, lifted: _ } = field;
275 vis.visit_ty(ty);
276}
277
278pub fn walk_variant_ret<'v, V: Visitor<'v>>(vis: &mut V, ret: &VariantRet<'v>) {
279 let VariantRet { idx, enum_id: _ } = ret;
280 vis.visit_expr(idx);
281}
282
283pub fn walk_ty_alias<'v, V: Visitor<'v>>(vis: &mut V, ty_alias: &TyAlias<'v>) {
284 if let Some(index) = &ty_alias.index {
285 vis.visit_refine_param(index);
286 }
287 vis.visit_ty(&ty_alias.ty);
288}
289
290pub fn walk_opaque_ty<'v, V: Visitor<'v>>(vis: &mut V, opaque_ty: &OpaqueTy<'v>) {
291 walk_list!(vis, visit_generic_bound, opaque_ty.bounds);
292}
293
294pub fn walk_generic_bound<'v, V: Visitor<'v>>(vis: &mut V, bound: &GenericBound<'v>) {
295 match bound {
296 GenericBound::Trait(trait_ref) => vis.visit_poly_trait_ref(trait_ref),
297 GenericBound::Outlives(_) => {}
298 }
299}
300
301pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(vis: &mut V, trait_ref: &PolyTraitRef<'v>) {
302 walk_list!(vis, visit_refine_param, trait_ref.refine_params);
303 vis.visit_path(&trait_ref.trait_ref);
304}
305
306pub fn walk_node<'v, V: Visitor<'v>>(vis: &mut V, node: &OwnerNode<'v>) {
307 match node {
308 OwnerNode::Item(item) => vis.visit_item(item),
309 OwnerNode::TraitItem(trait_item) => vis.visit_trait_item(trait_item),
310 OwnerNode::ImplItem(impl_item) => vis.visit_impl_item(impl_item),
311 OwnerNode::ForeignItem(foreign_item) => vis.visit_foreign_item(foreign_item),
312 }
313}
314
315pub fn walk_item<'v, V: Visitor<'v>>(vis: &mut V, item: &Item<'v>) {
316 vis.visit_generics(&item.generics);
317 match &item.kind {
318 ItemKind::Enum(enum_def) => vis.visit_enum_def(enum_def),
319 ItemKind::Struct(struct_def) => vis.visit_struct_def(struct_def),
320 ItemKind::TyAlias(ty_alias) => vis.visit_ty_alias(ty_alias),
321 ItemKind::Trait(trait_) => {
322 walk_list!(vis, visit_trait_assoc_reft, trait_.assoc_refinements);
323 }
324 ItemKind::Impl(impl_) => vis.visit_impl(impl_),
325 ItemKind::Fn(fn_sig) => vis.visit_fn_sig(fn_sig),
326 ItemKind::Const(info) => {
327 if let Some(expr) = info {
328 vis.visit_expr(expr);
329 }
330 }
331 ItemKind::Static(ty) => {
332 if let Some(ty) = ty {
333 vis.visit_ty(ty);
334 }
335 }
336 }
337}
338
339pub fn walk_trait_item<'v, V: Visitor<'v>>(vis: &mut V, trait_item: &TraitItem<'v>) {
340 vis.visit_generics(&trait_item.generics);
341 match &trait_item.kind {
342 TraitItemKind::Fn(fn_sig) => vis.visit_fn_sig(fn_sig),
343 TraitItemKind::Type => {}
344 TraitItemKind::Const => {}
345 }
346}
347
348pub fn walk_impl_item<'v, V: Visitor<'v>>(vis: &mut V, impl_item: &ImplItem<'v>) {
349 vis.visit_generics(&impl_item.generics);
350 match &impl_item.kind {
351 ImplItemKind::Fn(fn_sig) => vis.visit_fn_sig(fn_sig),
352 ImplItemKind::Const => {}
353 ImplItemKind::Type => {}
354 }
355}
356
357pub fn walk_foreign_item<'v, V: Visitor<'v>>(vis: &mut V, impl_item: &ForeignItem<'v>) {
358 match &impl_item.kind {
359 ForeignItemKind::Fn(fn_sig, generics) => {
360 vis.visit_generics(generics);
361 vis.visit_fn_sig(fn_sig);
362 }
363 ForeignItemKind::Static(ty, _, _, generics) => {
364 vis.visit_generics(generics);
365 vis.visit_ty(ty);
366 }
367 }
368}
369
370pub fn walk_trait_assoc_reft<'v, V: Visitor<'v>>(vis: &mut V, assoc_reft: &TraitAssocReft<'v>) {
371 walk_list!(vis, visit_refine_param, assoc_reft.params);
372 vis.visit_sort(&assoc_reft.output);
373 if let Some(expr) = &assoc_reft.body {
374 vis.visit_expr(expr);
375 }
376}
377
378pub fn walk_impl_assoc_reft<'v, V: Visitor<'v>>(vis: &mut V, assoc_reft: &ImplAssocReft<'v>) {
379 walk_list!(vis, visit_refine_param, assoc_reft.params);
380 vis.visit_sort(&assoc_reft.output);
381 vis.visit_expr(&assoc_reft.body);
382}
383
384pub fn walk_generics<'v, V: Visitor<'v>>(vis: &mut V, generics: &Generics<'v>) {
385 walk_list!(vis, visit_refine_param, generics.refinement_params);
386 if let Some(predicates) = generics.predicates {
387 walk_list!(vis, visit_where_predicate, predicates);
388 }
389}
390
391pub fn walk_where_predicate<'v, V: Visitor<'v>>(vis: &mut V, predicate: &WhereBoundPredicate<'v>) {
392 vis.visit_ty(&predicate.bounded_ty);
393 walk_list!(vis, visit_generic_bound, predicate.bounds);
394}
395
396pub fn walk_fn_sig<'v, V: Visitor<'v>>(vis: &mut V, sig: &FnSig<'v>) {
397 vis.visit_fn_decl(sig.decl);
398}
399
400pub fn walk_fn_decl<'v, V: Visitor<'v>>(vis: &mut V, decl: &FnDecl<'v>) {
401 walk_list!(vis, visit_requires, decl.requires);
402 walk_list!(vis, visit_ty, decl.inputs);
403 vis.visit_fn_output(&decl.output);
404}
405
406pub fn walk_refine_param<'v, V: Visitor<'v>>(vis: &mut V, param: &RefineParam<'v>) {
407 vis.visit_sort(¶m.sort);
408}
409
410pub fn walk_requires<'v, V: Visitor<'v>>(vis: &mut V, requires: &Requires<'v>) {
411 walk_list!(vis, visit_refine_param, requires.params);
412 vis.visit_expr(&requires.pred);
413}
414
415pub fn walk_ensures<'v, V: Visitor<'v>>(vis: &mut V, constraint: &Ensures<'v>) {
416 match constraint {
417 Ensures::Type(loc, ty) => {
418 vis.visit_path_expr(loc);
419 vis.visit_ty(ty);
420 }
421 Ensures::Pred(pred) => {
422 vis.visit_expr(pred);
423 }
424 }
425}
426
427pub fn walk_fn_output<'v, V: Visitor<'v>>(vis: &mut V, output: &FnOutput<'v>) {
428 walk_list!(vis, visit_refine_param, output.params);
429 vis.visit_ty(&output.ret);
430 walk_list!(vis, visit_ensures, output.ensures);
431}
432
433pub fn walk_generic_arg<'v, V: Visitor<'v>>(vis: &mut V, arg: &GenericArg<'v>) {
434 match arg {
435 GenericArg::Lifetime(lft) => vis.visit_lifetime(lft),
436 GenericArg::Type(ty) => vis.visit_ty(ty),
437 GenericArg::Const(_) | GenericArg::Infer => {}
438 }
439}
440
441pub fn walk_ty<'v, V: Visitor<'v>>(vis: &mut V, ty: &Ty<'v>) {
442 match ty.kind {
443 TyKind::BaseTy(bty) => vis.visit_bty(&bty),
444 TyKind::Indexed(bty, idx) => {
445 vis.visit_bty(&bty);
446 vis.visit_expr(&idx);
447 }
448 TyKind::Exists(params, ty) => {
449 walk_list!(vis, visit_refine_param, params);
450 vis.visit_ty(ty);
451 }
452 TyKind::Constr(pred, ty) => {
453 vis.visit_expr(&pred);
454 vis.visit_ty(ty);
455 }
456 TyKind::StrgRef(lft, loc, ty) => {
457 vis.visit_lifetime(&lft);
458 vis.visit_path_expr(loc);
459 vis.visit_ty(ty);
460 }
461 TyKind::Ref(lft, mty) => {
462 vis.visit_lifetime(&lft);
463 vis.visit_ty(mty.ty);
464 }
465 TyKind::BareFn(bare_fn) => vis.visit_fn_decl(bare_fn.decl),
466 TyKind::Tuple(tys) => {
467 walk_list!(vis, visit_ty, tys);
468 }
469 TyKind::Array(ty, _len) => {
470 vis.visit_ty(ty);
471 }
472 TyKind::OpaqueDef(opaque_ty) => {
473 vis.visit_opaque_ty(opaque_ty);
474 }
475 TyKind::TraitObject(poly_traits, lft, _) => {
476 walk_list!(vis, visit_poly_trait_ref, poly_traits);
477 vis.visit_lifetime(&lft);
478 }
479 TyKind::Never | TyKind::Infer | TyKind::Err(_) => {}
480 }
481}
482
483pub fn walk_bty<'v, V: Visitor<'v>>(vis: &mut V, bty: &BaseTy<'v>) {
484 match &bty.kind {
485 BaseTyKind::Path(path) => vis.visit_qpath(path),
486 BaseTyKind::Slice(ty) => vis.visit_ty(ty),
487 BaseTyKind::RawPtr(ty, _mtblt) => {
488 vis.visit_ty(ty);
489 }
490 BaseTyKind::Err(_) => {}
491 }
492}
493
494pub fn walk_qpath<'v, V: Visitor<'v>>(vis: &mut V, qpath: &QPath<'v>) {
495 match qpath {
496 QPath::Resolved(qself, path) => {
497 if let Some(self_ty) = qself {
498 vis.visit_ty(self_ty);
499 }
500 vis.visit_path(path);
501 }
502 QPath::TypeRelative(qself, assoc) => {
503 vis.visit_ty(qself);
504 vis.visit_path_segment(assoc);
505 }
506 }
507}
508
509pub fn walk_path<'v, V: Visitor<'v>>(vis: &mut V, path: &Path<'v>) {
510 walk_list!(vis, visit_path_segment, path.segments);
511 walk_list!(vis, visit_expr, path.refine);
512}
513
514pub fn walk_path_segment<'v, V: Visitor<'v>>(vis: &mut V, segment: &PathSegment<'v>) {
515 walk_list!(vis, visit_generic_arg, segment.args);
516 walk_list!(vis, visit_assoc_item_constraint, segment.constraints);
517}
518
519pub fn walk_assoc_item_constraint<'v, V: Visitor<'v>>(
520 vis: &mut V,
521 constraint: &AssocItemConstraint<'v>,
522) {
523 match &constraint.kind {
524 AssocItemConstraintKind::Equality { term } => {
525 vis.visit_ty(term);
526 }
527 }
528}
529
530pub fn walk_sort<'v, V: Visitor<'v>>(vis: &mut V, sort: &Sort<'v>) {
531 match sort {
532 Sort::Path(path) => vis.visit_sort_path(path),
533 Sort::Func(func) => vis.visit_poly_func_sort(func),
534 Sort::SortOf(bty) => vis.visit_bty(bty),
535 Sort::Tuple(sorts) => {
536 walk_list!(vis, visit_sort, *sorts);
537 }
538 Sort::Loc | Sort::BitVec(_) | Sort::Infer | Sort::Err(_) => {}
539 }
540}
541
542pub fn walk_sort_path<'v, V: Visitor<'v>>(vis: &mut V, path: &SortPath<'v>) {
543 walk_list!(vis, visit_sort, path.args);
544}
545
546pub fn walk_poly_func_sort<'v, V: Visitor<'v>>(vis: &mut V, func: &PolyFuncSort<'v>) {
547 let PolyFuncSort { params: _, fsort } = func;
548 vis.visit_func_sort(fsort);
549}
550
551pub fn walk_func_sort<'v, V: Visitor<'v>>(vis: &mut V, func: &FuncSort<'v>) {
552 walk_list!(vis, visit_sort, func.inputs_and_output);
553}
554
555pub fn walk_alias_reft<'v, V: Visitor<'v>>(vis: &mut V, alias: &AliasReft<'v>) {
556 match alias {
557 AliasReft::Qualified { qself, trait_, name: _ } => {
558 vis.visit_ty(qself);
559 vis.visit_path(trait_);
560 }
561 AliasReft::TypeRelative { qself, name: _ } => {
562 vis.visit_ty(qself);
563 }
564 }
565}
566
567pub fn walk_field_expr<'v, V: Visitor<'v>>(vis: &mut V, expr: &FieldExpr<'v>) {
568 vis.visit_expr(&expr.expr);
569}
570
571pub fn walk_domain<'v, V: Visitor<'v>>(vis: &mut V, dom: &QuantDom) {
572 match dom {
573 QuantDom::Bounded { start, end } => {
574 vis.visit_literal(&Lit::Int(*start as u128));
575 vis.visit_literal(&Lit::Int(*end as u128));
576 }
577 QuantDom::Unbounded => {}
578 }
579}
580
581pub fn walk_expr<'v, V: Visitor<'v>>(vis: &mut V, expr: &Expr<'v>) {
582 match expr.kind {
583 ExprKind::Var(qpath) => walk_qpath_expr(vis, qpath),
584 ExprKind::Dot(base, _fld) => {
585 vis.visit_expr(base);
586 }
587 ExprKind::Literal(lit) => vis.visit_literal(&lit),
588 ExprKind::BinaryOp(_op, e1, e2) => {
589 vis.visit_expr(e1);
590 vis.visit_expr(e2);
591 }
592 ExprKind::PrimApp(_op, e1, e2) => {
593 vis.visit_expr(e1);
594 vis.visit_expr(e2);
595 }
596 ExprKind::UnaryOp(_op, e) => vis.visit_expr(e),
597 ExprKind::App(_func, args) => {
598 walk_list!(vis, visit_expr, args);
599 }
600 ExprKind::Alias(alias_reft, args) => {
601 vis.visit_alias_reft(&alias_reft);
602 walk_list!(vis, visit_expr, args);
603 }
604 ExprKind::IfThenElse(e1, e2, e3) => {
605 vis.visit_expr(e1);
606 vis.visit_expr(e2);
607 vis.visit_expr(e3);
608 }
609 ExprKind::Abs(refine_params, body) => {
610 walk_list!(vis, visit_refine_param, refine_params);
611 vis.visit_expr(body);
612 }
613 ExprKind::Record(exprs) | ExprKind::SetLiteral(exprs) | ExprKind::Tuple(exprs) => {
614 walk_list!(vis, visit_expr, exprs);
615 }
616 ExprKind::Constructor(path, exprs, spread) => {
617 if let Some(path) = path {
618 vis.visit_path_expr(&path);
619 }
620 walk_list!(vis, visit_field_expr, exprs);
621 if let Some(s) = spread {
622 vis.visit_expr(&s.expr);
623 }
624 }
625 ExprKind::Quant(_, param, dom, expr) => {
626 vis.visit_domain(&dom);
627 vis.visit_refine_param(¶m);
628 vis.visit_expr(expr);
629 }
630 ExprKind::Block(decls, body) => {
631 for decl in decls {
632 vis.visit_expr(&decl.init);
633 vis.visit_refine_param(&decl.param);
634 }
635 vis.visit_expr(body);
636 }
637 ExprKind::Err(_) => {}
638 }
639}
640
641pub fn walk_qpath_expr<'v, V: Visitor<'v>>(vis: &mut V, qpath: QPathExpr<'v>) {
642 match qpath {
643 QPathExpr::Resolved(path, _param_kind) => {
644 vis.visit_path_expr(&path);
645 }
646 QPathExpr::TypeRelative(qself, _ident) => vis.visit_ty(qself),
647 }
648}