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