@@ -4,8 +4,9 @@ use rustc_type_ir::data_structures::{HashMap, ensure_sufficient_stack};
44use rustc_type_ir:: inherent:: * ;
55use rustc_type_ir:: solve:: { Goal , QueryInput } ;
66use 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 ,
910} ;
1011
1112use crate :: delegate:: SolverDelegate ;
@@ -109,20 +110,65 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
109110 return ( param_env, Default :: default ( ) , Vec :: new ( ) ) ;
110111 }
111112
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 } ,
115160
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 ,
120165
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+ }
126172 }
127173
128174 /// When canonicalizing query inputs, we keep `'static` in the `param_env`
0 commit comments