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