@@ -37,10 +37,11 @@ use snapshot::undo_log::InferCtxtUndoLogs;
37
37
use tracing:: { debug, instrument} ;
38
38
use type_variable:: TypeVariableOrigin ;
39
39
40
- use crate :: infer:: region_constraints :: UndoLog ;
40
+ use crate :: infer:: snapshot :: undo_log :: UndoLog ;
41
41
use crate :: infer:: unify_key:: { ConstVariableOrigin , ConstVariableValue , ConstVidKey } ;
42
42
use crate :: traits:: {
43
- self , ObligationCause , ObligationInspector , PredicateObligations , TraitEngine ,
43
+ self , ObligationCause , ObligationInspector , PredicateObligation , PredicateObligations ,
44
+ TraitEngine ,
44
45
} ;
45
46
46
47
pub mod at;
@@ -156,6 +157,12 @@ pub struct InferCtxtInner<'tcx> {
156
157
/// which may cause types to no longer be considered well-formed.
157
158
region_assumptions : Vec < ty:: ArgOutlivesPredicate < ' tcx > > ,
158
159
160
+ /// `-Znext-solver`: Successfully proven goals during HIR typeck which
161
+ /// reference inference variables and get reproven after writeback.
162
+ ///
163
+ /// See the documentation of `InferCtxt::in_hir_typeck` for more details.
164
+ hir_typeck_potentially_region_dependent_goals : Vec < PredicateObligation < ' tcx > > ,
165
+
159
166
/// Caches for opaque type inference.
160
167
opaque_type_storage : OpaqueTypeStorage < ' tcx > ,
161
168
}
@@ -173,6 +180,7 @@ impl<'tcx> InferCtxtInner<'tcx> {
173
180
region_constraint_storage : Some ( Default :: default ( ) ) ,
174
181
region_obligations : Default :: default ( ) ,
175
182
region_assumptions : Default :: default ( ) ,
183
+ hir_typeck_potentially_region_dependent_goals : Default :: default ( ) ,
176
184
opaque_type_storage : Default :: default ( ) ,
177
185
}
178
186
}
@@ -244,9 +252,29 @@ pub struct InferCtxt<'tcx> {
244
252
typing_mode : TypingMode < ' tcx > ,
245
253
246
254
/// Whether this inference context should care about region obligations in
247
- /// the root universe. Most notably, this is used during hir typeck as region
255
+ /// the root universe. Most notably, this is used during HIR typeck as region
248
256
/// solving is left to borrowck instead.
249
257
pub considering_regions : bool ,
258
+ /// `-Znext-solver`: Whether this inference context is used by HIR typeck. If so, we
259
+ /// need to make sure we don't rely on region identity in the trait solver or when
260
+ /// relating types. This is necessary as borrowck starts by replacing each occurrence of a
261
+ /// free region with a unique inference variable. If HIR typeck ends up depending on two
262
+ /// regions being equal we'd get unexpected mismatches between HIR typeck and MIR typeck,
263
+ /// resulting in an ICE.
264
+ ///
265
+ /// The trait solver sometimes depends on regions being identical. As a concrete example
266
+ /// the trait solver ignores other candidates if one candidate exists without any constraints.
267
+ /// The goal `&'a u32: Equals<&'a u32>` has no constraints right now. If we replace each
268
+ /// occurrence of `'a` with a unique region the goal now equates these regions. See
269
+ /// the tests in trait-system-refactor-initiative#27 for concrete examples.
270
+ ///
271
+ /// We handle this by *uniquifying* region when canonicalizing root goals during HIR typeck.
272
+ /// This is still insufficient as inference variables may *hide* region variables, so e.g.
273
+ /// `dyn TwoSuper<?x, ?x>: Super<?x>` may hold but MIR typeck could end up having to prove
274
+ /// `dyn TwoSuper<&'0 (), &'1 ()>: Super<&'2 ()>` which is now ambiguous. Because of this we
275
+ /// stash all successfully proven goals which reference inference variables and then reprove
276
+ /// them after writeback.
277
+ pub in_hir_typeck : bool ,
250
278
251
279
/// If set, this flag causes us to skip the 'leak check' during
252
280
/// higher-ranked subtyping operations. This flag is a temporary one used
@@ -506,6 +534,7 @@ pub struct TypeOutlivesConstraint<'tcx> {
506
534
pub struct InferCtxtBuilder < ' tcx > {
507
535
tcx : TyCtxt < ' tcx > ,
508
536
considering_regions : bool ,
537
+ in_hir_typeck : bool ,
509
538
skip_leak_check : bool ,
510
539
/// Whether we should use the new trait solver in the local inference context,
511
540
/// which affects things like which solver is used in `predicate_may_hold`.
@@ -518,6 +547,7 @@ impl<'tcx> TyCtxt<'tcx> {
518
547
InferCtxtBuilder {
519
548
tcx : self ,
520
549
considering_regions : true ,
550
+ in_hir_typeck : false ,
521
551
skip_leak_check : false ,
522
552
next_trait_solver : self . next_trait_solver_globally ( ) ,
523
553
}
@@ -535,6 +565,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
535
565
self
536
566
}
537
567
568
+ pub fn in_hir_typeck ( mut self ) -> Self {
569
+ self . in_hir_typeck = true ;
570
+ self
571
+ }
572
+
538
573
pub fn skip_leak_check ( mut self , skip_leak_check : bool ) -> Self {
539
574
self . skip_leak_check = skip_leak_check;
540
575
self
@@ -568,12 +603,18 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
568
603
}
569
604
570
605
pub fn build ( & mut self , typing_mode : TypingMode < ' tcx > ) -> InferCtxt < ' tcx > {
571
- let InferCtxtBuilder { tcx, considering_regions, skip_leak_check, next_trait_solver } =
572
- * self ;
606
+ let InferCtxtBuilder {
607
+ tcx,
608
+ considering_regions,
609
+ in_hir_typeck,
610
+ skip_leak_check,
611
+ next_trait_solver,
612
+ } = * self ;
573
613
InferCtxt {
574
614
tcx,
575
615
typing_mode,
576
616
considering_regions,
617
+ in_hir_typeck,
577
618
skip_leak_check,
578
619
inner : RefCell :: new ( InferCtxtInner :: new ( ) ) ,
579
620
lexical_region_resolutions : RefCell :: new ( None ) ,
@@ -978,6 +1019,22 @@ impl<'tcx> InferCtxt<'tcx> {
978
1019
}
979
1020
}
980
1021
1022
+ pub fn push_hir_typeck_potentially_region_dependent_goal (
1023
+ & self ,
1024
+ goal : PredicateObligation < ' tcx > ,
1025
+ ) {
1026
+ let mut inner = self . inner . borrow_mut ( ) ;
1027
+ inner. undo_log . push ( UndoLog :: PushHirTypeckPotentiallyRegionDependentGoal ) ;
1028
+ inner. hir_typeck_potentially_region_dependent_goals . push ( goal) ;
1029
+ }
1030
+
1031
+ pub fn take_hir_typeck_potentially_region_dependent_goals (
1032
+ & self ,
1033
+ ) -> Vec < PredicateObligation < ' tcx > > {
1034
+ assert ! ( !self . in_snapshot( ) , "cannot take goals in a snapshot" ) ;
1035
+ std:: mem:: take ( & mut self . inner . borrow_mut ( ) . hir_typeck_potentially_region_dependent_goals )
1036
+ }
1037
+
981
1038
pub fn ty_to_string ( & self , t : Ty < ' tcx > ) -> String {
982
1039
self . resolve_vars_if_possible ( t) . to_string ( )
983
1040
}
0 commit comments