Skip to main content

rustc_type_ir/
fold.rs

1//! A folding traversal mechanism for complex data structures that contain type
2//! information.
3//!
4//! This is a modifying traversal. It consumes the data structure, producing a
5//! (possibly) modified version of it. Both fallible and infallible versions are
6//! available. The name is potentially confusing, because this traversal is more
7//! like `Iterator::map` than `Iterator::fold`.
8//!
9//! This traversal has limited flexibility. Only a small number of "types of
10//! interest" within the complex data structures can receive custom
11//! modification. These are the ones containing the most important type-related
12//! information, such as `Ty`, `Predicate`, `Region`, and `Const`.
13//!
14//! There are three traits involved in each traversal.
15//! - `TypeFoldable`. This is implemented once for many types, including:
16//!   - Types of interest, for which the methods delegate to the folder.
17//!   - All other types, including generic containers like `Vec` and `Option`.
18//!     It defines a "skeleton" of how they should be folded.
19//! - `TypeSuperFoldable`. This is implemented only for recursive types of
20//!   interest, and defines the folding "skeleton" for these types. (This
21//!   excludes `Region` because it is non-recursive, i.e. it never contains
22//!   other types of interest.)
23//! - `TypeFolder`/`FallibleTypeFolder`. One of these is implemented for each
24//!   folder. This defines how types of interest are folded.
25//!
26//! This means each fold is a mixture of (a) generic folding operations, and (b)
27//! custom fold operations that are specific to the folder.
28//! - The `TypeFoldable` impls handle most of the traversal, and call into
29//!   `TypeFolder`/`FallibleTypeFolder` when they encounter a type of interest.
30//! - A `TypeFolder`/`FallibleTypeFolder` may call into another `TypeFoldable`
31//!   impl, because some of the types of interest are recursive and can contain
32//!   other types of interest.
33//! - A `TypeFolder`/`FallibleTypeFolder` may also call into a `TypeSuperFoldable`
34//!   impl, because each folder might provide custom handling only for some types
35//!   of interest, or only for some variants of each type of interest, and then
36//!   use default traversal for the remaining cases.
37//!
38//! For example, if you have `struct S(Ty, U)` where `S: TypeFoldable` and `U:
39//! TypeFoldable`, and an instance `s = S(ty, u)`, it would be folded like so:
40//! ```text
41//! s.fold_with(folder) calls
42//! - ty.fold_with(folder) calls
43//!   - folder.fold_ty(ty) may call
44//!     - ty.super_fold_with(folder)
45//! - u.fold_with(folder)
46//! ```
47
48use std::convert::Infallible;
49use std::mem;
50use std::sync::Arc;
51
52use rustc_index::{Idx, IndexVec};
53use thin_vec::ThinVec;
54use tracing::{debug, instrument};
55
56use crate::inherent::*;
57use crate::visit::{TypeVisitable, TypeVisitableExt as _};
58use crate::{
59    self as ty, Binder, BoundVarIndexKind, ClauseKind, Flags, Interner, ProjectionClause, Region,
60    TypeSuperVisitable,
61};
62
63/// This trait is implemented for every type that can be folded,
64/// providing the skeleton of the traversal.
65///
66/// To implement this conveniently, use the derive macro located in
67/// `rustc_macros`.
68///
69/// This trait is a sub-trait of `TypeVisitable`. This is because many
70/// `TypeFolder` instances use the methods in `TypeVisitableExt` while folding,
71/// which means in practice almost every foldable type needs to also be
72/// visitable. (However, there are some types that are visitable without being
73/// foldable.)
74pub trait TypeFoldable<I: Interner>: TypeVisitable<I> + Clone {
75    /// The entry point for folding. To fold a value `t` with a folder `f`
76    /// call: `t.try_fold_with(f)`.
77    ///
78    /// For most types, this just traverses the value, calling `try_fold_with`
79    /// on each field/element.
80    ///
81    /// For types of interest (such as `Ty`), the implementation of this method
82    /// calls a folder method specifically for that type (such as
83    /// `F::try_fold_ty`). This is where control transfers from [`TypeFoldable`]
84    /// to [`FallibleTypeFolder`].
85    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error>;
86
87    /// The entry point for folding. To fold a value `t` with a folder `f`
88    /// call: `t.fold_with(f)`.
89    ///
90    /// For most types, this just traverses the value, calling `fold_with`
91    /// on each field/element.
92    ///
93    /// For types of interest (such as `Ty`), the implementation of this method
94    /// calls a folder method specifically for that type (such as
95    /// `F::fold_ty`). This is where control transfers from `TypeFoldable`
96    /// to `TypeFolder`.
97    ///
98    /// Same as [`TypeFoldable::try_fold_with`], but not fallible. Make sure to keep
99    /// the behavior in sync across functions.
100    fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self;
101}
102
103// This trait is implemented for types of interest.
104pub trait TypeSuperFoldable<I: Interner>: TypeFoldable<I> {
105    /// Provides a default fold for a recursive type of interest. This should
106    /// only be called within `TypeFolder` methods, when a non-custom traversal
107    /// is desired for the value of the type of interest passed to that method.
108    /// For example, in `MyFolder::try_fold_ty(ty)`, it is valid to call
109    /// `ty.try_super_fold_with(self)`, but any other folding should be done
110    /// with `xyz.try_fold_with(self)`.
111    fn try_super_fold_with<F: FallibleTypeFolder<I>>(
112        self,
113        folder: &mut F,
114    ) -> Result<Self, F::Error>;
115
116    /// A convenient alternative to `try_super_fold_with` for use with
117    /// infallible folders. Do not override this method, to ensure coherence
118    /// with `try_super_fold_with`.
119    fn super_fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self;
120}
121
122/// This trait is implemented for every infallible folding traversal. There is
123/// a fold method defined for every type of interest. Each such method has a
124/// default that does an "identity" fold. Implementations of these methods
125/// often fall back to a `super_fold_with` method if the primary argument
126/// doesn't satisfy a particular condition.
127pub trait TypeFolder<I: Interner>: Sized {
128    fn cx(&self) -> I;
129
130    fn fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T>
131    where
132        T: TypeFoldable<I>,
133    {
134        t.super_fold_with(self)
135    }
136
137    fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
138        t.super_fold_with(self)
139    }
140
141    // The default region folder is a no-op because `Region` is non-recursive
142    // and has no `super_fold_with` method to call.
143    fn fold_region(&mut self, r: Region<I>) -> Region<I> {
144        r
145    }
146
147    fn fold_const(&mut self, c: I::Const) -> I::Const {
148        c.super_fold_with(self)
149    }
150
151    fn fold_predicate<P: PredicateProxy<I>>(&mut self, p: P) -> P {
152        p.super_fold_with(self)
153    }
154
155    fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
156        c.super_fold_with(self)
157    }
158}
159
160/// [Fold predicate](TypeFolder::fold_predicate) deliberately doesn't get access
161/// to an actual predicate. This way, we can compress lists of predicates, and hide
162/// this detail to folders. Instead, some type implementing this trait, [`PredicateProxy`]
163/// is passed, with its limited API.
164///
165/// Most [`TypeFolder`]s only use `fold_predicate` to inspect type flags.
166pub trait PredicateProxy<I: Interner>:
167    TypeSuperFoldable<I> + TypeSuperVisitable<I> + Flags + Copy
168{
169    fn allow_normalization(&self) -> bool;
170
171    /// Gets the underlying clause kind (if this predicate is a clause, otherwise `None`).
172    /// The fact that it's `unchecked`, is because no attempt is made to hide implementation
173    /// details. For example, in the future we may compress clauses together. Code calling
174    /// `clause_kind_unchecked` will have to correctly deal with these implementation details,
175    /// and have code handling any edgecase arising as a result.
176    fn clause_kind_unchecked(&self) -> Option<Binder<I, ClauseKind<I>>>;
177
178    /// If self is a projection clause, call `f` with it. The result will be rebound and returned as `Some`.
179    /// Otherwise, when self is not a projection clause, `None` is returned.
180    fn map_projection(
181        self,
182        cx: I,
183        f: impl FnOnce(Binder<I, ProjectionClause<I>>) -> Binder<I, ProjectionClause<I>>,
184    ) -> Option<Self>;
185}
186
187/// This trait is implemented for every folding traversal. There is a fold
188/// method defined for every type of interest. Each such method has a default
189/// that does an "identity" fold.
190///
191/// A blanket implementation of this trait (that defers to the relevant
192/// method of [`TypeFolder`]) is provided for all infallible folders in
193/// order to ensure the two APIs are coherent.
194pub trait FallibleTypeFolder<I: Interner>: Sized {
195    type Error;
196
197    fn cx(&self) -> I;
198
199    fn try_fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> Result<ty::Binder<I, T>, Self::Error>
200    where
201        T: TypeFoldable<I>,
202    {
203        t.try_super_fold_with(self)
204    }
205
206    fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, Self::Error> {
207        t.try_super_fold_with(self)
208    }
209
210    // The default region folder is a no-op because `Region` is non-recursive
211    // and has no `super_fold_with` method to call.
212    fn try_fold_region(&mut self, r: Region<I>) -> Result<Region<I>, Self::Error> {
213        Ok(r)
214    }
215
216    fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, Self::Error> {
217        c.try_super_fold_with(self)
218    }
219
220    fn try_fold_predicate<P: PredicateProxy<I>>(&mut self, p: P) -> Result<P, Self::Error> {
221        p.try_super_fold_with(self)
222    }
223
224    fn try_fold_clauses(&mut self, c: I::Clauses) -> Result<I::Clauses, Self::Error> {
225        c.try_super_fold_with(self)
226    }
227}
228
229///////////////////////////////////////////////////////////////////////////
230// Traversal implementations.
231
232impl<I: Interner, T: TypeFoldable<I>, U: TypeFoldable<I>> TypeFoldable<I> for (T, U) {
233    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<(T, U), F::Error> {
234        Ok((self.0.try_fold_with(folder)?, self.1.try_fold_with(folder)?))
235    }
236
237    fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
238        (self.0.fold_with(folder), self.1.fold_with(folder))
239    }
240}
241
242impl<I: Interner, A: TypeFoldable<I>, B: TypeFoldable<I>, C: TypeFoldable<I>> TypeFoldable<I>
243    for (A, B, C)
244{
245    fn try_fold_with<F: FallibleTypeFolder<I>>(
246        self,
247        folder: &mut F,
248    ) -> Result<(A, B, C), F::Error> {
249        Ok((
250            self.0.try_fold_with(folder)?,
251            self.1.try_fold_with(folder)?,
252            self.2.try_fold_with(folder)?,
253        ))
254    }
255
256    fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
257        (self.0.fold_with(folder), self.1.fold_with(folder), self.2.fold_with(folder))
258    }
259}
260
261impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Option<T> {
262    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
263        Ok(match self {
264            Some(v) => Some(v.try_fold_with(folder)?),
265            None => None,
266        })
267    }
268
269    fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
270        Some(self?.fold_with(folder))
271    }
272}
273
274impl<I: Interner, T: TypeFoldable<I>, E: TypeFoldable<I>> TypeFoldable<I> for Result<T, E> {
275    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
276        Ok(match self {
277            Ok(v) => Ok(v.try_fold_with(folder)?),
278            Err(e) => Err(e.try_fold_with(folder)?),
279        })
280    }
281
282    fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
283        match self {
284            Ok(v) => Ok(v.fold_with(folder)),
285            Err(e) => Err(e.fold_with(folder)),
286        }
287    }
288}
289
290fn fold_arc<T: Clone, E>(
291    mut arc: Arc<T>,
292    fold: impl FnOnce(T) -> Result<T, E>,
293) -> Result<Arc<T>, E> {
294    // We merely want to replace the contained `T`, if at all possible,
295    // so that we don't needlessly allocate a new `Arc` or indeed clone
296    // the contained type.
297    unsafe {
298        // First step is to ensure that we have a unique reference to
299        // the contained type, which `Arc::make_mut` will accomplish (by
300        // allocating a new `Arc` and cloning the `T` only if required).
301        // This is done *before* casting to `Arc<ManuallyDrop<T>>` so that
302        // panicking during `make_mut` does not leak the `T`.
303        Arc::make_mut(&mut arc);
304
305        // Casting to `Arc<ManuallyDrop<T>>` is safe because `ManuallyDrop`
306        // is `repr(transparent)`.
307        let ptr = Arc::into_raw(arc).cast::<mem::ManuallyDrop<T>>();
308        let mut unique = Arc::from_raw(ptr);
309
310        // Call to `Arc::make_mut` above guarantees that `unique` is the
311        // sole reference to the contained value, so we can avoid doing
312        // a checked `get_mut` here.
313        let slot = Arc::get_mut(&mut unique).unwrap_unchecked();
314
315        // Semantically move the contained type out from `unique`, fold
316        // it, then move the folded value back into `unique`. Should
317        // folding fail, `ManuallyDrop` ensures that the "moved-out"
318        // value is not re-dropped.
319        let owned = mem::ManuallyDrop::take(slot);
320        let folded = fold(owned)?;
321        *slot = mem::ManuallyDrop::new(folded);
322
323        // Cast back to `Arc<T>`.
324        Ok(Arc::from_raw(Arc::into_raw(unique).cast()))
325    }
326}
327
328impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Arc<T> {
329    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
330        fold_arc(self, |t| t.try_fold_with(folder))
331    }
332
333    fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
334        match fold_arc::<T, Infallible>(self, |t| Ok(t.fold_with(folder))) {
335            Ok(t) => t,
336        }
337    }
338}
339
340impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Box<T> {
341    fn try_fold_with<F: FallibleTypeFolder<I>>(mut self, folder: &mut F) -> Result<Self, F::Error> {
342        *self = (*self).try_fold_with(folder)?;
343        Ok(self)
344    }
345
346    fn fold_with<F: TypeFolder<I>>(mut self, folder: &mut F) -> Self {
347        *self = (*self).fold_with(folder);
348        self
349    }
350}
351
352impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Vec<T> {
353    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
354        self.into_iter().map(|t| t.try_fold_with(folder)).collect()
355    }
356
357    fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
358        self.into_iter().map(|t| t.fold_with(folder)).collect()
359    }
360}
361
362impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for ThinVec<T> {
363    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
364        self.into_iter().map(|t| t.try_fold_with(folder)).collect()
365    }
366
367    fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
368        self.into_iter().map(|t| t.fold_with(folder)).collect()
369    }
370}
371
372impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Box<[T]> {
373    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
374        Vec::from(self).try_fold_with(folder).map(Vec::into_boxed_slice)
375    }
376
377    fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
378        Vec::into_boxed_slice(Vec::from(self).fold_with(folder))
379    }
380}
381
382impl<I: Interner, T: TypeFoldable<I>, Ix: Idx> TypeFoldable<I> for IndexVec<Ix, T> {
383    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
384        self.raw.try_fold_with(folder).map(IndexVec::from_raw)
385    }
386
387    fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
388        IndexVec::from_raw(self.raw.fold_with(folder))
389    }
390}
391
392///////////////////////////////////////////////////////////////////////////
393// Shifter
394//
395// Shifts the De Bruijn indices on all escaping bound vars by a
396// fixed amount. Useful in instantiation or when otherwise introducing
397// a binding level that is not intended to capture the existing bound
398// vars. See comment on `shift_vars_through_binders` method in
399// `rustc_middle/src/ty/generic_args.rs` for more details.
400
401struct Shifter<I: Interner> {
402    cx: I,
403    current_index: ty::DebruijnIndex,
404    amount: u32,
405}
406
407impl<I: Interner> Shifter<I> {
408    fn new(cx: I, amount: u32) -> Self {
409        Shifter { cx, current_index: ty::INNERMOST, amount }
410    }
411}
412
413impl<I: Interner> TypeFolder<I> for Shifter<I> {
414    fn cx(&self) -> I {
415        self.cx
416    }
417
418    fn fold_binder<T: TypeFoldable<I>>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> {
419        self.current_index.shift_in(1);
420        let t = t.super_fold_with(self);
421        self.current_index.shift_out(1);
422        t
423    }
424
425    fn fold_region(&mut self, r: Region<I>) -> Region<I> {
426        match r.kind() {
427            ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), br)
428                if debruijn >= self.current_index =>
429            {
430                let debruijn = debruijn.shifted_in(self.amount);
431                Region::new_bound(self.cx, debruijn, br)
432            }
433            _ => r,
434        }
435    }
436
437    fn fold_ty(&mut self, ty: I::Ty) -> I::Ty {
438        match ty.kind() {
439            ty::Bound(BoundVarIndexKind::Bound(debruijn), bound_ty)
440                if debruijn >= self.current_index =>
441            {
442                let debruijn = debruijn.shifted_in(self.amount);
443                Ty::new_bound(self.cx, debruijn, bound_ty)
444            }
445
446            _ if ty.has_vars_bound_at_or_above(self.current_index) => ty.super_fold_with(self),
447            _ => ty,
448        }
449    }
450
451    fn fold_const(&mut self, ct: I::Const) -> I::Const {
452        match ct.kind() {
453            ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_ct)
454                if debruijn >= self.current_index =>
455            {
456                let debruijn = debruijn.shifted_in(self.amount);
457                Const::new_bound(self.cx, debruijn, bound_ct)
458            }
459            _ => ct.super_fold_with(self),
460        }
461    }
462
463    fn fold_predicate<P: PredicateProxy<I>>(&mut self, p: P) -> P {
464        if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p }
465    }
466
467    fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
468        if c.has_vars_bound_at_or_above(self.current_index) { c.super_fold_with(self) } else { c }
469    }
470}
471
472pub fn shift_region<I: Interner>(cx: I, region: Region<I>, amount: u32) -> Region<I> {
473    match region.kind() {
474        ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), br) if amount > 0 => {
475            Region::new_bound(cx, debruijn.shifted_in(amount), br)
476        }
477        _ => region,
478    }
479}
480
481{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
            ::tracing::Level::TRACE <=
                ::tracing::level_filters::LevelFilter::current() || { false }
    {
    __tracing_attr_span =
        {
            use ::tracing::__macro_support::Callsite as _;
            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                {
                    static META: ::tracing::Metadata<'static> =
                        {
                            ::tracing_core::metadata::Metadata::new("shift_vars",
                                "rustc_type_ir::fold", ::tracing::Level::TRACE,
                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs"),
                                ::tracing_core::__macro_support::Option::Some(481u32),
                                ::tracing_core::__macro_support::Option::Some("rustc_type_ir::fold"),
                                ::tracing_core::field::FieldSet::new(&[{
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("value")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("value");
                                                    NAME.as_str()
                                                },
                                                {
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("amount")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("amount");
                                                    NAME.as_str()
                                                }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                ::tracing::metadata::Kind::SPAN)
                        };
                    ::tracing::callsite::DefaultCallsite::new(&META)
                };
            let mut interest = ::tracing::subscriber::Interest::never();
            if ::tracing::Level::TRACE <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::TRACE <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        { interest = __CALLSITE.interest(); !interest.is_never() }
                    &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest) {
                let meta = __CALLSITE.metadata();
                ::tracing::Span::new(meta,
                    &{
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&value)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&amount as
                                                        &dyn ::tracing::field::Value))])
                        })
            } else {
                let span =
                    ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                {};
                span
            }
        };
    __tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
    (move ||
                {

                    #[allow(unknown_lints, unreachable_code, clippy ::
                    diverging_sub_expression, clippy :: empty_loop, clippy ::
                    let_unit_value, clippy :: let_with_type_underscore, clippy
                    :: needless_return, clippy :: unreachable)]
                    if false {
                        let __tracing_attr_fake_return: T = loop {};
                        return __tracing_attr_fake_return;
                    }
                    {
                        if amount == 0 || !value.has_escaping_bound_vars() {
                            value
                        } else { value.fold_with(&mut Shifter::new(cx, amount)) }
                    }
                })();
{
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs:481",
                        "rustc_type_ir::fold", ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs"),
                        ::tracing_core::__macro_support::Option::Some(481u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_type_ir::fold"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("return")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("return");
                                            NAME.as_str()
                                        }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};
x;#[instrument(level = "trace", skip(cx), ret)]
482pub fn shift_vars<I: Interner, T>(cx: I, value: T, amount: u32) -> T
483where
484    T: TypeFoldable<I>,
485{
486    if amount == 0 || !value.has_escaping_bound_vars() {
487        value
488    } else {
489        value.fold_with(&mut Shifter::new(cx, amount))
490    }
491}
492
493///////////////////////////////////////////////////////////////////////////
494// Region folder
495
496pub fn fold_regions<I: Interner, T>(
497    cx: I,
498    value: T,
499    f: impl FnMut(Region<I>, ty::DebruijnIndex) -> Region<I>,
500) -> T
501where
502    T: TypeFoldable<I>,
503{
504    value.fold_with(&mut RegionFolder::new(cx, f))
505}
506
507/// Folds over the substructure of a type, visiting its component
508/// types and all regions that occur *free* within it.
509///
510/// That is, function pointer types and trait objects can introduce
511/// new bound regions which are not visited by this visitor as
512/// they are not free; only regions that occur free will be
513/// visited by `fold_region_fn`.
514pub struct RegionFolder<I, F> {
515    cx: I,
516
517    /// Stores the index of a binder *just outside* the stuff we have
518    /// visited. So this begins as INNERMOST; when we pass through a
519    /// binder, it is incremented (via `shift_in`).
520    current_index: ty::DebruijnIndex,
521
522    /// Callback invoked for each free region. The `DebruijnIndex`
523    /// points to the binder *just outside* the ones we have passed
524    /// through.
525    fold_region_fn: F,
526}
527
528impl<I, F> RegionFolder<I, F> {
529    #[inline]
530    pub fn new(cx: I, fold_region_fn: F) -> RegionFolder<I, F> {
531        RegionFolder { cx, current_index: ty::INNERMOST, fold_region_fn }
532    }
533}
534
535impl<I, F> TypeFolder<I> for RegionFolder<I, F>
536where
537    I: Interner,
538    F: FnMut(Region<I>, ty::DebruijnIndex) -> Region<I>,
539{
540    fn cx(&self) -> I {
541        self.cx
542    }
543
544    fn fold_binder<T: TypeFoldable<I>>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> {
545        self.current_index.shift_in(1);
546        let t = t.super_fold_with(self);
547        self.current_index.shift_out(1);
548        t
549    }
550
551    {}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
            ::tracing::Level::DEBUG <=
                ::tracing::level_filters::LevelFilter::current() || { false }
    {
    __tracing_attr_span =
        {
            use ::tracing::__macro_support::Callsite as _;
            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                {
                    static META: ::tracing::Metadata<'static> =
                        {
                            ::tracing_core::metadata::Metadata::new("fold_region",
                                "rustc_type_ir::fold", ::tracing::Level::DEBUG,
                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs"),
                                ::tracing_core::__macro_support::Option::Some(551u32),
                                ::tracing_core::__macro_support::Option::Some("rustc_type_ir::fold"),
                                ::tracing_core::field::FieldSet::new(&[{
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("r")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("r");
                                                    NAME.as_str()
                                                }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                ::tracing::metadata::Kind::SPAN)
                        };
                    ::tracing::callsite::DefaultCallsite::new(&META)
                };
            let mut interest = ::tracing::subscriber::Interest::never();
            if ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        { interest = __CALLSITE.interest(); !interest.is_never() }
                    &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest) {
                let meta = __CALLSITE.metadata();
                ::tracing::Span::new(meta,
                    &{
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&r)
                                                        as &dyn ::tracing::field::Value))])
                        })
            } else {
                let span =
                    ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                {};
                span
            }
        };
    __tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
    (move ||
                {

                    #[allow(unknown_lints, unreachable_code, clippy ::
                    diverging_sub_expression, clippy :: empty_loop, clippy ::
                    let_unit_value, clippy :: let_with_type_underscore, clippy
                    :: needless_return, clippy :: unreachable)]
                    if false {
                        let __tracing_attr_fake_return: Region<I> = loop {};
                        return __tracing_attr_fake_return;
                    }
                    {
                        match r.kind() {
                            ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _) if
                                debruijn < self.current_index => {
                                {
                                    use ::tracing::__macro_support::Callsite as _;
                                    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                        {
                                            static META: ::tracing::Metadata<'static> =
                                                {
                                                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs:557",
                                                        "rustc_type_ir::fold", ::tracing::Level::DEBUG,
                                                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs"),
                                                        ::tracing_core::__macro_support::Option::Some(557u32),
                                                        ::tracing_core::__macro_support::Option::Some("rustc_type_ir::fold"),
                                                        ::tracing_core::field::FieldSet::new(&["message",
                                                                        {
                                                                            const NAME:
                                                                                ::tracing::__macro_support::FieldName<{
                                                                                    ::tracing::__macro_support::FieldName::len("self.current_index")
                                                                                }> =
                                                                                ::tracing::__macro_support::FieldName::new("self.current_index");
                                                                            NAME.as_str()
                                                                        }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                                        ::tracing::metadata::Kind::EVENT)
                                                };
                                            ::tracing::callsite::DefaultCallsite::new(&META)
                                        };
                                    let enabled =
                                        ::tracing::Level::DEBUG <=
                                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                                ::tracing::Level::DEBUG <=
                                                    ::tracing::level_filters::LevelFilter::current() &&
                                            {
                                                let interest = __CALLSITE.interest();
                                                !interest.is_never() &&
                                                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                                        interest)
                                            };
                                    if enabled {
                                        (|value_set: ::tracing::field::ValueSet|
                                                    {
                                                        let meta = __CALLSITE.metadata();
                                                        ::tracing::Event::dispatch(meta, &value_set);
                                                        ;
                                                    })({
                                                #[allow(unused_imports)]
                                                use ::tracing::field::{debug, display, Value};
                                                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("skipped bound region")
                                                                            as &dyn ::tracing::field::Value)),
                                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&self.current_index)
                                                                            as &dyn ::tracing::field::Value))])
                                            });
                                    } else { ; }
                                };
                                r
                            }
                            ty::ReBound(ty::BoundVarIndexKind::Canonical, _) => {
                                {
                                    use ::tracing::__macro_support::Callsite as _;
                                    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                        {
                                            static META: ::tracing::Metadata<'static> =
                                                {
                                                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs:561",
                                                        "rustc_type_ir::fold", ::tracing::Level::DEBUG,
                                                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs"),
                                                        ::tracing_core::__macro_support::Option::Some(561u32),
                                                        ::tracing_core::__macro_support::Option::Some("rustc_type_ir::fold"),
                                                        ::tracing_core::field::FieldSet::new(&["message",
                                                                        {
                                                                            const NAME:
                                                                                ::tracing::__macro_support::FieldName<{
                                                                                    ::tracing::__macro_support::FieldName::len("self.current_index")
                                                                                }> =
                                                                                ::tracing::__macro_support::FieldName::new("self.current_index");
                                                                            NAME.as_str()
                                                                        }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                                        ::tracing::metadata::Kind::EVENT)
                                                };
                                            ::tracing::callsite::DefaultCallsite::new(&META)
                                        };
                                    let enabled =
                                        ::tracing::Level::DEBUG <=
                                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                                ::tracing::Level::DEBUG <=
                                                    ::tracing::level_filters::LevelFilter::current() &&
                                            {
                                                let interest = __CALLSITE.interest();
                                                !interest.is_never() &&
                                                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                                        interest)
                                            };
                                    if enabled {
                                        (|value_set: ::tracing::field::ValueSet|
                                                    {
                                                        let meta = __CALLSITE.metadata();
                                                        ::tracing::Event::dispatch(meta, &value_set);
                                                        ;
                                                    })({
                                                #[allow(unused_imports)]
                                                use ::tracing::field::{debug, display, Value};
                                                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("skipped bound region")
                                                                            as &dyn ::tracing::field::Value)),
                                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&self.current_index)
                                                                            as &dyn ::tracing::field::Value))])
                                            });
                                    } else { ; }
                                };
                                r
                            }
                            _ => {
                                {
                                    use ::tracing::__macro_support::Callsite as _;
                                    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                        {
                                            static META: ::tracing::Metadata<'static> =
                                                {
                                                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs:565",
                                                        "rustc_type_ir::fold", ::tracing::Level::DEBUG,
                                                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs"),
                                                        ::tracing_core::__macro_support::Option::Some(565u32),
                                                        ::tracing_core::__macro_support::Option::Some("rustc_type_ir::fold"),
                                                        ::tracing_core::field::FieldSet::new(&["message",
                                                                        {
                                                                            const NAME:
                                                                                ::tracing::__macro_support::FieldName<{
                                                                                    ::tracing::__macro_support::FieldName::len("self.current_index")
                                                                                }> =
                                                                                ::tracing::__macro_support::FieldName::new("self.current_index");
                                                                            NAME.as_str()
                                                                        }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                                        ::tracing::metadata::Kind::EVENT)
                                                };
                                            ::tracing::callsite::DefaultCallsite::new(&META)
                                        };
                                    let enabled =
                                        ::tracing::Level::DEBUG <=
                                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                                ::tracing::Level::DEBUG <=
                                                    ::tracing::level_filters::LevelFilter::current() &&
                                            {
                                                let interest = __CALLSITE.interest();
                                                !interest.is_never() &&
                                                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                                        interest)
                                            };
                                    if enabled {
                                        (|value_set: ::tracing::field::ValueSet|
                                                    {
                                                        let meta = __CALLSITE.metadata();
                                                        ::tracing::Event::dispatch(meta, &value_set);
                                                        ;
                                                    })({
                                                #[allow(unused_imports)]
                                                use ::tracing::field::{debug, display, Value};
                                                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("folding free region")
                                                                            as &dyn ::tracing::field::Value)),
                                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&self.current_index)
                                                                            as &dyn ::tracing::field::Value))])
                                            });
                                    } else { ; }
                                };
                                (self.fold_region_fn)(r, self.current_index)
                            }
                        }
                    }
                })();
{
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs:551",
                        "rustc_type_ir::fold", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs"),
                        ::tracing_core::__macro_support::Option::Some(551u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_type_ir::fold"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("return")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("return");
                                            NAME.as_str()
                                        }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};
x;#[instrument(skip(self), level = "debug", ret)]
552    fn fold_region(&mut self, r: Region<I>) -> Region<I> {
553        match r.kind() {
554            ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _)
555                if debruijn < self.current_index =>
556            {
557                debug!(?self.current_index, "skipped bound region");
558                r
559            }
560            ty::ReBound(ty::BoundVarIndexKind::Canonical, _) => {
561                debug!(?self.current_index, "skipped bound region");
562                r
563            }
564            _ => {
565                debug!(?self.current_index, "folding free region");
566                (self.fold_region_fn)(r, self.current_index)
567            }
568        }
569    }
570
571    fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
572        if t.has_regions() { t.super_fold_with(self) } else { t }
573    }
574
575    fn fold_const(&mut self, ct: I::Const) -> I::Const {
576        if ct.has_regions() { ct.super_fold_with(self) } else { ct }
577    }
578
579    fn fold_predicate<P: PredicateProxy<I>>(&mut self, p: P) -> P {
580        if p.has_regions() { p.super_fold_with(self) } else { p }
581    }
582
583    fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
584        if c.has_regions() { c.super_fold_with(self) } else { c }
585    }
586}
587
588/// This function should ideally only be used if either the `TypingMode`
589/// or the `ParamEnv` differs from the environment the aliases were normalized
590/// in.
591///
592/// Cases outside these two should consider whether the problem can be
593/// fixed at the root instead.
594pub fn set_aliases_to_non_rigid<I: Interner, T>(cx: I, value: T) -> ty::Unnormalized<I, T>
595where
596    T: TypeFoldable<I>,
597{
598    let folded = set_aliases_rigidness_with_mode(cx, value, RigidnessFoldMode::AllToNonRigid);
599    ty::Unnormalized::new(folded)
600}
601
602pub fn set_opaques_to_non_rigid<I: Interner, T>(cx: I, value: T) -> ty::Unnormalized<I, T>
603where
604    T: TypeFoldable<I>,
605{
606    let folded = set_aliases_rigidness_with_mode(cx, value, RigidnessFoldMode::OpaqueToNonRigid);
607    ty::Unnormalized::new(folded)
608}
609
610pub fn set_aliases_to_rigid<I: Interner, T>(cx: I, value: T) -> T
611where
612    T: TypeFoldable<I>,
613{
614    set_aliases_rigidness_with_mode(cx, value, RigidnessFoldMode::AllToRigid)
615}
616
617pub fn set_type_aliases_to_rigid<I: Interner, T>(cx: I, value: T) -> T
618where
619    T: TypeFoldable<I>,
620{
621    set_aliases_rigidness_with_mode(cx, value, RigidnessFoldMode::TypeToRigid)
622}
623
624fn set_aliases_rigidness_with_mode<I: Interner, T>(cx: I, value: T, mode: RigidnessFoldMode) -> T
625where
626    T: TypeFoldable<I>,
627{
628    if !mode.needs_change(&value) {
629        return value;
630    }
631
632    let mut folder = RigidnessFolder { cx, mode };
633    value.fold_with(&mut folder)
634}
635
636enum RigidnessFoldMode {
637    AllToRigid,
638    AllToNonRigid,
639    TypeToRigid,
640    OpaqueToNonRigid,
641}
642
643impl RigidnessFoldMode {
644    fn needs_change<I: Interner, T: TypeVisitable<I>>(&self, v: &T) -> bool {
645        match self {
646            RigidnessFoldMode::AllToRigid => v.has_non_rigid_aliases(),
647            RigidnessFoldMode::AllToNonRigid => v.has_rigid_aliases(),
648            RigidnessFoldMode::TypeToRigid => {
649                v.has_non_rigid_aliases()
650                    && v.has_type_flags(ty::TypeFlags::HAS_ALIAS - ty::TypeFlags::HAS_CONST_ALIAS)
651            }
652            RigidnessFoldMode::OpaqueToNonRigid => v.has_rigid_aliases() && v.has_opaque_types(),
653        }
654    }
655}
656
657// Set aliases to be rigid or non-rigid according to the mode.
658struct RigidnessFolder<I: Interner> {
659    cx: I,
660    mode: RigidnessFoldMode,
661}
662
663impl<I: Interner> TypeFolder<I> for RigidnessFolder<I> {
664    #[inline]
665    fn cx(&self) -> I {
666        self.cx
667    }
668
669    fn fold_binder<T: TypeFoldable<I>>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> {
670        if self.mode.needs_change(&t) { t.super_fold_with(self) } else { t }
671    }
672
673    fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
674        if !self.mode.needs_change(&t) {
675            return t;
676        }
677
678        match t.kind() {
679            ty::Alias(is_rigid, alias_ty) => {
680                let alias_ty = alias_ty.fold_with(self);
681                match self.mode {
682                    RigidnessFoldMode::AllToRigid | RigidnessFoldMode::TypeToRigid => {
683                        I::Ty::new_alias(self.cx(), ty::IsRigid::Yes, alias_ty)
684                    }
685                    RigidnessFoldMode::AllToNonRigid => {
686                        I::Ty::new_alias(self.cx(), ty::IsRigid::No, alias_ty)
687                    }
688                    RigidnessFoldMode::OpaqueToNonRigid => {
689                        if let ty::AliasTyKind::Opaque { .. } = alias_ty.kind {
690                            I::Ty::new_alias(self.cx(), ty::IsRigid::No, alias_ty)
691                        } else {
692                            I::Ty::new_alias(self.cx(), is_rigid, alias_ty)
693                        }
694                    }
695                }
696            }
697            _ => t.super_fold_with(self),
698        }
699    }
700
701    fn fold_const(&mut self, c: I::Const) -> I::Const {
702        if !self.mode.needs_change(&c) {
703            return c;
704        }
705
706        match c.kind() {
707            ty::ConstKind::Alias(is_rigid, alias_const) => {
708                let alias_const = alias_const.fold_with(self);
709                match self.mode {
710                    RigidnessFoldMode::AllToRigid => {
711                        I::Const::new_alias(self.cx, ty::IsRigid::Yes, alias_const)
712                    }
713                    RigidnessFoldMode::AllToNonRigid => {
714                        I::Const::new_alias(self.cx(), ty::IsRigid::No, alias_const)
715                    }
716                    RigidnessFoldMode::OpaqueToNonRigid | RigidnessFoldMode::TypeToRigid => {
717                        I::Const::new_alias(self.cx(), is_rigid, alias_const)
718                    }
719                }
720            }
721            _ => c.super_fold_with(self),
722        }
723    }
724
725    fn fold_predicate<P: PredicateProxy<I>>(&mut self, p: P) -> P {
726        if self.mode.needs_change(&p) { p.super_fold_with(self) } else { p }
727    }
728
729    fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
730        if self.mode.needs_change(&c) { c.super_fold_with(self) } else { c }
731    }
732}