Skip to main content

flux_middle/rty/
fold.rs

1//! This modules follows the implementation of folding in rustc. For more information read the
2//! documentation in `rustc_type_ir::fold`.
3
4use std::ops::ControlFlow;
5
6use flux_arc_interner::{Internable, List};
7use flux_common::bug;
8use itertools::Itertools;
9use rustc_data_structures::unord::{UnordMap, UnordSet};
10use rustc_hash::FxHashSet;
11use rustc_type_ir::{BoundVar, DebruijnIndex, INNERMOST};
12
13use super::{
14    BaseTy, Binder, BoundVariableKinds, Const, EVid, EarlyReftParam, Ensures, Expr, ExprKind,
15    GenericArg, Name, OutlivesPredicate, PolyFuncSort, PtrKind, ReBound, ReErased, Region, Sort,
16    SubsetTy, Ty, TyKind, TyOrBase, reduce::Reducer,
17};
18use crate::{
19    global_env::GlobalEnv,
20    rty::{BoundReft, BoundRegion, Var, VariantSig, expr::HoleKind},
21};
22
23pub trait TypeVisitor: Sized {
24    type BreakTy = !;
25
26    fn enter_binder(&mut self, _vars: &BoundVariableKinds) {}
27
28    fn exit_binder(&mut self) {}
29
30    fn visit_expr(&mut self, expr: &Expr) -> ControlFlow<Self::BreakTy> {
31        expr.super_visit_with(self)
32    }
33
34    fn visit_sort(&mut self, sort: &Sort) -> ControlFlow<Self::BreakTy> {
35        sort.super_visit_with(self)
36    }
37
38    fn visit_ty(&mut self, ty: &Ty) -> ControlFlow<Self::BreakTy> {
39        ty.super_visit_with(self)
40    }
41
42    fn visit_bty(&mut self, bty: &BaseTy) -> ControlFlow<Self::BreakTy> {
43        bty.super_visit_with(self)
44    }
45}
46
47pub trait FallibleTypeFolder: Sized {
48    type Error;
49
50    fn try_enter_binder(&mut self, _vars: &BoundVariableKinds) {}
51
52    fn try_exit_binder(&mut self) {}
53
54    fn try_fold_sort(&mut self, sort: &Sort) -> Result<Sort, Self::Error> {
55        sort.try_super_fold_with(self)
56    }
57
58    fn try_fold_ty(&mut self, ty: &Ty) -> Result<Ty, Self::Error> {
59        ty.try_super_fold_with(self)
60    }
61
62    fn try_fold_bty(&mut self, bty: &BaseTy) -> Result<BaseTy, Self::Error> {
63        bty.try_super_fold_with(self)
64    }
65
66    fn try_fold_subset_ty(&mut self, constr: &SubsetTy) -> Result<SubsetTy, Self::Error> {
67        constr.try_super_fold_with(self)
68    }
69
70    fn try_fold_region(&mut self, re: &Region) -> Result<Region, Self::Error> {
71        Ok(*re)
72    }
73
74    fn try_fold_const(&mut self, c: &Const) -> Result<Const, Self::Error> {
75        c.try_super_fold_with(self)
76    }
77
78    fn try_fold_expr(&mut self, expr: &Expr) -> Result<Expr, Self::Error> {
79        expr.try_super_fold_with(self)
80    }
81}
82
83pub trait TypeFolder: FallibleTypeFolder<Error = !> {
84    fn enter_binder(&mut self, _vars: &BoundVariableKinds) {}
85
86    fn exit_binder(&mut self) {}
87
88    fn fold_sort(&mut self, sort: &Sort) -> Sort {
89        sort.super_fold_with(self)
90    }
91
92    fn fold_ty(&mut self, ty: &Ty) -> Ty {
93        ty.super_fold_with(self)
94    }
95
96    fn fold_bty(&mut self, bty: &BaseTy) -> BaseTy {
97        bty.super_fold_with(self)
98    }
99
100    fn fold_subset_ty(&mut self, constr: &SubsetTy) -> SubsetTy {
101        constr.super_fold_with(self)
102    }
103
104    fn fold_region(&mut self, re: &Region) -> Region {
105        *re
106    }
107
108    fn fold_const(&mut self, c: &Const) -> Const {
109        c.super_fold_with(self)
110    }
111
112    fn fold_expr(&mut self, expr: &Expr) -> Expr {
113        expr.super_fold_with(self)
114    }
115}
116
117impl<F> FallibleTypeFolder for F
118where
119    F: TypeFolder,
120{
121    type Error = !;
122
123    fn try_enter_binder(&mut self, vars: &BoundVariableKinds) {
124        self.enter_binder(vars);
125    }
126
127    fn try_exit_binder(&mut self) {
128        self.exit_binder();
129    }
130
131    fn try_fold_sort(&mut self, sort: &Sort) -> Result<Sort, Self::Error> {
132        Ok(self.fold_sort(sort))
133    }
134
135    fn try_fold_ty(&mut self, ty: &Ty) -> Result<Ty, Self::Error> {
136        Ok(self.fold_ty(ty))
137    }
138
139    fn try_fold_bty(&mut self, bty: &BaseTy) -> Result<BaseTy, Self::Error> {
140        Ok(self.fold_bty(bty))
141    }
142
143    fn try_fold_subset_ty(&mut self, ty: &SubsetTy) -> Result<SubsetTy, Self::Error> {
144        Ok(self.fold_subset_ty(ty))
145    }
146
147    fn try_fold_region(&mut self, re: &Region) -> Result<Region, Self::Error> {
148        Ok(self.fold_region(re))
149    }
150
151    fn try_fold_const(&mut self, c: &Const) -> Result<Const, Self::Error> {
152        Ok(self.fold_const(c))
153    }
154
155    fn try_fold_expr(&mut self, expr: &Expr) -> Result<Expr, Self::Error> {
156        Ok(self.fold_expr(expr))
157    }
158}
159
160pub trait TypeVisitable: Sized {
161    fn visit_with<V: TypeVisitor>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
162
163    fn has_escaping_bvars(&self) -> bool {
164        self.has_escaping_bvars_at_or_above(INNERMOST)
165    }
166
167    /// Returns `true` if `self` has any late-bound vars that are either
168    /// bound by `binder` or bound by some binder outside of `binder`.
169    /// If `binder` is `ty::INNERMOST`, this indicates whether
170    /// there are any late-bound vars that appear free.
171    fn has_escaping_bvars_at_or_above(&self, binder: DebruijnIndex) -> bool {
172        struct HasEscapingVars {
173            /// Anything bound by `outer_index` or "above" is escaping.
174            outer_index: DebruijnIndex,
175        }
176
177        impl TypeVisitor for HasEscapingVars {
178            type BreakTy = ();
179
180            fn enter_binder(&mut self, _: &BoundVariableKinds) {
181                self.outer_index.shift_in(1);
182            }
183
184            fn exit_binder(&mut self) {
185                self.outer_index.shift_out(1);
186            }
187
188            // TODO(nilehmann) keep track of the outermost binder to optimize this, i.e.,
189            // what rustc calls outer_exclusive_binder.
190            fn visit_expr(&mut self, expr: &Expr) -> ControlFlow<()> {
191                if let ExprKind::Var(Var::Bound(debruijn, _)) = expr.kind() {
192                    if *debruijn >= self.outer_index {
193                        ControlFlow::Break(())
194                    } else {
195                        ControlFlow::Continue(())
196                    }
197                } else {
198                    expr.super_visit_with(self)
199                }
200            }
201        }
202        let mut visitor = HasEscapingVars { outer_index: binder };
203        self.visit_with(&mut visitor).is_break()
204    }
205
206    /// Returns the set of all free variables.
207    /// For example, `Vec<i32[n]>{v : v > m}` returns `{n, m}`.
208    fn fvars(&self) -> FxHashSet<Name> {
209        struct CollectFreeVars(FxHashSet<Name>);
210
211        impl TypeVisitor for CollectFreeVars {
212            fn visit_expr(&mut self, e: &Expr) -> ControlFlow<Self::BreakTy> {
213                if let ExprKind::Var(Var::Free(name)) = e.kind() {
214                    self.0.insert(*name);
215                }
216                e.super_visit_with(self)
217            }
218        }
219
220        let mut collector = CollectFreeVars(FxHashSet::default());
221        let _ = self.visit_with(&mut collector);
222        collector.0
223    }
224
225    fn early_params(&self) -> FxHashSet<EarlyReftParam> {
226        struct CollectEarlyParams(FxHashSet<EarlyReftParam>);
227
228        impl TypeVisitor for CollectEarlyParams {
229            fn visit_expr(&mut self, e: &Expr) -> ControlFlow<Self::BreakTy> {
230                if let ExprKind::Var(Var::EarlyParam(param)) = e.kind() {
231                    self.0.insert(*param);
232                }
233                e.super_visit_with(self)
234            }
235        }
236
237        let mut collector = CollectEarlyParams(FxHashSet::default());
238        let _ = self.visit_with(&mut collector);
239        collector.0
240    }
241
242    /// Gives the indices of the provided bvars which:
243    ///   1. Only occur a single time.
244    ///   2. In their occurrence, are either
245    ///      a. The direct argument in an index (e.g. `exists b0. usize[b0]`)
246    ///      b. The direct argument of a constructor in an index (e.g.
247    ///      `exists b0. Vec<usize>[{len: b0}]`)
248    ///
249    /// This is to be used for "re-sugaring" existentials into surface syntax
250    /// that doesn't use existentials.
251    ///
252    /// For 2b., we do need to be careful to ensure that if a constructor has
253    /// multiple arguments, they _all_ are redundant bvars, e.g. as in
254    ///
255    ///     exists b0, b1. RMat<f32>[{rows: b0, cols: b1}]
256    ///
257    /// which may be rewritten as `RMat<f32>`,
258    /// versus the (unlikely) edge case
259    ///
260    ///     exists b0. RMat<f32>[{rows: b0, cols: b0}]
261    ///
262    /// for which the existential is now necessary.
263    ///
264    /// NOTE: this only applies to refinement bvars.
265    fn redundant_bvars(&self) -> UnordSet<BoundVar> {
266        struct RedundantBVarFinder {
267            current_index: DebruijnIndex,
268            total_bvar_occurrences: UnordMap<BoundVar, usize>,
269            bvars_appearing_in_index: UnordSet<BoundVar>,
270        }
271
272        impl TypeVisitor for RedundantBVarFinder {
273            // Here we count all times we see a bvar
274            fn visit_expr(&mut self, e: &Expr) -> ControlFlow<Self::BreakTy> {
275                if let ExprKind::Var(Var::Bound(debruijn, BoundReft { var, .. })) = e.kind()
276                    && debruijn == &self.current_index
277                {
278                    self.total_bvar_occurrences
279                        .entry(*var)
280                        .and_modify(|count| {
281                            *count += 1;
282                        })
283                        .or_insert(1);
284                }
285                e.super_visit_with(self)
286            }
287
288            fn visit_ty(&mut self, ty: &Ty) -> ControlFlow<Self::BreakTy> {
289                // Here we check for bvars specifically as the direct arguments
290                // to an index or as the direct arguments to a Ctor in an index.
291                if let TyKind::Indexed(_bty, expr) = ty.kind() {
292                    match expr.kind() {
293                        ExprKind::Var(Var::Bound(debruijn, BoundReft { var, .. })) => {
294                            if debruijn == &self.current_index {
295                                self.bvars_appearing_in_index.insert(*var);
296                            }
297                        }
298                        ExprKind::Ctor(_ctor, exprs) => {
299                            exprs.iter().for_each(|expr| {
300                                if let ExprKind::Var(Var::Bound(debruijn, BoundReft { var, .. })) =
301                                    expr.kind()
302                                    && debruijn == &self.current_index
303                                {
304                                    self.bvars_appearing_in_index.insert(*var);
305                                }
306                            });
307                        }
308                        _ => {}
309                    }
310                }
311                ty.super_visit_with(self)
312            }
313
314            fn enter_binder(&mut self, _: &BoundVariableKinds) {
315                self.current_index.shift_in(1);
316            }
317
318            fn exit_binder(&mut self) {
319                self.current_index.shift_out(1);
320            }
321        }
322
323        let mut finder = RedundantBVarFinder {
324            current_index: INNERMOST,
325            total_bvar_occurrences: UnordMap::default(),
326            bvars_appearing_in_index: UnordSet::new(),
327        };
328        let _ = self.visit_with(&mut finder);
329
330        let RedundantBVarFinder { bvars_appearing_in_index, total_bvar_occurrences, .. } = finder;
331        bvars_appearing_in_index
332            .into_items()
333            .filter(|var_index| total_bvar_occurrences.get(var_index) == Some(&1))
334            .collect()
335    }
336}
337
338pub trait TypeSuperVisitable: TypeVisitable {
339    fn super_visit_with<V: TypeVisitor>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
340}
341
342pub trait TypeFoldable: TypeVisitable {
343    fn try_fold_with<F: FallibleTypeFolder>(&self, folder: &mut F) -> Result<Self, F::Error>;
344
345    fn fold_with<F: TypeFolder>(&self, folder: &mut F) -> Self {
346        self.try_fold_with(folder).into_ok()
347    }
348
349    /// Reduces expressions by
350    /// * inlining calls to spec functions (according to [`GlobalEnv::should_inline_fun`]),
351    /// * applying lambda abstractions to their arguments, and
352    /// * reducing field projections on tuples and constructors.
353    fn reduce(&self, genv: GlobalEnv) -> Self {
354        self.fold_with(&mut Reducer::new(genv))
355    }
356
357    /// Replaces all [holes] with the result of calling a closure. The closure takes a list with
358    /// all the *layers* of [bound] variables at the point the hole was found. Each layer corresponds
359    /// to the list of bound variables at that level. The list is ordered from outermost to innermost
360    /// binder, i.e., the last element is the binder closest to the hole.
361    ///
362    /// [holes]: ExprKind::Hole
363    /// [bound]: Binder
364    fn replace_holes(&self, f: impl FnMut(&[BoundVariableKinds], HoleKind) -> Expr) -> Self {
365        struct ReplaceHoles<F>(F, Vec<BoundVariableKinds>);
366
367        impl<F> TypeFolder for ReplaceHoles<F>
368        where
369            F: FnMut(&[BoundVariableKinds], HoleKind) -> Expr,
370        {
371            fn enter_binder(&mut self, vars: &BoundVariableKinds) {
372                self.1.push(vars.clone());
373            }
374
375            fn exit_binder(&mut self) {
376                self.1.pop();
377            }
378
379            fn fold_expr(&mut self, e: &Expr) -> Expr {
380                if let ExprKind::Hole(kind) = e.kind() {
381                    self.0(&self.1, kind.clone())
382                } else {
383                    e.super_fold_with(self)
384                }
385            }
386        }
387
388        self.fold_with(&mut ReplaceHoles(f, vec![]))
389    }
390
391    /// Remove all refinements and turn each underlying [`BaseTy`] into a [`TyKind::Exists`] with a
392    /// [`TyKind::Constr`] and a [`hole`]. For example, `Vec<{v. i32[v] | v > 0}>[n]` becomes
393    /// `{n. Vec<{v. i32[v] | *}>[n] | *}`.
394    ///
395    /// [`hole`]: ExprKind::Hole
396    fn with_holes(&self) -> Self {
397        struct WithHoles;
398
399        impl TypeFolder for WithHoles {
400            fn fold_ty(&mut self, ty: &Ty) -> Ty {
401                if let Some(bty) = ty.as_bty_skipping_existentials() {
402                    Ty::exists_with_constr(bty.fold_with(self), Expr::hole(HoleKind::Pred))
403                } else {
404                    ty.super_fold_with(self)
405                }
406            }
407
408            fn fold_subset_ty(&mut self, constr: &SubsetTy) -> SubsetTy {
409                SubsetTy::new(constr.bty.clone(), constr.idx.clone(), Expr::hole(HoleKind::Pred))
410            }
411        }
412
413        self.fold_with(&mut WithHoles)
414    }
415
416    fn replace_evars(&self, f: &mut impl FnMut(EVid) -> Option<Expr>) -> Result<Self, EVid> {
417        struct Folder<F>(F);
418        impl<F: FnMut(EVid) -> Option<Expr>> FallibleTypeFolder for Folder<F> {
419            type Error = EVid;
420
421            fn try_fold_expr(&mut self, expr: &Expr) -> Result<Expr, Self::Error> {
422                if let ExprKind::Var(Var::EVar(evid)) = expr.kind() {
423                    if let Some(sol) = (self.0)(*evid) { Ok(sol.clone()) } else { Err(*evid) }
424                } else {
425                    expr.try_super_fold_with(self)
426                }
427            }
428        }
429
430        self.try_fold_with(&mut Folder(f))
431    }
432
433    /// Shift the [`BoundVar`] of all the the variables at index [`INNERMOST`] "horizontally" to the
434    /// right by the specified `amount`.
435    fn shift_horizontally(&self, amount: usize) -> Self {
436        struct Shifter {
437            current_index: DebruijnIndex,
438            amount: usize,
439        }
440
441        impl TypeFolder for Shifter {
442            fn enter_binder(&mut self, _: &BoundVariableKinds) {
443                self.current_index.shift_in(1);
444            }
445
446            fn exit_binder(&mut self) {
447                self.current_index.shift_out(1);
448            }
449
450            fn fold_region(&mut self, re: &Region) -> Region {
451                if let ReBound(debruijn, br) = *re
452                    && debruijn == self.current_index
453                {
454                    ReBound(debruijn, BoundRegion { var: br.var + self.amount, kind: br.kind })
455                } else {
456                    *re
457                }
458            }
459
460            fn fold_expr(&mut self, expr: &Expr) -> Expr {
461                if let ExprKind::Var(Var::Bound(debruijn, breft)) = expr.kind()
462                    && debruijn == &self.current_index
463                {
464                    Expr::bvar(*debruijn, breft.var + self.amount, breft.kind)
465                } else {
466                    expr.super_fold_with(self)
467                }
468            }
469        }
470        self.fold_with(&mut Shifter { amount, current_index: INNERMOST })
471    }
472
473    fn shift_in_escaping(&self, amount: u32) -> Self {
474        struct Shifter {
475            current_index: DebruijnIndex,
476            amount: u32,
477        }
478
479        impl TypeFolder for Shifter {
480            fn enter_binder(&mut self, _: &BoundVariableKinds) {
481                self.current_index.shift_in(1);
482            }
483
484            fn exit_binder(&mut self) {
485                self.current_index.shift_out(1);
486            }
487
488            fn fold_region(&mut self, re: &Region) -> Region {
489                if let ReBound(debruijn, br) = *re
490                    && debruijn >= self.current_index
491                {
492                    ReBound(debruijn.shifted_in(self.amount), br)
493                } else {
494                    *re
495                }
496            }
497
498            fn fold_expr(&mut self, expr: &Expr) -> Expr {
499                if let ExprKind::Var(Var::Bound(debruijn, breft)) = expr.kind()
500                    && *debruijn >= self.current_index
501                {
502                    Expr::bvar(debruijn.shifted_in(self.amount), breft.var, breft.kind)
503                } else {
504                    expr.super_fold_with(self)
505                }
506            }
507        }
508        self.fold_with(&mut Shifter { amount, current_index: INNERMOST })
509    }
510
511    fn shift_out_escaping(&self, amount: u32) -> Self {
512        struct Shifter {
513            amount: u32,
514            current_index: DebruijnIndex,
515        }
516
517        impl TypeFolder for Shifter {
518            fn enter_binder(&mut self, _: &BoundVariableKinds) {
519                self.current_index.shift_in(1);
520            }
521
522            fn exit_binder(&mut self) {
523                self.current_index.shift_out(1);
524            }
525
526            fn fold_region(&mut self, re: &Region) -> Region {
527                if let ReBound(debruijn, br) = *re
528                    && debruijn >= self.current_index
529                {
530                    ReBound(debruijn.shifted_out(self.amount), br)
531                } else {
532                    *re
533                }
534            }
535
536            fn fold_expr(&mut self, expr: &Expr) -> Expr {
537                if let ExprKind::Var(Var::Bound(debruijn, breft)) = expr.kind()
538                    && debruijn >= &self.current_index
539                {
540                    Expr::bvar(debruijn.shifted_out(self.amount), breft.var, breft.kind)
541                } else {
542                    expr.super_fold_with(self)
543                }
544            }
545        }
546        self.fold_with(&mut Shifter { amount, current_index: INNERMOST })
547    }
548
549    fn erase_regions(&self) -> Self {
550        struct RegionEraser;
551        impl TypeFolder for RegionEraser {
552            fn fold_region(&mut self, r: &Region) -> Region {
553                match *r {
554                    ReBound(..) => *r,
555                    _ => ReErased,
556                }
557            }
558        }
559
560        self.fold_with(&mut RegionEraser)
561    }
562
563    /// Like [`TypeFoldable::erase_regions`], but also erases bound regions.
564    fn erase_regions_including_bound(&self) -> Self {
565        struct RegionEraser;
566        impl TypeFolder for RegionEraser {
567            fn fold_region(&mut self, _: &Region) -> Region {
568                ReErased
569            }
570        }
571
572        self.fold_with(&mut RegionEraser)
573    }
574}
575
576pub trait TypeSuperFoldable: TypeFoldable {
577    fn try_super_fold_with<F: FallibleTypeFolder>(&self, folder: &mut F) -> Result<Self, F::Error>;
578
579    fn super_fold_with<F: TypeFolder>(&self, folder: &mut F) -> Self {
580        self.try_super_fold_with(folder).into_ok()
581    }
582}
583
584impl<T: TypeVisitable> TypeVisitable for OutlivesPredicate<T> {
585    fn visit_with<V: TypeVisitor>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
586        self.0.visit_with(visitor)?;
587        self.1.visit_with(visitor)
588    }
589}
590
591impl<T: TypeFoldable> TypeFoldable for OutlivesPredicate<T> {
592    fn try_fold_with<F: FallibleTypeFolder>(&self, folder: &mut F) -> Result<Self, F::Error> {
593        Ok(OutlivesPredicate(self.0.try_fold_with(folder)?, self.1.try_fold_with(folder)?))
594    }
595}
596
597impl TypeVisitable for Sort {
598    fn visit_with<V: TypeVisitor>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
599        visitor.visit_sort(self)
600    }
601}
602
603impl TypeSuperVisitable for Sort {
604    fn super_visit_with<V: TypeVisitor>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
605        match self {
606            Sort::Tuple(sorts) => sorts.visit_with(visitor),
607            Sort::App(_, args) => args.visit_with(visitor),
608            Sort::Func(fsort) => fsort.visit_with(visitor),
609            Sort::Alias(alias_ty) => alias_ty.visit_with(visitor),
610            Sort::Int
611            | Sort::Bool
612            | Sort::Real
613            | Sort::Str
614            | Sort::Char
615            | Sort::BitVec(_)
616            | Sort::Loc
617            | Sort::Param(_)
618            | Sort::Var(_)
619            | Sort::Infer(_)
620            | Sort::RawPtr
621            | Sort::Err => ControlFlow::Continue(()),
622        }
623    }
624}
625
626impl TypeFoldable for Sort {
627    fn try_fold_with<F: FallibleTypeFolder>(&self, folder: &mut F) -> Result<Self, F::Error> {
628        folder.try_fold_sort(self)
629    }
630}
631
632impl TypeSuperFoldable for Sort {
633    fn try_super_fold_with<F: FallibleTypeFolder>(&self, folder: &mut F) -> Result<Self, F::Error> {
634        let sort = match self {
635            Sort::Tuple(sorts) => Sort::tuple(sorts.try_fold_with(folder)?),
636            Sort::App(ctor, sorts) => Sort::app(ctor.clone(), sorts.try_fold_with(folder)?),
637            Sort::Func(fsort) => Sort::Func(fsort.try_fold_with(folder)?),
638            Sort::Alias(alias_ty) => Sort::Alias(alias_ty.try_fold_with(folder)?),
639            Sort::Int
640            | Sort::Bool
641            | Sort::Real
642            | Sort::Loc
643            | Sort::Str
644            | Sort::Char
645            | Sort::BitVec(_)
646            | Sort::Param(_)
647            | Sort::Var(_)
648            | Sort::Infer(_)
649            | Sort::RawPtr
650            | Sort::Err => self.clone(),
651        };
652        Ok(sort)
653    }
654}
655
656impl TypeVisitable for PolyFuncSort {
657    fn visit_with<V: TypeVisitor>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
658        self.fsort.visit_with(visitor)
659    }
660}
661
662impl TypeFoldable for PolyFuncSort {
663    fn try_fold_with<F: FallibleTypeFolder>(&self, folder: &mut F) -> Result<Self, F::Error> {
664        Ok(PolyFuncSort { params: self.params.clone(), fsort: self.fsort.try_fold_with(folder)? })
665    }
666}
667
668impl<T> TypeVisitable for Binder<T>
669where
670    T: TypeVisitable,
671{
672    fn visit_with<V: TypeVisitor>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
673        self.vars().visit_with(visitor)?;
674        visitor.enter_binder(self.vars());
675        self.skip_binder_ref().visit_with(visitor)?;
676        visitor.exit_binder();
677        ControlFlow::Continue(())
678    }
679}
680
681impl<T> TypeSuperVisitable for Binder<T>
682where
683    T: TypeVisitable,
684{
685    fn super_visit_with<V: TypeVisitor>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
686        self.skip_binder_ref().visit_with(visitor)
687    }
688}
689
690impl<T> TypeFoldable for Binder<T>
691where
692    T: TypeFoldable,
693{
694    fn try_fold_with<F: FallibleTypeFolder>(&self, folder: &mut F) -> Result<Self, F::Error> {
695        let vars = self.vars().try_fold_with(folder)?;
696        folder.try_enter_binder(&vars);
697        let r = self.skip_binder_ref().try_fold_with(folder)?;
698        folder.try_exit_binder();
699        Ok(Binder::bind_with_vars(r, vars))
700    }
701}
702
703impl TypeVisitable for VariantSig {
704    fn visit_with<V: TypeVisitor>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
705        self.fields.visit_with(visitor)?;
706        self.idx.visit_with(visitor)
707    }
708}
709
710impl TypeFoldable for VariantSig {
711    fn try_fold_with<F: FallibleTypeFolder>(&self, folder: &mut F) -> Result<Self, F::Error> {
712        let args = self.args.try_fold_with(folder)?;
713        let fields = self.fields.try_fold_with(folder)?;
714        let idx = self.idx.try_fold_with(folder)?;
715        let requires = self.requires.try_fold_with(folder)?;
716        Ok(VariantSig::new(self.adt_def.clone(), args, fields, idx, requires))
717    }
718}
719
720impl<T: TypeVisitable> TypeVisitable for Vec<T> {
721    fn visit_with<V: TypeVisitor>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
722        self.iter().try_for_each(|t| t.visit_with(visitor))
723    }
724}
725
726impl TypeVisitable for Ensures {
727    fn visit_with<V: TypeVisitor>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
728        match self {
729            Ensures::Type(path, ty) => {
730                path.to_expr().visit_with(visitor)?;
731                ty.visit_with(visitor)
732            }
733            Ensures::Pred(e) => e.visit_with(visitor),
734        }
735    }
736}
737
738impl TypeFoldable for Ensures {
739    fn try_fold_with<F: FallibleTypeFolder>(&self, folder: &mut F) -> Result<Self, F::Error> {
740        let c = match self {
741            Ensures::Type(path, ty) => {
742                let path_expr = path.to_expr().try_fold_with(folder)?;
743                Ensures::Type(
744                    path_expr.to_path().unwrap_or_else(|| {
745                        bug!("invalid path `{path_expr:?}` produced when folding `{self:?}`",)
746                    }),
747                    ty.try_fold_with(folder)?,
748                )
749            }
750            Ensures::Pred(e) => Ensures::Pred(e.try_fold_with(folder)?),
751        };
752        Ok(c)
753    }
754}
755
756impl TypeVisitable for super::TyOrBase {
757    fn visit_with<V: TypeVisitor>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
758        match self {
759            Self::Ty(ty) => ty.visit_with(visitor),
760            Self::Base(bty) => bty.visit_with(visitor),
761        }
762    }
763}
764
765impl TypeVisitable for Ty {
766    fn visit_with<V: TypeVisitor>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
767        visitor.visit_ty(self)
768    }
769}
770
771impl TypeSuperVisitable for Ty {
772    fn super_visit_with<V: TypeVisitor>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
773        match self.kind() {
774            TyKind::Indexed(bty, idxs) => {
775                bty.visit_with(visitor)?;
776                idxs.visit_with(visitor)
777            }
778            TyKind::Exists(exists) => exists.visit_with(visitor),
779            TyKind::StrgRef(_, path, ty) => {
780                path.to_expr().visit_with(visitor)?;
781                ty.visit_with(visitor)
782            }
783            TyKind::Ptr(_, path) => path.to_expr().visit_with(visitor),
784            TyKind::Constr(pred, ty) => {
785                pred.visit_with(visitor)?;
786                ty.visit_with(visitor)
787            }
788            TyKind::Downcast(.., args, _, fields) => {
789                args.visit_with(visitor)?;
790                fields.visit_with(visitor)
791            }
792            TyKind::Blocked(ty) => ty.visit_with(visitor),
793            TyKind::Infer(_) | TyKind::Param(_) | TyKind::Discr(..) | TyKind::Uninit => {
794                ControlFlow::Continue(())
795            }
796        }
797    }
798}
799
800impl TypeFoldable for Ty {
801    fn try_fold_with<F: FallibleTypeFolder>(&self, folder: &mut F) -> Result<Self, F::Error> {
802        folder.try_fold_ty(self)
803    }
804}
805
806impl TypeSuperFoldable for Ty {
807    fn try_super_fold_with<F: FallibleTypeFolder>(&self, folder: &mut F) -> Result<Ty, F::Error> {
808        let ty = match self.kind() {
809            TyKind::Indexed(bty, idxs) => {
810                Ty::indexed(bty.try_fold_with(folder)?, idxs.try_fold_with(folder)?)
811            }
812            TyKind::Exists(exists) => TyKind::Exists(exists.try_fold_with(folder)?).intern(),
813            TyKind::StrgRef(re, path, ty) => {
814                Ty::strg_ref(
815                    re.try_fold_with(folder)?,
816                    path.to_expr()
817                        .try_fold_with(folder)?
818                        .to_path()
819                        .expect("type folding produced an invalid path"),
820                    ty.try_fold_with(folder)?,
821                )
822            }
823            TyKind::Ptr(pk, path) => {
824                let pk = match pk {
825                    PtrKind::Mut(re) => PtrKind::Mut(re.try_fold_with(folder)?),
826                    PtrKind::Box => PtrKind::Box,
827                };
828                Ty::ptr(
829                    pk,
830                    path.to_expr()
831                        .try_fold_with(folder)?
832                        .to_path()
833                        .expect("type folding produced an invalid path"),
834                )
835            }
836            TyKind::Constr(pred, ty) => {
837                Ty::constr(pred.try_fold_with(folder)?, ty.try_fold_with(folder)?)
838            }
839            TyKind::Downcast(adt, args, ty, variant, fields) => {
840                Ty::downcast(
841                    adt.clone(),
842                    args.clone(),
843                    ty.clone(),
844                    *variant,
845                    fields.try_fold_with(folder)?,
846                )
847            }
848            TyKind::Blocked(ty) => Ty::blocked(ty.try_fold_with(folder)?),
849            TyKind::Infer(_) | TyKind::Param(_) | TyKind::Uninit | TyKind::Discr(..) => {
850                self.clone()
851            }
852        };
853        Ok(ty)
854    }
855}
856
857impl TypeVisitable for Region {
858    fn visit_with<V: TypeVisitor>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
859        ControlFlow::Continue(())
860    }
861}
862
863impl TypeFoldable for Region {
864    fn try_fold_with<F: FallibleTypeFolder>(&self, folder: &mut F) -> Result<Self, F::Error> {
865        folder.try_fold_region(self)
866    }
867}
868
869impl TypeSuperFoldable for Const {
870    fn try_super_fold_with<F: FallibleTypeFolder>(
871        &self,
872        _folder: &mut F,
873    ) -> Result<Self, F::Error> {
874        // FIXME(nilehmann) we are not folding the type in `ConstKind::Value` because it's a rustc::ty::Ty
875        Ok(self.clone())
876    }
877}
878
879impl TypeVisitable for Const {
880    fn visit_with<V: TypeVisitor>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
881        ControlFlow::Continue(())
882    }
883}
884
885impl TypeFoldable for Const {
886    fn try_fold_with<F: FallibleTypeFolder>(&self, folder: &mut F) -> Result<Self, F::Error> {
887        folder.try_fold_const(self)
888    }
889}
890
891impl TypeVisitable for BaseTy {
892    fn visit_with<V: TypeVisitor>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
893        visitor.visit_bty(self)
894    }
895}
896
897impl TypeSuperVisitable for BaseTy {
898    fn super_visit_with<V: TypeVisitor>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
899        match self {
900            BaseTy::Adt(_, args) => args.visit_with(visitor),
901            BaseTy::FnDef(_, args) => args.visit_with(visitor),
902            BaseTy::Slice(ty) => ty.visit_with(visitor),
903            BaseTy::RawPtr(ty, _) => ty.visit_with(visitor),
904            BaseTy::RawPtrMetadata(ty) => ty.visit_with(visitor),
905            BaseTy::Ref(_, ty, _) => ty.visit_with(visitor),
906            BaseTy::FnPtr(poly_fn_sig) => poly_fn_sig.visit_with(visitor),
907            BaseTy::Tuple(tys) => tys.visit_with(visitor),
908            BaseTy::Alias(alias_ty) => alias_ty.visit_with(visitor),
909            BaseTy::Array(ty, _) => ty.visit_with(visitor),
910            BaseTy::Coroutine(_, resume_ty, upvars, _) => {
911                resume_ty.visit_with(visitor)?;
912                upvars.visit_with(visitor)
913            }
914            BaseTy::Dynamic(exi_preds, _) => exi_preds.visit_with(visitor),
915            BaseTy::Int(_)
916            | BaseTy::Pat
917            | BaseTy::Uint(_)
918            | BaseTy::Bool
919            | BaseTy::Float(_)
920            | BaseTy::Str
921            | BaseTy::Char
922            | BaseTy::Closure(..)
923            | BaseTy::Never
924            | BaseTy::Infer(_)
925            | BaseTy::Foreign(_)
926            | BaseTy::Param(_) => ControlFlow::Continue(()),
927        }
928    }
929}
930
931impl TypeFoldable for BaseTy {
932    fn try_fold_with<F: FallibleTypeFolder>(&self, folder: &mut F) -> Result<Self, F::Error> {
933        folder.try_fold_bty(self)
934    }
935}
936
937impl TypeSuperFoldable for BaseTy {
938    fn try_super_fold_with<F: FallibleTypeFolder>(&self, folder: &mut F) -> Result<Self, F::Error> {
939        let bty = match self {
940            BaseTy::Adt(adt_def, args) => BaseTy::adt(adt_def.clone(), args.try_fold_with(folder)?),
941            BaseTy::FnDef(def_id, args) => BaseTy::fn_def(*def_id, args.try_fold_with(folder)?),
942            BaseTy::Foreign(def_id) => BaseTy::Foreign(*def_id),
943            BaseTy::Slice(ty) => BaseTy::Slice(ty.try_fold_with(folder)?),
944            BaseTy::RawPtr(ty, mu) => BaseTy::RawPtr(ty.try_fold_with(folder)?, *mu),
945            BaseTy::RawPtrMetadata(ty) => BaseTy::RawPtrMetadata(ty.try_fold_with(folder)?),
946            BaseTy::Ref(re, ty, mutbl) => {
947                BaseTy::Ref(re.try_fold_with(folder)?, ty.try_fold_with(folder)?, *mutbl)
948            }
949            BaseTy::FnPtr(decl) => BaseTy::FnPtr(decl.try_fold_with(folder)?),
950            BaseTy::Tuple(tys) => BaseTy::Tuple(tys.try_fold_with(folder)?),
951            BaseTy::Alias(alias_ty) => BaseTy::Alias(alias_ty.try_fold_with(folder)?),
952            BaseTy::Array(ty, c) => {
953                BaseTy::Array(ty.try_fold_with(folder)?, c.try_fold_with(folder)?)
954            }
955            BaseTy::Closure(did, args, gen_args, no_panic) => {
956                BaseTy::Closure(*did, args.try_fold_with(folder)?, gen_args.clone(), *no_panic)
957            }
958            BaseTy::Coroutine(did, resume_ty, args, gen_args) => {
959                BaseTy::Coroutine(
960                    *did,
961                    resume_ty.try_fold_with(folder)?,
962                    args.try_fold_with(folder)?,
963                    gen_args.clone(),
964                )
965            }
966            BaseTy::Dynamic(preds, region) => {
967                BaseTy::Dynamic(preds.try_fold_with(folder)?, region.try_fold_with(folder)?)
968            }
969            BaseTy::Pat => BaseTy::Pat,
970            BaseTy::Int(_)
971            | BaseTy::Param(_)
972            | BaseTy::Uint(_)
973            | BaseTy::Bool
974            | BaseTy::Float(_)
975            | BaseTy::Str
976            | BaseTy::Char
977            | BaseTy::Infer(_)
978            | BaseTy::Never => self.clone(),
979        };
980        Ok(bty)
981    }
982}
983
984impl TypeVisitable for SubsetTy {
985    fn visit_with<V: TypeVisitor>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
986        self.bty.visit_with(visitor)?;
987        self.idx.visit_with(visitor)?;
988        self.pred.visit_with(visitor)
989    }
990}
991impl TypeFoldable for TyOrBase {
992    fn try_fold_with<F: FallibleTypeFolder>(&self, folder: &mut F) -> Result<Self, F::Error> {
993        match self {
994            Self::Ty(ty) => Ok(Self::Ty(ty.try_fold_with(folder)?)),
995            Self::Base(bty) => Ok(Self::Base(bty.try_fold_with(folder)?)),
996        }
997    }
998}
999
1000impl TypeFoldable for SubsetTy {
1001    fn try_fold_with<F: FallibleTypeFolder>(&self, folder: &mut F) -> Result<Self, F::Error> {
1002        folder.try_fold_subset_ty(self)
1003    }
1004}
1005
1006impl TypeSuperFoldable for SubsetTy {
1007    fn try_super_fold_with<F: FallibleTypeFolder>(&self, folder: &mut F) -> Result<Self, F::Error> {
1008        Ok(SubsetTy {
1009            bty: self.bty.try_fold_with(folder)?,
1010            idx: self.idx.try_fold_with(folder)?,
1011            pred: self.pred.try_fold_with(folder)?,
1012        })
1013    }
1014}
1015
1016impl TypeVisitable for GenericArg {
1017    fn visit_with<V: TypeVisitor>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
1018        match self {
1019            GenericArg::Ty(ty) => ty.visit_with(visitor),
1020            GenericArg::Base(ty) => ty.visit_with(visitor),
1021            GenericArg::Lifetime(_) => ControlFlow::Continue(()),
1022            GenericArg::Const(_) => ControlFlow::Continue(()),
1023        }
1024    }
1025}
1026
1027impl TypeFoldable for GenericArg {
1028    fn try_fold_with<F: FallibleTypeFolder>(&self, folder: &mut F) -> Result<Self, F::Error> {
1029        let arg = match self {
1030            GenericArg::Ty(ty) => GenericArg::Ty(ty.try_fold_with(folder)?),
1031            GenericArg::Base(ctor) => GenericArg::Base(ctor.try_fold_with(folder)?),
1032            GenericArg::Lifetime(re) => GenericArg::Lifetime(re.try_fold_with(folder)?),
1033            GenericArg::Const(c) => GenericArg::Const(c.try_fold_with(folder)?),
1034        };
1035        Ok(arg)
1036    }
1037}
1038
1039impl TypeVisitable for Expr {
1040    fn visit_with<V: TypeVisitor>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
1041        visitor.visit_expr(self)
1042    }
1043}
1044
1045impl TypeSuperVisitable for Expr {
1046    fn super_visit_with<V: TypeVisitor>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
1047        match self.kind() {
1048            ExprKind::Var(_) => ControlFlow::Continue(()),
1049            ExprKind::BinaryOp(_, e1, e2) => {
1050                e1.visit_with(visitor)?;
1051                e2.visit_with(visitor)
1052            }
1053            ExprKind::Tuple(flds) => flds.visit_with(visitor),
1054            ExprKind::Ctor(_, flds) => flds.visit_with(visitor),
1055            ExprKind::IsCtor(_, _, e) => e.visit_with(visitor),
1056            ExprKind::FieldProj(e, _) | ExprKind::PathProj(e, _) | ExprKind::UnaryOp(_, e) => {
1057                e.visit_with(visitor)
1058            }
1059            ExprKind::App(func, sorts, arg) => {
1060                func.visit_with(visitor)?;
1061                sorts.visit_with(visitor)?;
1062                arg.visit_with(visitor)
1063            }
1064            ExprKind::IfThenElse(p, e1, e2) => {
1065                p.visit_with(visitor)?;
1066                e1.visit_with(visitor)?;
1067                e2.visit_with(visitor)
1068            }
1069            ExprKind::KVar(kvar) => kvar.visit_with(visitor),
1070            ExprKind::WKVar(wkvar) => wkvar.visit_with(visitor),
1071            ExprKind::Alias(alias, args) => {
1072                alias.visit_with(visitor)?;
1073                args.visit_with(visitor)
1074            }
1075            ExprKind::Abs(body) => body.visit_with(visitor),
1076            ExprKind::Quant(_, dom, body) => {
1077                dom.visit_with(visitor)?;
1078                body.visit_with(visitor)
1079            }
1080            ExprKind::Let(init, body) => {
1081                init.visit_with(visitor)?;
1082                body.visit_with(visitor)
1083            }
1084            ExprKind::Constant(_)
1085            | ExprKind::Hole(_)
1086            | ExprKind::Local(_)
1087            | ExprKind::GlobalFunc(..)
1088            | ExprKind::InternalFunc(..)
1089            | ExprKind::ConstDefId(_) => ControlFlow::Continue(()),
1090        }
1091    }
1092}
1093
1094impl TypeFoldable for Expr {
1095    fn try_fold_with<F: FallibleTypeFolder>(&self, folder: &mut F) -> Result<Self, F::Error> {
1096        folder.try_fold_expr(self)
1097    }
1098}
1099
1100impl TypeSuperFoldable for Expr {
1101    fn try_super_fold_with<F: FallibleTypeFolder>(&self, folder: &mut F) -> Result<Self, F::Error> {
1102        let span = self.span();
1103        let expr = match self.kind() {
1104            ExprKind::Var(var) => Expr::var(*var),
1105            ExprKind::Local(local) => Expr::local(*local),
1106            ExprKind::Constant(c) => Expr::constant(*c),
1107            ExprKind::ConstDefId(did) => Expr::const_def_id(*did),
1108            ExprKind::BinaryOp(op, e1, e2) => {
1109                Expr::binary_op(
1110                    op.try_fold_with(folder)?,
1111                    e1.try_fold_with(folder)?,
1112                    e2.try_fold_with(folder)?,
1113                )
1114            }
1115            ExprKind::UnaryOp(op, e) => Expr::unary_op(*op, e.try_fold_with(folder)?),
1116            ExprKind::FieldProj(e, proj) => Expr::field_proj(e.try_fold_with(folder)?, *proj),
1117            ExprKind::Tuple(flds) => Expr::tuple(flds.try_fold_with(folder)?),
1118            ExprKind::Ctor(ctor, flds) => Expr::ctor(*ctor, flds.try_fold_with(folder)?),
1119            ExprKind::IsCtor(def_id, variant_idx, e) => {
1120                Expr::is_ctor(*def_id, *variant_idx, e.try_fold_with(folder)?)
1121            }
1122            ExprKind::PathProj(e, field) => Expr::path_proj(e.try_fold_with(folder)?, *field),
1123            ExprKind::App(func, sorts, arg) => {
1124                Expr::app(
1125                    func.try_fold_with(folder)?,
1126                    sorts.try_fold_with(folder)?,
1127                    arg.try_fold_with(folder)?,
1128                )
1129            }
1130            ExprKind::IfThenElse(p, e1, e2) => {
1131                Expr::ite(
1132                    p.try_fold_with(folder)?,
1133                    e1.try_fold_with(folder)?,
1134                    e2.try_fold_with(folder)?,
1135                )
1136            }
1137            ExprKind::Hole(kind) => Expr::hole(kind.try_fold_with(folder)?),
1138            ExprKind::KVar(kvar) => Expr::kvar(kvar.try_fold_with(folder)?),
1139            ExprKind::WKVar(wkvar) => Expr::wkvar(wkvar.try_fold_with(folder)?),
1140            ExprKind::Abs(lam) => Expr::abs(lam.try_fold_with(folder)?),
1141            ExprKind::Quant(kind, dom, body) => {
1142                Expr::quant(*kind, dom.try_fold_with(folder)?, body.try_fold_with(folder)?)
1143            }
1144            ExprKind::GlobalFunc(kind) => Expr::global_func(kind.clone()),
1145            ExprKind::InternalFunc(kind) => Expr::internal_func(kind.clone()),
1146            ExprKind::Alias(alias, args) => {
1147                Expr::alias(alias.try_fold_with(folder)?, args.try_fold_with(folder)?)
1148            }
1149            ExprKind::Let(init, body) => {
1150                Expr::let_(init.try_fold_with(folder)?, body.try_fold_with(folder)?)
1151            }
1152        };
1153        Ok(expr.at_opt(span))
1154    }
1155}
1156
1157impl<T> TypeVisitable for List<T>
1158where
1159    T: TypeVisitable,
1160    [T]: Internable,
1161{
1162    fn visit_with<V: TypeVisitor>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
1163        self.iter().try_for_each(|t| t.visit_with(visitor))
1164    }
1165}
1166
1167impl<S, T> TypeVisitable for (S, T)
1168where
1169    S: TypeVisitable,
1170    T: TypeVisitable,
1171{
1172    fn visit_with<V: TypeVisitor>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
1173        self.0.visit_with(visitor)?;
1174        self.1.visit_with(visitor)
1175    }
1176}
1177
1178impl<T> TypeFoldable for List<T>
1179where
1180    T: TypeFoldable,
1181    [T]: Internable,
1182{
1183    fn try_fold_with<F: FallibleTypeFolder>(&self, folder: &mut F) -> Result<Self, F::Error> {
1184        self.iter().map(|t| t.try_fold_with(folder)).try_collect()
1185    }
1186}
1187
1188impl<S, T> TypeFoldable for (S, T)
1189where
1190    S: TypeFoldable,
1191    T: TypeFoldable,
1192{
1193    fn try_fold_with<F: FallibleTypeFolder>(&self, folder: &mut F) -> Result<Self, F::Error> {
1194        Ok((self.0.try_fold_with(folder)?, self.1.try_fold_with(folder)?))
1195    }
1196}
1197
1198/// Used for types that are `Copy` and which **do not care arena allocated data** (i.e., don't need
1199/// to be folded).
1200macro_rules! TrivialTypeTraversalImpls {
1201    ($($ty:ty,)+) => {
1202        $(
1203            impl $crate::rty::fold::TypeFoldable for $ty {
1204                fn try_fold_with<F: $crate::rty::fold::FallibleTypeFolder>(
1205                    &self,
1206                    _: &mut F,
1207                ) -> ::std::result::Result<Self, F::Error> {
1208                    Ok(*self)
1209                }
1210
1211                #[inline]
1212                fn fold_with<F: $crate::rty::fold::TypeFolder>(
1213                    &self,
1214                    _: &mut F,
1215                ) -> Self {
1216                    *self
1217                }
1218            }
1219
1220            impl $crate::rty::fold::TypeVisitable for $ty {
1221                #[inline]
1222                fn visit_with<V: $crate::rty::fold::TypeVisitor>(
1223                    &self,
1224                    _: &mut V)
1225                    -> ::core::ops::ControlFlow<V::BreakTy>
1226                {
1227                    ::core::ops::ControlFlow::Continue(())
1228                }
1229            }
1230        )+
1231    };
1232}
1233
1234// For things that don't carry any arena-allocated data (and are copy...), just add them to this list.
1235TrivialTypeTraversalImpls! {
1236    (),
1237    bool,
1238    usize,
1239    crate::fhir::InferMode,
1240    crate::rty::BoundReftKind,
1241    crate::rty::BvSize,
1242    crate::rty::KVid,
1243    crate::def_id::FluxDefId,
1244    crate::def_id::FluxLocalDefId,
1245    rustc_span::Symbol,
1246    rustc_hir::def_id::DefId,
1247    rustc_hir::Safety,
1248    rustc_abi::ExternAbi,
1249    rustc_type_ir::ClosureKind,
1250    flux_rustc_bridge::ty::BoundRegionKind,
1251    flux_rustc_bridge::ty::AliasKind,
1252    flux_rustc_bridge::ty::AliasTermKind,
1253}