@@ -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