@@ -35,13 +35,13 @@ impl<'tcx> InferCtxt<'tcx> {
35
35
/// [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html#canonicalizing-the-query
36
36
pub fn canonicalize_query < V > (
37
37
& self ,
38
- value : V ,
38
+ value : ty :: ParamEnvAnd < ' tcx , V > ,
39
39
query_state : & mut OriginalQueryValues < ' tcx > ,
40
- ) -> Canonical < ' tcx , V >
40
+ ) -> Canonical < ' tcx , ty :: ParamEnvAnd < ' tcx , V > >
41
41
where
42
42
V : TypeFoldable < TyCtxt < ' tcx > > ,
43
43
{
44
- Canonicalizer :: canonicalize ( value, self , self . tcx , & CanonicalizeAllFreeRegions , query_state )
44
+ self . canonicalize_query_with_mode ( value, query_state , & CanonicalizeAllFreeRegions )
45
45
}
46
46
47
47
/// Like [Self::canonicalize_query], but preserves distinct universes. For
@@ -126,19 +126,52 @@ impl<'tcx> InferCtxt<'tcx> {
126
126
/// handling of `'static` regions (e.g. trait evaluation).
127
127
pub fn canonicalize_query_keep_static < V > (
128
128
& self ,
129
- value : V ,
129
+ value : ty :: ParamEnvAnd < ' tcx , V > ,
130
130
query_state : & mut OriginalQueryValues < ' tcx > ,
131
- ) -> Canonical < ' tcx , V >
131
+ ) -> Canonical < ' tcx , ty :: ParamEnvAnd < ' tcx , V > >
132
132
where
133
133
V : TypeFoldable < TyCtxt < ' tcx > > ,
134
134
{
135
- Canonicalizer :: canonicalize (
135
+ self . canonicalize_query_with_mode (
136
+ value,
137
+ query_state,
138
+ & CanonicalizeFreeRegionsOtherThanStatic ,
139
+ )
140
+ }
141
+
142
+ fn canonicalize_query_with_mode < V > (
143
+ & self ,
144
+ value : ty:: ParamEnvAnd < ' tcx , V > ,
145
+ query_state : & mut OriginalQueryValues < ' tcx > ,
146
+ canonicalize_region_mode : & dyn CanonicalizeMode ,
147
+ ) -> Canonical < ' tcx , ty:: ParamEnvAnd < ' tcx , V > >
148
+ where
149
+ V : TypeFoldable < TyCtxt < ' tcx > > ,
150
+ {
151
+ let ( param_env, value) = value. into_parts ( ) ;
152
+ let base = self . tcx . canonical_param_env_cache . get_or_insert (
153
+ param_env,
154
+ query_state,
155
+ |query_state| {
156
+ Canonicalizer :: canonicalize (
157
+ param_env,
158
+ self ,
159
+ self . tcx ,
160
+ & CanonicalizeFreeRegionsOtherThanStatic ,
161
+ query_state,
162
+ )
163
+ } ,
164
+ ) ;
165
+
166
+ Canonicalizer :: canonicalize_with_base (
167
+ base,
136
168
value,
137
169
self ,
138
170
self . tcx ,
139
- & CanonicalizeFreeRegionsOtherThanStatic ,
171
+ canonicalize_region_mode ,
140
172
query_state,
141
173
)
174
+ . unchecked_map ( |( param_env, value) | param_env. and ( value) )
142
175
}
143
176
}
144
177
@@ -567,6 +600,33 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
567
600
canonicalize_region_mode : & dyn CanonicalizeMode ,
568
601
query_state : & mut OriginalQueryValues < ' tcx > ,
569
602
) -> Canonical < ' tcx , V >
603
+ where
604
+ V : TypeFoldable < TyCtxt < ' tcx > > ,
605
+ {
606
+ let base = Canonical {
607
+ max_universe : ty:: UniverseIndex :: ROOT ,
608
+ variables : List :: empty ( ) ,
609
+ value : ( ) ,
610
+ } ;
611
+ Canonicalizer :: canonicalize_with_base (
612
+ base,
613
+ value,
614
+ infcx,
615
+ tcx,
616
+ canonicalize_region_mode,
617
+ query_state,
618
+ )
619
+ . unchecked_map ( |( ( ) , val) | val)
620
+ }
621
+
622
+ fn canonicalize_with_base < U , V > (
623
+ base : Canonical < ' tcx , U > ,
624
+ value : V ,
625
+ infcx : & InferCtxt < ' tcx > ,
626
+ tcx : TyCtxt < ' tcx > ,
627
+ canonicalize_region_mode : & dyn CanonicalizeMode ,
628
+ query_state : & mut OriginalQueryValues < ' tcx > ,
629
+ ) -> Canonical < ' tcx , ( U , V ) >
570
630
where
571
631
V : TypeFoldable < TyCtxt < ' tcx > > ,
572
632
{
@@ -578,24 +638,28 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
578
638
579
639
// Fast path: nothing that needs to be canonicalized.
580
640
if !value. has_type_flags ( needs_canonical_flags) {
581
- let canon_value = Canonical {
582
- max_universe : ty:: UniverseIndex :: ROOT ,
583
- variables : List :: empty ( ) ,
584
- value,
585
- } ;
586
- return canon_value;
641
+ return base. unchecked_map ( |b| ( b, value) ) ;
587
642
}
588
643
589
644
let mut canonicalizer = Canonicalizer {
590
645
infcx,
591
646
tcx,
592
647
canonicalize_mode : canonicalize_region_mode,
593
648
needs_canonical_flags,
594
- variables : SmallVec :: new ( ) ,
649
+ variables : SmallVec :: from_slice ( base . variables ) ,
595
650
query_state,
596
651
indices : FxHashMap :: default ( ) ,
597
652
binder_index : ty:: INNERMOST ,
598
653
} ;
654
+ if canonicalizer. query_state . var_values . spilled ( ) {
655
+ canonicalizer. indices = canonicalizer
656
+ . query_state
657
+ . var_values
658
+ . iter ( )
659
+ . enumerate ( )
660
+ . map ( |( i, & kind) | ( kind, BoundVar :: new ( i) ) )
661
+ . collect ( ) ;
662
+ }
599
663
let out_value = value. fold_with ( & mut canonicalizer) ;
600
664
601
665
// Once we have canonicalized `out_value`, it should not
@@ -612,7 +676,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
612
676
. max ( )
613
677
. unwrap_or ( ty:: UniverseIndex :: ROOT ) ;
614
678
615
- Canonical { max_universe, variables : canonical_variables, value : out_value }
679
+ Canonical { max_universe, variables : canonical_variables, value : ( base . value , out_value) }
616
680
}
617
681
618
682
/// Creates a canonical variable replacing `kind` from the input,
0 commit comments