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