@@ -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. 
157158region_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. 
160167opaque_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> {
244252typing_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. 
249257pub  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