@@ -4,12 +4,22 @@ use rustc_type_ir::data_structures::{HashMap, ensure_sufficient_stack};
4
4
use rustc_type_ir::inherent::*;
5
5
use rustc_type_ir::solve::{Goal, QueryInput};
6
6
use rustc_type_ir::{
7
- self as ty, Canonical, CanonicalTyVarKind, CanonicalVarKind, InferCtxtLike, Interner,
8
- TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
7
+ self as ty, Canonical, CanonicalTyVarKind, CanonicalVarKind, Flags, InferCtxtLike, Interner,
8
+ TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
9
9
};
10
10
11
11
use crate::delegate::SolverDelegate;
12
12
13
+ /// Does this have infer/placeholder/param, free regions or ReErased?
14
+ const NEEDS_CANONICAL: TypeFlags = TypeFlags::from_bits(
15
+ TypeFlags::HAS_INFER.bits()
16
+ | TypeFlags::HAS_PLACEHOLDER.bits()
17
+ | TypeFlags::HAS_PARAM.bits()
18
+ | TypeFlags::HAS_FREE_REGIONS.bits()
19
+ | TypeFlags::HAS_RE_ERASED.bits(),
20
+ )
21
+ .unwrap();
22
+
13
23
/// Whether we're canonicalizing a query input or the query response.
14
24
///
15
25
/// When canonicalizing an input we're in the context of the caller
@@ -79,7 +89,11 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
79
89
cache: Default::default(),
80
90
};
81
91
82
- let value = value.fold_with(&mut canonicalizer);
92
+ let value = if value.has_type_flags(NEEDS_CANONICAL) {
93
+ value.fold_with(&mut canonicalizer)
94
+ } else {
95
+ value
96
+ };
83
97
assert!(!value.has_infer(), "unexpected infer in {value:?}");
84
98
assert!(!value.has_placeholders(), "unexpected placeholders in {value:?}");
85
99
let (max_universe, variables) = canonicalizer.finalize();
@@ -111,7 +125,14 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
111
125
112
126
cache: Default::default(),
113
127
};
114
- let param_env = input.goal.param_env.fold_with(&mut env_canonicalizer);
128
+
129
+ let param_env = input.goal.param_env;
130
+ let param_env = if param_env.has_type_flags(NEEDS_CANONICAL) {
131
+ param_env.fold_with(&mut env_canonicalizer)
132
+ } else {
133
+ param_env
134
+ };
135
+
115
136
debug_assert_eq!(env_canonicalizer.binder_index, ty::INNERMOST);
116
137
// Then canonicalize the rest of the input without keeping `'static`
117
138
// while *mostly* reusing the canonicalizer from above.
@@ -134,10 +155,22 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
134
155
cache: Default::default(),
135
156
};
136
157
137
- let predicate = input.goal.predicate.fold_with(&mut rest_canonicalizer);
158
+ let predicate = input.goal.predicate;
159
+ let predicate = if predicate.has_type_flags(NEEDS_CANONICAL) {
160
+ predicate.fold_with(&mut rest_canonicalizer)
161
+ } else {
162
+ predicate
163
+ };
138
164
let goal = Goal { param_env, predicate };
165
+
166
+ let predefined_opaques_in_body = input.predefined_opaques_in_body;
139
167
let predefined_opaques_in_body =
140
- input.predefined_opaques_in_body.fold_with(&mut rest_canonicalizer);
168
+ if input.predefined_opaques_in_body.has_type_flags(NEEDS_CANONICAL) {
169
+ predefined_opaques_in_body.fold_with(&mut rest_canonicalizer)
170
+ } else {
171
+ predefined_opaques_in_body
172
+ };
173
+
141
174
let value = QueryInput { goal, predefined_opaques_in_body };
142
175
143
176
assert!(!value.has_infer(), "unexpected infer in {value:?}");
@@ -387,7 +420,11 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
387
420
| ty::Alias(_, _)
388
421
| ty::Bound(_, _)
389
422
| ty::Error(_) => {
390
- return ensure_sufficient_stack(|| t.super_fold_with(self));
423
+ return if t.has_type_flags(NEEDS_CANONICAL) {
424
+ ensure_sufficient_stack(|| t.super_fold_with(self))
425
+ } else {
426
+ t
427
+ };
391
428
}
392
429
};
393
430
@@ -522,11 +559,17 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
522
559
| ty::ConstKind::Unevaluated(_)
523
560
| ty::ConstKind::Value(_)
524
561
| ty::ConstKind::Error(_)
525
- | ty::ConstKind::Expr(_) => return c.super_fold_with(self),
562
+ | ty::ConstKind::Expr(_) => {
563
+ return if c.has_type_flags(NEEDS_CANONICAL) { c.super_fold_with(self) } else { c };
564
+ }
526
565
};
527
566
528
567
let var = self.get_or_insert_bound_var(c, kind);
529
568
530
569
Const::new_anon_bound(self.cx(), self.binder_index, var)
531
570
}
571
+
572
+ fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate {
573
+ if p.flags().intersects(NEEDS_CANONICAL) { p.super_fold_with(self) } else { p }
574
+ }
532
575
}
0 commit comments