Skip to main content

rustc_next_trait_solver/canonical/
canonicalizer.rs

1use rustc_type_ir::data_structures::{HashMap, ensure_sufficient_stack};
2use rustc_type_ir::inherent::*;
3use rustc_type_ir::solve::{Goal, QueryInput};
4use rustc_type_ir::{
5    self as ty, Canonical, CanonicalParamEnvCacheEntry, CanonicalVarKind, Flags, InferCtxtLike,
6    Interner, PlaceholderConst, PlaceholderType, TypeFlags, TypeFoldable, TypeFolder,
7    TypeSuperFoldable, TypeVisitableExt,
8};
9
10use crate::delegate::SolverDelegate;
11
12/// Does this have infer/placeholder/param, free regions or ReErased?
13const NEEDS_CANONICAL: TypeFlags = TypeFlags::from_bits(
14    TypeFlags::HAS_INFER.bits()
15        | TypeFlags::HAS_PLACEHOLDER.bits()
16        | TypeFlags::HAS_PARAM.bits()
17        | TypeFlags::HAS_FREE_REGIONS.bits()
18        | TypeFlags::HAS_RE_ERASED.bits(),
19)
20.unwrap();
21
22#[derive(#[automatically_derived]
impl ::core::fmt::Debug for CanonicalizeInputKind {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                CanonicalizeInputKind::ParamEnv => "ParamEnv",
                CanonicalizeInputKind::Predicate => "Predicate",
            })
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for CanonicalizeInputKind {
    #[inline]
    fn clone(&self) -> CanonicalizeInputKind { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for CanonicalizeInputKind { }Copy)]
23enum CanonicalizeInputKind {
24    /// When canonicalizing the `param_env`, we keep `'static` as merging
25    /// trait candidates relies on it when deciding whether a where-bound
26    /// is trivial.
27    ParamEnv,
28    /// When canonicalizing predicates, we don't keep `'static`.
29    Predicate,
30}
31
32/// Whether we're canonicalizing a query input or the query response.
33///
34/// When canonicalizing an input we're in the context of the caller
35/// while canonicalizing the response happens in the context of the
36/// query.
37#[derive(#[automatically_derived]
impl ::core::fmt::Debug for CanonicalizeMode {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            CanonicalizeMode::Input(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Input",
                    &__self_0),
            CanonicalizeMode::Response { max_input_universe: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "Response", "max_input_universe", &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for CanonicalizeMode {
    #[inline]
    fn clone(&self) -> CanonicalizeMode {
        let _: ::core::clone::AssertParamIsClone<CanonicalizeInputKind>;
        let _: ::core::clone::AssertParamIsClone<ty::UniverseIndex>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for CanonicalizeMode { }Copy)]
38enum CanonicalizeMode {
39    Input(CanonicalizeInputKind),
40    /// FIXME: We currently return region constraints referring to
41    /// placeholders and inference variables from a binder instantiated
42    /// inside of the query.
43    ///
44    /// In the long term we should eagerly deal with these constraints
45    /// inside of the query and only propagate constraints which are
46    /// actually nameable by the caller.
47    Response {
48        /// The highest universe nameable by the caller.
49        ///
50        /// All variables in a universe nameable by the caller get mapped
51        /// to the root universe in the response and then mapped back to
52        /// their correct universe when applying the query response in the
53        /// context of the caller.
54        ///
55        /// This doesn't work for universes created inside of the query so
56        /// we do remember their universe in the response.
57        max_input_universe: ty::UniverseIndex,
58    },
59}
60
61pub(super) struct Canonicalizer<'a, D: SolverDelegate<Interner = I>, I: Interner> {
62    delegate: &'a D,
63
64    // Immutable field.
65    canonicalize_mode: CanonicalizeMode,
66
67    // Mutable fields.
68    variables: Vec<I::GenericArg>,
69    var_kinds: Vec<CanonicalVarKind<I>>,
70    variable_lookup_table: HashMap<I::GenericArg, usize>,
71    /// Maps each `sub_unification_table_root_var` to the index of the first
72    /// variable which used it.
73    ///
74    /// This means in case two type variables have the same sub relations root,
75    /// we set the `sub_root` of the second variable to the position of the first.
76    /// Otherwise the `sub_root` of each type variable is just its own position.
77    sub_root_lookup_table: HashMap<ty::TyVid, usize>,
78
79    /// We can simply cache based on the ty itself, because we use
80    /// `ty::BoundVarIndexKind::Canonical`.
81    cache: HashMap<I::Ty, I::Ty>,
82}
83
84impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
85    pub(super) fn canonicalize_response<T: TypeFoldable<I>>(
86        delegate: &'a D,
87        max_input_universe: ty::UniverseIndex,
88        value: T,
89    ) -> ty::Canonical<I, T> {
90        let mut canonicalizer = Canonicalizer {
91            delegate,
92            canonicalize_mode: CanonicalizeMode::Response { max_input_universe },
93
94            variables: Vec::new(),
95            variable_lookup_table: Default::default(),
96            sub_root_lookup_table: Default::default(),
97            var_kinds: Vec::new(),
98
99            cache: Default::default(),
100        };
101
102        let value = if value.has_type_flags(NEEDS_CANONICAL) {
103            value.fold_with(&mut canonicalizer)
104        } else {
105            value
106        };
107        if true {
    if !!value.has_infer() {
        {
            ::core::panicking::panic_fmt(format_args!("unexpected infer in {0:?}",
                    value));
        }
    };
};debug_assert!(!value.has_infer(), "unexpected infer in {value:?}");
108        if true {
    if !!value.has_placeholders() {
        {
            ::core::panicking::panic_fmt(format_args!("unexpected placeholders in {0:?}",
                    value));
        }
    };
};debug_assert!(!value.has_placeholders(), "unexpected placeholders in {value:?}");
109        let (max_universe, _variables, var_kinds) = canonicalizer.finalize();
110        Canonical { max_universe, var_kinds, value }
111    }
112
113    fn canonicalize_param_env(
114        delegate: &'a D,
115        param_env: I::ParamEnv,
116    ) -> (I::ParamEnv, Vec<I::GenericArg>, Vec<CanonicalVarKind<I>>, HashMap<I::GenericArg, usize>)
117    {
118        if !param_env.has_type_flags(NEEDS_CANONICAL) {
119            return (param_env, Vec::new(), Vec::new(), Default::default());
120        }
121
122        // Check whether we can use the global cache for this param_env. As we only use
123        // the `param_env` itself as the cache key, considering any additional information
124        // durnig its canonicalization would be incorrect. We always canonicalize region
125        // inference variables in a separate universe, so these are fine. However, we do
126        // track the universe of type and const inference variables so these must not be
127        // globally cached. We don't rely on any additional information when canonicalizing
128        // placeholders.
129        if !param_env.has_non_region_infer() {
130            delegate.cx().canonical_param_env_cache_get_or_insert(
131                param_env,
132                || {
133                    let mut env_canonicalizer = Canonicalizer {
134                        delegate,
135                        canonicalize_mode: CanonicalizeMode::Input(CanonicalizeInputKind::ParamEnv),
136
137                        variables: Vec::new(),
138                        variable_lookup_table: Default::default(),
139                        sub_root_lookup_table: Default::default(),
140                        var_kinds: Vec::new(),
141
142                        cache: Default::default(),
143                    };
144                    let param_env = param_env.fold_with(&mut env_canonicalizer);
145                    if true {
    if !env_canonicalizer.sub_root_lookup_table.is_empty() {
        ::core::panicking::panic("assertion failed: env_canonicalizer.sub_root_lookup_table.is_empty()")
    };
};debug_assert!(env_canonicalizer.sub_root_lookup_table.is_empty());
146                    CanonicalParamEnvCacheEntry {
147                        param_env,
148                        variable_lookup_table: env_canonicalizer.variable_lookup_table,
149                        var_kinds: env_canonicalizer.var_kinds,
150                        variables: env_canonicalizer.variables,
151                    }
152                },
153                |&CanonicalParamEnvCacheEntry {
154                     param_env,
155                     variables: ref cache_variables,
156                     ref variable_lookup_table,
157                     ref var_kinds,
158                 }| {
159                    // FIXME(nnethercote): for reasons I don't understand, this `new`+`extend`
160                    // combination is faster than `variables.clone()`, because it somehow avoids
161                    // some allocations.
162                    let mut variables = Vec::new();
163                    variables.extend(cache_variables.iter().copied());
164                    (param_env, variables, var_kinds.clone(), variable_lookup_table.clone())
165                },
166            )
167        } else {
168            let mut env_canonicalizer = Canonicalizer {
169                delegate,
170                canonicalize_mode: CanonicalizeMode::Input(CanonicalizeInputKind::ParamEnv),
171
172                variables: Vec::new(),
173                variable_lookup_table: Default::default(),
174                sub_root_lookup_table: Default::default(),
175                var_kinds: Vec::new(),
176
177                cache: Default::default(),
178            };
179            let param_env = param_env.fold_with(&mut env_canonicalizer);
180            if true {
    if !env_canonicalizer.sub_root_lookup_table.is_empty() {
        ::core::panicking::panic("assertion failed: env_canonicalizer.sub_root_lookup_table.is_empty()")
    };
};debug_assert!(env_canonicalizer.sub_root_lookup_table.is_empty());
181            (
182                param_env,
183                env_canonicalizer.variables,
184                env_canonicalizer.var_kinds,
185                env_canonicalizer.variable_lookup_table,
186            )
187        }
188    }
189
190    /// When canonicalizing query inputs, we keep `'static` in the `param_env`
191    /// but erase it everywhere else. We generally don't want to depend on region
192    /// identity, so while it should not matter whether `'static` is kept in the
193    /// value or opaque type storage as well, this prevents us from accidentally
194    /// relying on it in the future.
195    ///
196    /// We want to keep the option of canonicalizing `'static` to an existential
197    /// variable in the future by changing the way we detect global where-bounds.
198    pub(super) fn canonicalize_input<P: TypeFoldable<I>>(
199        delegate: &'a D,
200        input: QueryInput<I, P>,
201    ) -> (Vec<I::GenericArg>, ty::Canonical<I, QueryInput<I, P>>) {
202        // First canonicalize the `param_env` while keeping `'static`
203        let (param_env, variables, var_kinds, variable_lookup_table) =
204            Canonicalizer::canonicalize_param_env(delegate, input.goal.param_env);
205        // Then canonicalize the rest of the input without keeping `'static`
206        // while *mostly* reusing the canonicalizer from above.
207        let mut rest_canonicalizer = Canonicalizer {
208            delegate,
209            canonicalize_mode: CanonicalizeMode::Input(CanonicalizeInputKind::Predicate),
210
211            variables,
212            variable_lookup_table,
213            sub_root_lookup_table: Default::default(),
214            var_kinds,
215
216            // We do not reuse the cache as it may contain entries whose canonicalized
217            // value contains `'static`. While we could alternatively handle this by
218            // checking for `'static` when using cached entries, this does not
219            // feel worth the effort. I do not expect that a `ParamEnv` will ever
220            // contain large enough types for caching to be necessary.
221            cache: Default::default(),
222        };
223
224        let predicate = input.goal.predicate;
225        let predicate = predicate.fold_with(&mut rest_canonicalizer);
226        let goal = Goal { param_env, predicate };
227
228        let predefined_opaques_in_body = input.predefined_opaques_in_body;
229        let predefined_opaques_in_body =
230            if predefined_opaques_in_body.has_type_flags(NEEDS_CANONICAL) {
231                predefined_opaques_in_body.fold_with(&mut rest_canonicalizer)
232            } else {
233                predefined_opaques_in_body
234            };
235
236        let value = QueryInput { goal, predefined_opaques_in_body };
237
238        if true {
    if !!value.has_infer() {
        {
            ::core::panicking::panic_fmt(format_args!("unexpected infer in {0:?}",
                    value));
        }
    };
};debug_assert!(!value.has_infer(), "unexpected infer in {value:?}");
239        if true {
    if !!value.has_placeholders() {
        {
            ::core::panicking::panic_fmt(format_args!("unexpected placeholders in {0:?}",
                    value));
        }
    };
};debug_assert!(!value.has_placeholders(), "unexpected placeholders in {value:?}");
240        let (max_universe, variables, var_kinds) = rest_canonicalizer.finalize();
241        (variables, Canonical { max_universe, var_kinds, value })
242    }
243
244    fn get_or_insert_bound_var(
245        &mut self,
246        arg: impl Into<I::GenericArg>,
247        kind: CanonicalVarKind<I>,
248    ) -> ty::BoundVar {
249        // The exact value of 16 here doesn't matter that much (8 and 32 give extremely similar
250        // results). So long as we have protection against the rare cases where the length reaches
251        // 1000+ (e.g. `wg-grammar`).
252        let arg = arg.into();
253        let idx = if self.variables.len() > 16 {
254            if self.variable_lookup_table.is_empty() {
255                self.variable_lookup_table.extend(self.variables.iter().copied().zip(0..));
256            }
257
258            *self.variable_lookup_table.entry(arg).or_insert_with(|| {
259                let var = self.variables.len();
260                self.variables.push(arg);
261                self.var_kinds.push(kind);
262                var
263            })
264        } else {
265            self.variables.iter().position(|&v| v == arg).unwrap_or_else(|| {
266                let var = self.variables.len();
267                self.variables.push(arg);
268                self.var_kinds.push(kind);
269                var
270            })
271        };
272
273        ty::BoundVar::from(idx)
274    }
275
276    fn get_or_insert_sub_root(&mut self, vid: ty::TyVid) -> ty::BoundVar {
277        let root_vid = self.delegate.sub_unification_table_root_var(vid);
278        let idx =
279            *self.sub_root_lookup_table.entry(root_vid).or_insert_with(|| self.variables.len());
280        ty::BoundVar::from(idx)
281    }
282
283    fn finalize(self) -> (ty::UniverseIndex, Vec<I::GenericArg>, I::CanonicalVarKinds) {
284        let mut var_kinds = self.var_kinds;
285        // See the rustc-dev-guide section about how we deal with universes
286        // during canonicalization in the new solver.
287        let max_universe = match self.canonicalize_mode {
288            // All placeholders and vars are canonicalized in the root universe.
289            CanonicalizeMode::Input { .. } => {
290                if true {
    if !var_kinds.iter().all(|var| var.universe() == ty::UniverseIndex::ROOT)
        {
        {
            ::core::panicking::panic_fmt(format_args!("expected all vars to be canonicalized in root universe: {0:#?}",
                    var_kinds));
        }
    };
};debug_assert!(
291                    var_kinds.iter().all(|var| var.universe() == ty::UniverseIndex::ROOT),
292                    "expected all vars to be canonicalized in root universe: {var_kinds:#?}"
293                );
294                ty::UniverseIndex::ROOT
295            }
296            // When canonicalizing a response we map a universes already entered
297            // by the caller to the root universe and only return useful universe
298            // information for placeholders and inference variables created inside
299            // of the query.
300            CanonicalizeMode::Response { max_input_universe } => {
301                for var in var_kinds.iter_mut() {
302                    let uv = var.universe();
303                    let new_uv = ty::UniverseIndex::from(
304                        uv.index().saturating_sub(max_input_universe.index()),
305                    );
306                    *var = var.with_updated_universe(new_uv);
307                }
308                var_kinds
309                    .iter()
310                    .map(|kind| kind.universe())
311                    .max()
312                    .unwrap_or(ty::UniverseIndex::ROOT)
313            }
314        };
315        let var_kinds = self.delegate.cx().mk_canonical_var_kinds(&var_kinds);
316        (max_universe, self.variables, var_kinds)
317    }
318
319    fn inner_fold_ty(&mut self, t: I::Ty) -> I::Ty {
320        let kind = match t.kind() {
321            ty::Infer(i) => match i {
322                ty::TyVar(vid) => {
323                    if true {
    match (&self.delegate.opportunistic_resolve_ty_var(vid), &t) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val,
                    ::core::option::Option::Some(format_args!("ty vid should have been resolved fully before canonicalization")));
            }
        }
    };
};debug_assert_eq!(
324                        self.delegate.opportunistic_resolve_ty_var(vid),
325                        t,
326                        "ty vid should have been resolved fully before canonicalization"
327                    );
328
329                    let sub_root = self.get_or_insert_sub_root(vid);
330                    let ui = match self.canonicalize_mode {
331                        CanonicalizeMode::Input { .. } => ty::UniverseIndex::ROOT,
332                        CanonicalizeMode::Response { .. } => self
333                            .delegate
334                            .universe_of_ty(vid)
335                            .unwrap_or_else(|| {
    ::core::panicking::panic_fmt(format_args!("ty var should have been resolved: {0:?}",
            t));
}panic!("ty var should have been resolved: {t:?}")),
336                    };
337                    CanonicalVarKind::Ty { ui, sub_root }
338                }
339                ty::IntVar(vid) => {
340                    if true {
    match (&self.delegate.opportunistic_resolve_int_var(vid), &t) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val,
                    ::core::option::Option::Some(format_args!("ty vid should have been resolved fully before canonicalization")));
            }
        }
    };
};debug_assert_eq!(
341                        self.delegate.opportunistic_resolve_int_var(vid),
342                        t,
343                        "ty vid should have been resolved fully before canonicalization"
344                    );
345                    CanonicalVarKind::Int
346                }
347                ty::FloatVar(vid) => {
348                    if true {
    match (&self.delegate.opportunistic_resolve_float_var(vid), &t) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val,
                    ::core::option::Option::Some(format_args!("ty vid should have been resolved fully before canonicalization")));
            }
        }
    };
};debug_assert_eq!(
349                        self.delegate.opportunistic_resolve_float_var(vid),
350                        t,
351                        "ty vid should have been resolved fully before canonicalization"
352                    );
353                    CanonicalVarKind::Float
354                }
355                ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {
356                    {
    ::core::panicking::panic_fmt(format_args!("fresh vars not expected in canonicalization"));
}panic!("fresh vars not expected in canonicalization")
357                }
358            },
359            ty::Placeholder(placeholder) => match self.canonicalize_mode {
360                CanonicalizeMode::Input { .. } => CanonicalVarKind::PlaceholderTy(
361                    PlaceholderType::new_anon(ty::UniverseIndex::ROOT, self.variables.len().into()),
362                ),
363                CanonicalizeMode::Response { .. } => CanonicalVarKind::PlaceholderTy(placeholder),
364            },
365            ty::Param(_) => match self.canonicalize_mode {
366                CanonicalizeMode::Input { .. } => CanonicalVarKind::PlaceholderTy(
367                    PlaceholderType::new_anon(ty::UniverseIndex::ROOT, self.variables.len().into()),
368                ),
369                CanonicalizeMode::Response { .. } => {
    ::core::panicking::panic_fmt(format_args!("param ty in response: {0:?}",
            t));
}panic!("param ty in response: {t:?}"),
370            },
371            ty::Bool
372            | ty::Char
373            | ty::Int(_)
374            | ty::Uint(_)
375            | ty::Float(_)
376            | ty::Adt(_, _)
377            | ty::Foreign(_)
378            | ty::Str
379            | ty::Array(_, _)
380            | ty::Slice(_)
381            | ty::RawPtr(_, _)
382            | ty::Ref(_, _, _)
383            | ty::Pat(_, _)
384            | ty::FnDef(_, _)
385            | ty::FnPtr(..)
386            | ty::UnsafeBinder(_)
387            | ty::Dynamic(_, _)
388            | ty::Closure(..)
389            | ty::CoroutineClosure(..)
390            | ty::Coroutine(_, _)
391            | ty::CoroutineWitness(..)
392            | ty::Never
393            | ty::Tuple(_)
394            | ty::Alias(_, _)
395            | ty::Bound(_, _)
396            | ty::Error(_) => {
397                return ensure_sufficient_stack(|| t.super_fold_with(self));
398            }
399        };
400
401        let var = self.get_or_insert_bound_var(t, kind);
402
403        Ty::new_canonical_bound(self.cx(), var)
404    }
405}
406
407impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicalizer<'_, D, I> {
408    fn cx(&self) -> I {
409        self.delegate.cx()
410    }
411
412    fn fold_region(&mut self, r: I::Region) -> I::Region {
413        let kind = match r.kind() {
414            ty::ReBound(..) => return r,
415
416            // We don't canonicalize `ReStatic` in the `param_env` as we use it
417            // when checking whether a `ParamEnv` candidate is global.
418            ty::ReStatic => match self.canonicalize_mode {
419                CanonicalizeMode::Input(CanonicalizeInputKind::Predicate) => {
420                    CanonicalVarKind::Region(ty::UniverseIndex::ROOT)
421                }
422                CanonicalizeMode::Input(CanonicalizeInputKind::ParamEnv)
423                | CanonicalizeMode::Response { .. } => return r,
424            },
425
426            // `ReErased` should only be encountered in the hidden
427            // type of an opaque for regions that are ignored for the purposes of
428            // captures.
429            //
430            // FIXME: We should investigate the perf implications of not uniquifying
431            // `ReErased`. We may be able to short-circuit registering region
432            // obligations if we encounter a `ReErased` on one side, for example.
433            ty::ReErased | ty::ReError(_) => match self.canonicalize_mode {
434                CanonicalizeMode::Input(_) => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
435                CanonicalizeMode::Response { .. } => return r,
436            },
437
438            ty::ReEarlyParam(_) | ty::ReLateParam(_) => match self.canonicalize_mode {
439                CanonicalizeMode::Input(_) => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
440                CanonicalizeMode::Response { .. } => {
441                    {
    ::core::panicking::panic_fmt(format_args!("unexpected region in response: {0:?}",
            r));
}panic!("unexpected region in response: {r:?}")
442                }
443            },
444
445            ty::RePlaceholder(placeholder) => match self.canonicalize_mode {
446                // We canonicalize placeholder regions as existentials in query inputs.
447                CanonicalizeMode::Input(_) => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
448                CanonicalizeMode::Response { max_input_universe } => {
449                    // If we have a placeholder region inside of a query, it must be from
450                    // a new universe.
451                    if max_input_universe.can_name(placeholder.universe()) {
452                        {
    ::core::panicking::panic_fmt(format_args!("new placeholder in universe {0:?}: {1:?}",
            max_input_universe, r));
};panic!("new placeholder in universe {max_input_universe:?}: {r:?}");
453                    }
454                    CanonicalVarKind::PlaceholderRegion(placeholder)
455                }
456            },
457
458            ty::ReVar(vid) => {
459                if true {
    match (&self.delegate.opportunistic_resolve_lt_var(vid), &r) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val,
                    ::core::option::Option::Some(format_args!("region vid should have been resolved fully before canonicalization")));
            }
        }
    };
};debug_assert_eq!(
460                    self.delegate.opportunistic_resolve_lt_var(vid),
461                    r,
462                    "region vid should have been resolved fully before canonicalization"
463                );
464                match self.canonicalize_mode {
465                    CanonicalizeMode::Input(_) => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
466                    CanonicalizeMode::Response { .. } => {
467                        CanonicalVarKind::Region(self.delegate.universe_of_lt(vid).unwrap())
468                    }
469                }
470            }
471        };
472
473        let var = self.get_or_insert_bound_var(r, kind);
474
475        Region::new_canonical_bound(self.cx(), var)
476    }
477
478    fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
479        if !t.flags().intersects(NEEDS_CANONICAL) {
480            t
481        } else if let Some(&ty) = self.cache.get(&t) {
482            ty
483        } else {
484            let res = self.inner_fold_ty(t);
485            let old = self.cache.insert(t, res);
486            match (&old, &None) {
    (left_val, right_val) => {
        if !(*left_val == *right_val) {
            let kind = ::core::panicking::AssertKind::Eq;
            ::core::panicking::assert_failed(kind, &*left_val, &*right_val,
                ::core::option::Option::None);
        }
    }
};assert_eq!(old, None);
487            res
488        }
489    }
490
491    fn fold_const(&mut self, c: I::Const) -> I::Const {
492        if !c.flags().intersects(NEEDS_CANONICAL) {
493            return c;
494        }
495
496        let kind = match c.kind() {
497            ty::ConstKind::Infer(i) => match i {
498                ty::InferConst::Var(vid) => {
499                    if true {
    match (&self.delegate.opportunistic_resolve_ct_var(vid), &c) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val,
                    ::core::option::Option::Some(format_args!("const vid should have been resolved fully before canonicalization")));
            }
        }
    };
};debug_assert_eq!(
500                        self.delegate.opportunistic_resolve_ct_var(vid),
501                        c,
502                        "const vid should have been resolved fully before canonicalization"
503                    );
504
505                    match self.canonicalize_mode {
506                        CanonicalizeMode::Input { .. } => {
507                            CanonicalVarKind::Const(ty::UniverseIndex::ROOT)
508                        }
509                        CanonicalizeMode::Response { .. } => {
510                            CanonicalVarKind::Const(self.delegate.universe_of_ct(vid).unwrap())
511                        }
512                    }
513                }
514                ty::InferConst::Fresh(_) => ::core::panicking::panic("not yet implemented")todo!(),
515            },
516            ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode {
517                CanonicalizeMode::Input { .. } => {
518                    CanonicalVarKind::PlaceholderConst(PlaceholderConst::new_anon(
519                        ty::UniverseIndex::ROOT,
520                        self.variables.len().into(),
521                    ))
522                }
523                CanonicalizeMode::Response { .. } => {
524                    CanonicalVarKind::PlaceholderConst(placeholder)
525                }
526            },
527            ty::ConstKind::Param(_) => match self.canonicalize_mode {
528                CanonicalizeMode::Input { .. } => {
529                    CanonicalVarKind::PlaceholderConst(PlaceholderConst::new_anon(
530                        ty::UniverseIndex::ROOT,
531                        self.variables.len().into(),
532                    ))
533                }
534                CanonicalizeMode::Response { .. } => {
    ::core::panicking::panic_fmt(format_args!("param ty in response: {0:?}",
            c));
}panic!("param ty in response: {c:?}"),
535            },
536            // FIXME: See comment above -- we could fold the region separately or something.
537            ty::ConstKind::Bound(_, _)
538            | ty::ConstKind::Unevaluated(_)
539            | ty::ConstKind::Value(_)
540            | ty::ConstKind::Error(_)
541            | ty::ConstKind::Expr(_) => return c.super_fold_with(self),
542        };
543
544        let var = self.get_or_insert_bound_var(c, kind);
545
546        Const::new_canonical_bound(self.cx(), var)
547    }
548
549    fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate {
550        if !p.flags().intersects(NEEDS_CANONICAL) { p } else { p.super_fold_with(self) }
551    }
552
553    fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
554        match self.canonicalize_mode {
555            CanonicalizeMode::Input(CanonicalizeInputKind::ParamEnv)
556            | CanonicalizeMode::Response { max_input_universe: _ } => {}
557            CanonicalizeMode::Input(CanonicalizeInputKind::Predicate) => {
558                { ::core::panicking::panic_fmt(format_args!("erasing \'static in env")); }panic!("erasing 'static in env")
559            }
560        }
561        if !c.flags().intersects(NEEDS_CANONICAL) { c } else { c.super_fold_with(self) }
562    }
563}