@@ -3,6 +3,7 @@ use std::cmp::Ordering;
3
3
use rustc_type_ir:: data_structures:: HashMap ;
4
4
use rustc_type_ir:: fold:: { TypeFoldable , TypeFolder , TypeSuperFoldable } ;
5
5
use rustc_type_ir:: inherent:: * ;
6
+ use rustc_type_ir:: solve:: { Goal , QueryInput } ;
6
7
use rustc_type_ir:: visit:: TypeVisitableExt ;
7
8
use rustc_type_ir:: {
8
9
self as ty, Canonical , CanonicalTyVarKind , CanonicalVarInfo , CanonicalVarKind , InferCtxtLike ,
@@ -17,8 +18,11 @@ use crate::delegate::SolverDelegate;
17
18
/// while canonicalizing the response happens in the context of the
18
19
/// query.
19
20
#[ 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 } ,
22
26
/// FIXME: We currently return region constraints referring to
23
27
/// placeholders and inference variables from a binder instantiated
24
28
/// inside of the query.
@@ -59,15 +63,15 @@ pub struct Canonicalizer<'a, D: SolverDelegate<Interner = I>, I: Interner> {
59
63
}
60
64
61
65
impl < ' 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 > > (
63
67
delegate : & ' a D ,
64
- canonicalize_mode : CanonicalizeMode ,
68
+ max_input_universe : ty :: UniverseIndex ,
65
69
variables : & ' a mut Vec < I :: GenericArg > ,
66
70
value : T ,
67
71
) -> ty:: Canonical < I , T > {
68
72
let mut canonicalizer = Canonicalizer {
69
73
delegate,
70
- canonicalize_mode,
74
+ canonicalize_mode : CanonicalizeMode :: Response { max_input_universe } ,
71
75
72
76
variables,
73
77
variable_lookup_table : Default :: default ( ) ,
@@ -80,9 +84,67 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
80
84
let value = value. fold_with ( & mut canonicalizer) ;
81
85
assert ! ( !value. has_infer( ) , "unexpected infer in {value:?}" ) ;
82
86
assert ! ( !value. has_placeholders( ) , "unexpected placeholders in {value:?}" ) ;
83
-
84
87
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 ,
85
130
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 ( ) ;
86
148
Canonical { max_universe, variables, value }
87
149
}
88
150
@@ -126,7 +188,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
126
188
// all information which should not matter for the solver.
127
189
//
128
190
// For this we compress universes as much as possible.
129
- CanonicalizeMode :: Input => { }
191
+ CanonicalizeMode :: Input { .. } => { }
130
192
// When canonicalizing a response we map a universes already entered
131
193
// by the caller to the root universe and only return useful universe
132
194
// information for placeholders and inference variables created inside
@@ -290,17 +352,15 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
290
352
}
291
353
} ,
292
354
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
+ ) ,
297
358
CanonicalizeMode :: Response { .. } => CanonicalVarKind :: PlaceholderTy ( placeholder) ,
298
359
} ,
299
360
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
+ ) ,
304
364
CanonicalizeMode :: Response { .. } => panic ! ( "param ty in response: {t:?}" ) ,
305
365
} ,
306
366
ty:: Bool
@@ -357,29 +417,38 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
357
417
let kind = match r. kind ( ) {
358
418
ty:: ReBound ( ..) => return r,
359
419
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
362
431
// type of an opaque for regions that are ignored for the purposes of
363
432
// captures.
364
433
//
365
434
// FIXME: We should investigate the perf implications of not uniquifying
366
435
// `ReErased`. We may be able to short-circuit registering region
367
436
// 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 ) ,
370
439
CanonicalizeMode :: Response { .. } => return r,
371
440
} ,
372
441
373
442
ty:: ReEarlyParam ( _) | ty:: ReLateParam ( _) => match self . canonicalize_mode {
374
- CanonicalizeMode :: Input => CanonicalVarKind :: Region ( ty:: UniverseIndex :: ROOT ) ,
443
+ CanonicalizeMode :: Input { .. } => CanonicalVarKind :: Region ( ty:: UniverseIndex :: ROOT ) ,
375
444
CanonicalizeMode :: Response { .. } => {
376
445
panic ! ( "unexpected region in response: {r:?}" )
377
446
}
378
447
} ,
379
448
380
449
ty:: RePlaceholder ( placeholder) => match self . canonicalize_mode {
381
450
// 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 ) ,
383
452
CanonicalizeMode :: Response { max_input_universe } => {
384
453
// If we have a placeholder region inside of a query, it must be from
385
454
// a new universe.
@@ -397,7 +466,9 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
397
466
"region vid should have been resolved fully before canonicalization"
398
467
) ;
399
468
match self . canonicalize_mode {
400
- CanonicalizeMode :: Input => CanonicalVarKind :: Region ( ty:: UniverseIndex :: ROOT ) ,
469
+ CanonicalizeMode :: Input { keep_static : _ } => {
470
+ CanonicalVarKind :: Region ( ty:: UniverseIndex :: ROOT )
471
+ }
401
472
CanonicalizeMode :: Response { .. } => {
402
473
CanonicalVarKind :: Region ( self . delegate . universe_of_lt ( vid) . unwrap ( ) )
403
474
}
@@ -434,15 +505,15 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
434
505
ty:: InferConst :: Fresh ( _) => todo ! ( ) ,
435
506
} ,
436
507
ty:: ConstKind :: Placeholder ( placeholder) => match self . canonicalize_mode {
437
- CanonicalizeMode :: Input => CanonicalVarKind :: PlaceholderConst (
508
+ CanonicalizeMode :: Input { .. } => CanonicalVarKind :: PlaceholderConst (
438
509
PlaceholderLike :: new ( placeholder. universe ( ) , self . variables . len ( ) . into ( ) ) ,
439
510
) ,
440
511
CanonicalizeMode :: Response { .. } => {
441
512
CanonicalVarKind :: PlaceholderConst ( placeholder)
442
513
}
443
514
} ,
444
515
ty:: ConstKind :: Param ( _) => match self . canonicalize_mode {
445
- CanonicalizeMode :: Input => CanonicalVarKind :: PlaceholderConst (
516
+ CanonicalizeMode :: Input { .. } => CanonicalVarKind :: PlaceholderConst (
446
517
PlaceholderLike :: new ( ty:: UniverseIndex :: ROOT , self . variables . len ( ) . into ( ) ) ,
447
518
) ,
448
519
CanonicalizeMode :: Response { .. } => panic ! ( "param ty in response: {c:?}" ) ,
0 commit comments