@@ -37,10 +37,11 @@ use snapshot::undo_log::InferCtxtUndoLogs;
3737use tracing:: { debug, instrument} ;
3838use type_variable:: TypeVariableOrigin ;
3939
40- use crate :: infer:: region_constraints :: UndoLog ;
40+ use crate :: infer:: snapshot :: undo_log :: UndoLog ;
4141use crate :: infer:: unify_key:: { ConstVariableOrigin , ConstVariableValue , ConstVidKey } ;
4242use crate :: traits:: {
43- self , ObligationCause , ObligationInspector , PredicateObligations , TraitEngine ,
43+ self , ObligationCause , ObligationInspector , PredicateObligation , PredicateObligations ,
44+ TraitEngine ,
4445} ;
4546
4647pub mod at;
@@ -156,6 +157,12 @@ pub struct InferCtxtInner<'tcx> {
156157 /// which may cause types to no longer be considered well-formed.
157158 region_assumptions : Vec < ty:: ArgOutlivesPredicate < ' tcx > > ,
158159
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+
159166 /// Caches for opaque type inference.
160167 opaque_type_storage : OpaqueTypeStorage < ' tcx > ,
161168}
@@ -173,6 +180,7 @@ impl<'tcx> InferCtxtInner<'tcx> {
173180 region_constraint_storage : Some ( Default :: default ( ) ) ,
174181 region_obligations : Default :: default ( ) ,
175182 region_assumptions : Default :: default ( ) ,
183+ hir_typeck_potentially_region_dependent_goals : Default :: default ( ) ,
176184 opaque_type_storage : Default :: default ( ) ,
177185 }
178186 }
@@ -244,9 +252,29 @@ pub struct InferCtxt<'tcx> {
244252 typing_mode : TypingMode < ' tcx > ,
245253
246254 /// 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
248256 /// solving is left to borrowck instead.
249257 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 ,
250278
251279 /// If set, this flag causes us to skip the 'leak check' during
252280 /// higher-ranked subtyping operations. This flag is a temporary one used
@@ -506,6 +534,7 @@ pub struct TypeOutlivesConstraint<'tcx> {
506534pub struct InferCtxtBuilder < ' tcx > {
507535 tcx : TyCtxt < ' tcx > ,
508536 considering_regions : bool ,
537+ in_hir_typeck : bool ,
509538 skip_leak_check : bool ,
510539 /// Whether we should use the new trait solver in the local inference context,
511540 /// which affects things like which solver is used in `predicate_may_hold`.
@@ -518,6 +547,7 @@ impl<'tcx> TyCtxt<'tcx> {
518547 InferCtxtBuilder {
519548 tcx : self ,
520549 considering_regions : true ,
550+ in_hir_typeck : false ,
521551 skip_leak_check : false ,
522552 next_trait_solver : self . next_trait_solver_globally ( ) ,
523553 }
@@ -535,6 +565,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
535565 self
536566 }
537567
568+ pub fn in_hir_typeck ( mut self ) -> Self {
569+ self . in_hir_typeck = true ;
570+ self
571+ }
572+
538573 pub fn skip_leak_check ( mut self , skip_leak_check : bool ) -> Self {
539574 self . skip_leak_check = skip_leak_check;
540575 self
@@ -568,12 +603,18 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
568603 }
569604
570605 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 ;
573613 InferCtxt {
574614 tcx,
575615 typing_mode,
576616 considering_regions,
617+ in_hir_typeck,
577618 skip_leak_check,
578619 inner : RefCell :: new ( InferCtxtInner :: new ( ) ) ,
579620 lexical_region_resolutions : RefCell :: new ( None ) ,
@@ -978,6 +1019,22 @@ impl<'tcx> InferCtxt<'tcx> {
9781019 }
9791020 }
9801021
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+
9811038 pub fn ty_to_string ( & self , t : Ty < ' tcx > ) -> String {
9821039 self . resolve_vars_if_possible ( t) . to_string ( )
9831040 }
0 commit comments