Skip to main content

rustc_next_trait_solver/canonical/
canonicalizer.rs

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