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
15const 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 ParamEnv,
31 Predicate,
33}
34
35#[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 Response {
51 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 canonicalize_mode: CanonicalizeMode,
69
70 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 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 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 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 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 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 #[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 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 #[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_and_make_rest()
190 }
191 }
192
193 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 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 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 let max_universe = match self.canonicalize_mode {
278 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 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 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 let kind = match r.kind() {
426 ty::ReBound(..) => return r,
427
428 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 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 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 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}