Skip to main content

rustc_next_trait_solver/canonical/
canonicalizer.rs

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