@@ -4,8 +4,9 @@ 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 , Flags , InferCtxtLike , Interner ,
8
- TypeFlags , TypeFoldable , TypeFolder , TypeSuperFoldable , TypeVisitableExt ,
7
+ self as ty, Canonical , CanonicalParamEnvCacheEntry , CanonicalTyVarKind , CanonicalVarKind ,
8
+ Flags , InferCtxtLike , Interner , TypeFlags , TypeFoldable , TypeFolder , TypeSuperFoldable ,
9
+ TypeVisitableExt ,
9
10
} ;
10
11
11
12
use crate :: delegate:: SolverDelegate ;
@@ -109,20 +110,65 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
109
110
return ( param_env, Default :: default ( ) , Vec :: new ( ) ) ;
110
111
}
111
112
112
- let mut env_canonicalizer = Canonicalizer {
113
- delegate,
114
- canonicalize_mode : CanonicalizeMode :: Input { keep_static : true } ,
113
+ // Check whether we can use the global cache for this param_env. As we only use
114
+ // the `param_env` itself as the cache key, considering any additional information
115
+ // durnig its canonicalization would be incorrect. We always canonicalize region
116
+ // inference variables in a separate universe, so these are fine. However, we do
117
+ // track the universe of type and const inference variables so these must not be
118
+ // globally cached. We don't rely on any additional information when canonicalizing
119
+ // placeholders.
120
+ if !param_env. has_non_region_infer ( ) {
121
+ delegate. cx ( ) . canonical_param_env_cache_get_or_insert (
122
+ param_env,
123
+ || {
124
+ let mut variables = Vec :: new ( ) ;
125
+ let mut env_canonicalizer = Canonicalizer {
126
+ delegate,
127
+ canonicalize_mode : CanonicalizeMode :: Input { keep_static : true } ,
128
+
129
+ variables : & mut variables,
130
+ variable_lookup_table : Default :: default ( ) ,
131
+ var_kinds : Vec :: new ( ) ,
132
+ binder_index : ty:: INNERMOST ,
133
+
134
+ cache : Default :: default ( ) ,
135
+ } ;
136
+ let param_env = param_env. fold_with ( & mut env_canonicalizer) ;
137
+ debug_assert_eq ! ( env_canonicalizer. binder_index, ty:: INNERMOST ) ;
138
+ CanonicalParamEnvCacheEntry {
139
+ param_env,
140
+ variable_lookup_table : env_canonicalizer. variable_lookup_table ,
141
+ var_kinds : env_canonicalizer. var_kinds ,
142
+ variables,
143
+ }
144
+ } ,
145
+ |& CanonicalParamEnvCacheEntry {
146
+ param_env,
147
+ variables : ref cache_variables,
148
+ ref variable_lookup_table,
149
+ ref var_kinds,
150
+ } | {
151
+ debug_assert ! ( variables. is_empty( ) ) ;
152
+ variables. extend ( cache_variables. iter ( ) . copied ( ) ) ;
153
+ ( param_env, variable_lookup_table. clone ( ) , var_kinds. clone ( ) )
154
+ } ,
155
+ )
156
+ } else {
157
+ let mut env_canonicalizer = Canonicalizer {
158
+ delegate,
159
+ canonicalize_mode : CanonicalizeMode :: Input { keep_static : true } ,
115
160
116
- variables,
117
- variable_lookup_table : Default :: default ( ) ,
118
- var_kinds : Vec :: new ( ) ,
119
- binder_index : ty:: INNERMOST ,
161
+ variables,
162
+ variable_lookup_table : Default :: default ( ) ,
163
+ var_kinds : Vec :: new ( ) ,
164
+ binder_index : ty:: INNERMOST ,
120
165
121
- cache : Default :: default ( ) ,
122
- } ;
123
- let param_env = param_env. fold_with ( & mut env_canonicalizer) ;
124
- debug_assert_eq ! ( env_canonicalizer. binder_index, ty:: INNERMOST ) ;
125
- ( param_env, env_canonicalizer. variable_lookup_table , env_canonicalizer. var_kinds )
166
+ cache : Default :: default ( ) ,
167
+ } ;
168
+ let param_env = param_env. fold_with ( & mut env_canonicalizer) ;
169
+ debug_assert_eq ! ( env_canonicalizer. binder_index, ty:: INNERMOST ) ;
170
+ ( param_env, env_canonicalizer. variable_lookup_table , env_canonicalizer. var_kinds )
171
+ }
126
172
}
127
173
128
174
/// When canonicalizing query inputs, we keep `'static` in the `param_env`
0 commit comments