@@ -3,6 +3,7 @@ use std::cmp::Ordering;
33use rustc_type_ir:: data_structures:: HashMap ;
44use rustc_type_ir:: fold:: { TypeFoldable , TypeFolder , TypeSuperFoldable } ;
55use rustc_type_ir:: inherent:: * ;
6+ use rustc_type_ir:: solve:: { Goal , QueryInput } ;
67use rustc_type_ir:: visit:: TypeVisitableExt ;
78use rustc_type_ir:: {
89 self as ty, Canonical , CanonicalTyVarKind , CanonicalVarInfo , CanonicalVarKind , InferCtxtLike ,
@@ -17,8 +18,11 @@ use crate::delegate::SolverDelegate;
1718/// while canonicalizing the response happens in the context of the
1819/// query.
1920#[ derive( Debug , Clone , Copy ) ]
20- pub enum CanonicalizeMode {
21- Input ,
21+ enum CanonicalizeMode {
22+ /// When canonicalizing the `param_env`, we keep `'static` as merging
23+ /// trait candidates relies on it when deciding whether a where-bound
24+ /// is trivial.
25+ Input { keep_static : bool } ,
2226 /// FIXME: We currently return region constraints referring to
2327 /// placeholders and inference variables from a binder instantiated
2428 /// inside of the query.
@@ -59,15 +63,15 @@ pub struct Canonicalizer<'a, D: SolverDelegate<Interner = I>, I: Interner> {
5963}
6064
6165impl < ' a , D : SolverDelegate < Interner = I > , I : Interner > Canonicalizer < ' a , D , I > {
62- pub fn canonicalize < T : TypeFoldable < I > > (
66+ pub fn canonicalize_response < T : TypeFoldable < I > > (
6367 delegate : & ' a D ,
64- canonicalize_mode : CanonicalizeMode ,
68+ max_input_universe : ty :: UniverseIndex ,
6569 variables : & ' a mut Vec < I :: GenericArg > ,
6670 value : T ,
6771 ) -> ty:: Canonical < I , T > {
6872 let mut canonicalizer = Canonicalizer {
6973 delegate,
70- canonicalize_mode,
74+ canonicalize_mode : CanonicalizeMode :: Response { max_input_universe } ,
7175
7276 variables,
7377 variable_lookup_table : Default :: default ( ) ,
@@ -80,9 +84,67 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
8084 let value = value. fold_with ( & mut canonicalizer) ;
8185 assert ! ( !value. has_infer( ) , "unexpected infer in {value:?}" ) ;
8286 assert ! ( !value. has_placeholders( ) , "unexpected placeholders in {value:?}" ) ;
83-
8487 let ( max_universe, variables) = canonicalizer. finalize ( ) ;
88+ Canonical { max_universe, variables, value }
89+ }
90+
91+ /// When canonicalizing query inputs, we keep `'static` in the `param_env`
92+ /// but erase it everywhere else. We generally don't want to depend on region
93+ /// identity, so while it should not matter whether `'static` is kept in the
94+ /// value or opaque type storage as well, this prevents us from accidentally
95+ /// relying on it in the future.
96+ ///
97+ /// We want to keep the option of canonicalizing `'static` to an existential
98+ /// variable in the future by changing the way we detect global where-bounds.
99+ pub fn canonicalize_input < P : TypeFoldable < I > > (
100+ delegate : & ' a D ,
101+ variables : & ' a mut Vec < I :: GenericArg > ,
102+ input : QueryInput < I , P > ,
103+ ) -> ty:: Canonical < I , QueryInput < I , P > > {
104+ // First canonicalize the `param_env` while keeping `'static`
105+ let mut env_canonicalizer = Canonicalizer {
106+ delegate,
107+ canonicalize_mode : CanonicalizeMode :: Input { keep_static : true } ,
108+
109+ variables,
110+ variable_lookup_table : Default :: default ( ) ,
111+ primitive_var_infos : Vec :: new ( ) ,
112+ binder_index : ty:: INNERMOST ,
113+
114+ cache : Default :: default ( ) ,
115+ } ;
116+ let param_env = input. goal . param_env . fold_with ( & mut env_canonicalizer) ;
117+ debug_assert_eq ! ( env_canonicalizer. binder_index, ty:: INNERMOST ) ;
118+ // Then canonicalize the rest of the input without keeping `'static`
119+ // while *mostly* reusing the canonicalizer from above.
120+ let mut rest_canonicalizer = Canonicalizer {
121+ delegate,
122+ canonicalize_mode : CanonicalizeMode :: Input { keep_static : false } ,
123+
124+ variables : env_canonicalizer. variables ,
125+ // We're able to reuse the `variable_lookup_table` as whether or not
126+ // it already contains an entry for `'static` does not matter.
127+ variable_lookup_table : env_canonicalizer. variable_lookup_table ,
128+ primitive_var_infos : env_canonicalizer. primitive_var_infos ,
129+ binder_index : ty:: INNERMOST ,
85130
131+ // We do not reuse the cache as it may contain entries whose canonicalized
132+ // value contains `'static`. While we could alternatively handle this by
133+ // checking for `'static` when using cached entries, this does not
134+ // feel worth the effort. I do not expect that a `ParamEnv` will ever
135+ // contain large enough types for caching to be necessary.
136+ cache : Default :: default ( ) ,
137+ } ;
138+
139+ let predicate = input. goal . predicate . fold_with ( & mut rest_canonicalizer) ;
140+ let goal = Goal { param_env, predicate } ;
141+ let predefined_opaques_in_body =
142+ input. predefined_opaques_in_body . fold_with ( & mut rest_canonicalizer) ;
143+ let value = QueryInput { goal, predefined_opaques_in_body } ;
144+
145+ assert ! ( !value. has_infer( ) , "unexpected infer in {value:?}" ) ;
146+ assert ! ( !value. has_placeholders( ) , "unexpected placeholders in {value:?}" ) ;
147+ let ( max_universe, variables) = rest_canonicalizer. finalize ( ) ;
86148 Canonical { max_universe, variables, value }
87149 }
88150
@@ -126,7 +188,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
126188 // all information which should not matter for the solver.
127189 //
128190 // For this we compress universes as much as possible.
129- CanonicalizeMode :: Input => { }
191+ CanonicalizeMode :: Input { .. } => { }
130192 // When canonicalizing a response we map a universes already entered
131193 // by the caller to the root universe and only return useful universe
132194 // information for placeholders and inference variables created inside
@@ -290,17 +352,15 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
290352 }
291353 } ,
292354 ty:: Placeholder ( placeholder) => match self . canonicalize_mode {
293- CanonicalizeMode :: Input => CanonicalVarKind :: PlaceholderTy ( PlaceholderLike :: new (
294- placeholder. universe ( ) ,
295- self . variables . len ( ) . into ( ) ,
296- ) ) ,
355+ CanonicalizeMode :: Input { .. } => CanonicalVarKind :: PlaceholderTy (
356+ PlaceholderLike :: new ( placeholder. universe ( ) , self . variables . len ( ) . into ( ) ) ,
357+ ) ,
297358 CanonicalizeMode :: Response { .. } => CanonicalVarKind :: PlaceholderTy ( placeholder) ,
298359 } ,
299360 ty:: Param ( _) => match self . canonicalize_mode {
300- CanonicalizeMode :: Input => CanonicalVarKind :: PlaceholderTy ( PlaceholderLike :: new (
301- ty:: UniverseIndex :: ROOT ,
302- self . variables . len ( ) . into ( ) ,
303- ) ) ,
361+ CanonicalizeMode :: Input { .. } => CanonicalVarKind :: PlaceholderTy (
362+ PlaceholderLike :: new ( ty:: UniverseIndex :: ROOT , self . variables . len ( ) . into ( ) ) ,
363+ ) ,
304364 CanonicalizeMode :: Response { .. } => panic ! ( "param ty in response: {t:?}" ) ,
305365 } ,
306366 ty:: Bool
@@ -357,29 +417,38 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
357417 let kind = match r. kind ( ) {
358418 ty:: ReBound ( ..) => return r,
359419
360- // We may encounter `ReStatic` in item signatures or the hidden type
361- // of an opaque. `ReErased` should only be encountered in the hidden
420+ // We don't canonicalize `ReStatic` in the `param_env` as we use it
421+ // when checking whether a `ParamEnv` candidate is global.
422+ ty:: ReStatic => match self . canonicalize_mode {
423+ CanonicalizeMode :: Input { keep_static : false } => {
424+ CanonicalVarKind :: Region ( ty:: UniverseIndex :: ROOT )
425+ }
426+ CanonicalizeMode :: Input { keep_static : true }
427+ | CanonicalizeMode :: Response { .. } => return r,
428+ } ,
429+
430+ // `ReErased` should only be encountered in the hidden
362431 // type of an opaque for regions that are ignored for the purposes of
363432 // captures.
364433 //
365434 // FIXME: We should investigate the perf implications of not uniquifying
366435 // `ReErased`. We may be able to short-circuit registering region
367436 // obligations if we encounter a `ReErased` on one side, for example.
368- ty:: ReStatic | ty :: ReErased | ty:: ReError ( _) => match self . canonicalize_mode {
369- CanonicalizeMode :: Input => CanonicalVarKind :: Region ( ty:: UniverseIndex :: ROOT ) ,
437+ ty:: ReErased | ty:: ReError ( _) => match self . canonicalize_mode {
438+ CanonicalizeMode :: Input { .. } => CanonicalVarKind :: Region ( ty:: UniverseIndex :: ROOT ) ,
370439 CanonicalizeMode :: Response { .. } => return r,
371440 } ,
372441
373442 ty:: ReEarlyParam ( _) | ty:: ReLateParam ( _) => match self . canonicalize_mode {
374- CanonicalizeMode :: Input => CanonicalVarKind :: Region ( ty:: UniverseIndex :: ROOT ) ,
443+ CanonicalizeMode :: Input { .. } => CanonicalVarKind :: Region ( ty:: UniverseIndex :: ROOT ) ,
375444 CanonicalizeMode :: Response { .. } => {
376445 panic ! ( "unexpected region in response: {r:?}" )
377446 }
378447 } ,
379448
380449 ty:: RePlaceholder ( placeholder) => match self . canonicalize_mode {
381450 // We canonicalize placeholder regions as existentials in query inputs.
382- CanonicalizeMode :: Input => CanonicalVarKind :: Region ( ty:: UniverseIndex :: ROOT ) ,
451+ CanonicalizeMode :: Input { .. } => CanonicalVarKind :: Region ( ty:: UniverseIndex :: ROOT ) ,
383452 CanonicalizeMode :: Response { max_input_universe } => {
384453 // If we have a placeholder region inside of a query, it must be from
385454 // a new universe.
@@ -397,7 +466,9 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
397466 "region vid should have been resolved fully before canonicalization"
398467 ) ;
399468 match self . canonicalize_mode {
400- CanonicalizeMode :: Input => CanonicalVarKind :: Region ( ty:: UniverseIndex :: ROOT ) ,
469+ CanonicalizeMode :: Input { keep_static : _ } => {
470+ CanonicalVarKind :: Region ( ty:: UniverseIndex :: ROOT )
471+ }
401472 CanonicalizeMode :: Response { .. } => {
402473 CanonicalVarKind :: Region ( self . delegate . universe_of_lt ( vid) . unwrap ( ) )
403474 }
@@ -434,15 +505,15 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
434505 ty:: InferConst :: Fresh ( _) => todo ! ( ) ,
435506 } ,
436507 ty:: ConstKind :: Placeholder ( placeholder) => match self . canonicalize_mode {
437- CanonicalizeMode :: Input => CanonicalVarKind :: PlaceholderConst (
508+ CanonicalizeMode :: Input { .. } => CanonicalVarKind :: PlaceholderConst (
438509 PlaceholderLike :: new ( placeholder. universe ( ) , self . variables . len ( ) . into ( ) ) ,
439510 ) ,
440511 CanonicalizeMode :: Response { .. } => {
441512 CanonicalVarKind :: PlaceholderConst ( placeholder)
442513 }
443514 } ,
444515 ty:: ConstKind :: Param ( _) => match self . canonicalize_mode {
445- CanonicalizeMode :: Input => CanonicalVarKind :: PlaceholderConst (
516+ CanonicalizeMode :: Input { .. } => CanonicalVarKind :: PlaceholderConst (
446517 PlaceholderLike :: new ( ty:: UniverseIndex :: ROOT , self . variables . len ( ) . into ( ) ) ,
447518 ) ,
448519 CanonicalizeMode :: Response { .. } => panic ! ( "param ty in response: {c:?}" ) ,
0 commit comments