@@ -13,6 +13,7 @@ use rustc_middle::ty::flags::FlagComputation;
13
13
use rustc_middle:: ty:: fold:: { TypeFoldable , TypeFolder , TypeSuperFoldable } ;
14
14
use rustc_middle:: ty:: GenericArg ;
15
15
use rustc_middle:: ty:: { self , BoundVar , InferConst , List , Ty , TyCtxt , TypeFlags , TypeVisitableExt } ;
16
+ use std:: borrow:: Cow ;
16
17
use std:: sync:: atomic:: Ordering ;
17
18
18
19
use rustc_data_structures:: fx:: FxHashMap ;
@@ -148,6 +149,27 @@ impl<'tcx> InferCtxt<'tcx> {
148
149
query_state,
149
150
)
150
151
}
152
+
153
+ pub fn canonicalize_query_keep_static_continue < U , V > (
154
+ & self ,
155
+ base : Canonical < ' tcx , U > ,
156
+ value : V ,
157
+ query_state : & mut Cow < ' _ , OriginalQueryValues < ' tcx > > ,
158
+ ) -> Canonical < ' tcx , ( U , V ) >
159
+ where
160
+ V : TypeFoldable < TyCtxt < ' tcx > > ,
161
+ {
162
+ self . tcx . sess . perf_stats . queries_canonicalized . fetch_add ( 1 , Ordering :: Relaxed ) ;
163
+
164
+ Canonicalizer :: canonicalize_continue (
165
+ base,
166
+ value,
167
+ self ,
168
+ self . tcx ,
169
+ & CanonicalizeFreeRegionsOtherThanStatic ,
170
+ query_state,
171
+ )
172
+ }
151
173
}
152
174
153
175
/// Controls how we canonicalize "free regions" that are not inference
@@ -616,6 +638,66 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
616
638
Canonical { max_universe, variables : canonical_variables, value : out_value }
617
639
}
618
640
641
+ fn canonicalize_continue < U , V > (
642
+ base : Canonical < ' tcx , U > ,
643
+ value : V ,
644
+ infcx : & InferCtxt < ' tcx > ,
645
+ tcx : TyCtxt < ' tcx > ,
646
+ canonicalize_region_mode : & dyn CanonicalizeMode ,
647
+ query_state : & mut Cow < ' _ , OriginalQueryValues < ' tcx > > ,
648
+ ) -> Canonical < ' tcx , ( U , V ) >
649
+ where
650
+ V : TypeFoldable < TyCtxt < ' tcx > > ,
651
+ {
652
+ let needs_canonical_flags = if canonicalize_region_mode. any ( ) {
653
+ TypeFlags :: HAS_INFER | TypeFlags :: HAS_PLACEHOLDER | TypeFlags :: HAS_FREE_REGIONS
654
+ } else {
655
+ TypeFlags :: HAS_INFER | TypeFlags :: HAS_PLACEHOLDER
656
+ } ;
657
+
658
+ // Fast path: nothing that needs to be canonicalized.
659
+ if !value. has_type_flags ( needs_canonical_flags) {
660
+ return base. unchecked_map ( |b| ( b, value) ) ;
661
+ }
662
+
663
+ let mut canonicalizer = Canonicalizer {
664
+ infcx,
665
+ tcx,
666
+ canonicalize_mode : canonicalize_region_mode,
667
+ needs_canonical_flags,
668
+ variables : SmallVec :: from_slice ( base. variables ) ,
669
+ query_state : query_state. to_mut ( ) ,
670
+ indices : FxHashMap :: default ( ) ,
671
+ binder_index : ty:: INNERMOST ,
672
+ } ;
673
+ if canonicalizer. query_state . var_values . spilled ( ) {
674
+ canonicalizer. indices = canonicalizer
675
+ . query_state
676
+ . var_values
677
+ . iter ( )
678
+ . enumerate ( )
679
+ . map ( |( i, & kind) | ( kind, BoundVar :: new ( i) ) )
680
+ . collect ( ) ;
681
+ }
682
+ let out_value = value. fold_with ( & mut canonicalizer) ;
683
+
684
+ // Once we have canonicalized `out_value`, it should not
685
+ // contain anything that ties it to this inference context
686
+ // anymore.
687
+ debug_assert ! ( !out_value. has_infer( ) && !out_value. has_placeholders( ) ) ;
688
+
689
+ let canonical_variables =
690
+ tcx. mk_canonical_var_infos ( & canonicalizer. universe_canonicalized_variables ( ) ) ;
691
+
692
+ let max_universe = canonical_variables
693
+ . iter ( )
694
+ . map ( |cvar| cvar. universe ( ) )
695
+ . max ( )
696
+ . unwrap_or ( ty:: UniverseIndex :: ROOT ) ;
697
+
698
+ Canonical { max_universe, variables : canonical_variables, value : ( base. value , out_value) }
699
+ }
700
+
619
701
/// Creates a canonical variable replacing `kind` from the input,
620
702
/// or returns an existing variable if `kind` has already been
621
703
/// seen. `kind` is expected to be an unbound variable (or
0 commit comments