@@ -35,13 +35,13 @@ impl<'tcx> InferCtxt<'tcx> {
3535 /// [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html#canonicalizing-the-query
3636 pub fn canonicalize_query < V > (
3737 & self ,
38- value : V ,
38+ value : ty :: ParamEnvAnd < ' tcx , V > ,
3939 query_state : & mut OriginalQueryValues < ' tcx > ,
40- ) -> Canonical < ' tcx , V >
40+ ) -> Canonical < ' tcx , ty :: ParamEnvAnd < ' tcx , V > >
4141 where
4242 V : TypeFoldable < TyCtxt < ' tcx > > ,
4343 {
44- Canonicalizer :: canonicalize ( value, self , self . tcx , & CanonicalizeAllFreeRegions , query_state )
44+ self . canonicalize_query_with_mode ( value, query_state , & CanonicalizeAllFreeRegions )
4545 }
4646
4747 /// Like [Self::canonicalize_query], but preserves distinct universes. For
@@ -126,19 +126,52 @@ impl<'tcx> InferCtxt<'tcx> {
126126 /// handling of `'static` regions (e.g. trait evaluation).
127127 pub fn canonicalize_query_keep_static < V > (
128128 & self ,
129- value : V ,
129+ value : ty :: ParamEnvAnd < ' tcx , V > ,
130130 query_state : & mut OriginalQueryValues < ' tcx > ,
131- ) -> Canonical < ' tcx , V >
131+ ) -> Canonical < ' tcx , ty :: ParamEnvAnd < ' tcx , V > >
132132 where
133133 V : TypeFoldable < TyCtxt < ' tcx > > ,
134134 {
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,
136168 value,
137169 self ,
138170 self . tcx ,
139- & CanonicalizeFreeRegionsOtherThanStatic ,
171+ canonicalize_region_mode ,
140172 query_state,
141173 )
174+ . unchecked_map ( |( param_env, value) | param_env. and ( value) )
142175 }
143176}
144177
@@ -567,6 +600,33 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
567600 canonicalize_region_mode : & dyn CanonicalizeMode ,
568601 query_state : & mut OriginalQueryValues < ' tcx > ,
569602 ) -> 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 ) >
570630 where
571631 V : TypeFoldable < TyCtxt < ' tcx > > ,
572632 {
@@ -578,24 +638,28 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
578638
579639 // Fast path: nothing that needs to be canonicalized.
580640 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) ) ;
587642 }
588643
589644 let mut canonicalizer = Canonicalizer {
590645 infcx,
591646 tcx,
592647 canonicalize_mode : canonicalize_region_mode,
593648 needs_canonical_flags,
594- variables : SmallVec :: new ( ) ,
649+ variables : SmallVec :: from_slice ( base . variables ) ,
595650 query_state,
596651 indices : FxHashMap :: default ( ) ,
597652 binder_index : ty:: INNERMOST ,
598653 } ;
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+ }
599663 let out_value = value. fold_with ( & mut canonicalizer) ;
600664
601665 // Once we have canonicalized `out_value`, it should not
@@ -612,7 +676,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
612676 . max ( )
613677 . unwrap_or ( ty:: UniverseIndex :: ROOT ) ;
614678
615- Canonical { max_universe, variables : canonical_variables, value : out_value }
679+ Canonical { max_universe, variables : canonical_variables, value : ( base . value , out_value) }
616680 }
617681
618682 /// Creates a canonical variable replacing `kind` from the input,
0 commit comments