@@ -16,7 +16,7 @@ use rustc_data_structures::undo_log::{Rollback, UndoLogs};
1616/// Represents a single undo-able action that affects a type inference variable.
1717pub ( crate ) enum UndoLog < ' tcx > {
1818 EqRelation ( sv:: UndoLog < ut:: Delegate < TyVidEqKey < ' tcx > > > ) ,
19- SubRelation ( sv:: UndoLog < ut:: Delegate < ty :: TyVid > > ) ,
19+ SubRelation ( sv:: UndoLog < ut:: Delegate < TyVidSubKey > > ) ,
2020 Values ( sv:: UndoLog < Delegate > ) ,
2121}
2222
@@ -28,8 +28,8 @@ impl<'tcx> From<sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>> for UndoLog<'tcx> {
2828}
2929
3030/// Convert from a specific kind of undo to the more general UndoLog
31- impl < ' tcx > From < sv:: UndoLog < ut:: Delegate < ty :: TyVid > > > for UndoLog < ' tcx > {
32- fn from ( l : sv:: UndoLog < ut:: Delegate < ty :: TyVid > > ) -> Self {
31+ impl < ' tcx > From < sv:: UndoLog < ut:: Delegate < TyVidSubKey > > > for UndoLog < ' tcx > {
32+ fn from ( l : sv:: UndoLog < ut:: Delegate < TyVidSubKey > > ) -> Self {
3333 UndoLog :: SubRelation ( l)
3434 }
3535}
@@ -83,7 +83,7 @@ pub struct TypeVariableStorage<'tcx> {
8383 /// This is reasonable because, in Rust, subtypes have the same
8484 /// "skeleton" and hence there is no possible type such that
8585 /// (e.g.) `Box<?3> <: ?3` for any `?3`.
86- sub_relations : ut:: UnificationTableStorage < ty :: TyVid > ,
86+ sub_relations : ut:: UnificationTableStorage < TyVidSubKey > ,
8787}
8888
8989pub struct TypeVariableTable < ' a , ' tcx > {
@@ -169,6 +169,16 @@ impl<'tcx> TypeVariableStorage<'tcx> {
169169}
170170
171171impl < ' tcx > TypeVariableTable < ' _ , ' tcx > {
172+ /// Returns `false` if all non-auxiliary type variables unified with
173+ /// `vid` is diverging. Returns `true` otherwise.
174+ ///
175+ /// Precondition: `vid` should be unknown.
176+ pub fn var_diverges_with_unification ( & mut self , vid : ty:: TyVid ) -> bool {
177+ debug_assert ! ( self . probe( vid) . is_unknown( ) ) ;
178+ let kind = self . sub_relations ( ) . inlined_probe_value ( vid) ;
179+ matches ! ( kind, TyVarUnifiedDiverging :: Yes )
180+ }
181+
172182 /// Returns the diverges flag given when `vid` was created.
173183 ///
174184 /// Note that this function does not return care whether
@@ -243,8 +253,9 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
243253 ) -> ty:: TyVid {
244254 let eq_key = self . eq_relations ( ) . new_key ( TypeVariableValue :: Unknown { universe } ) ;
245255
246- let sub_key = self . sub_relations ( ) . new_key ( ( ) ) ;
247- assert_eq ! ( eq_key. vid, sub_key) ;
256+ let diverging_kind = TyVarUnifiedDiverging :: from ( diverging, origin. kind ) ;
257+ let sub_key = self . sub_relations ( ) . new_key ( diverging_kind) ;
258+ assert_eq ! ( eq_key. vid, sub_key. vid) ;
248259
249260 let index = self . values ( ) . push ( TypeVariableData { origin, diverging } ) ;
250261 assert_eq ! ( eq_key. vid. index, index as u32 ) ;
@@ -279,7 +290,7 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
279290 ///
280291 /// exists X. (a <: X || X <: a) && (b <: X || X <: b)
281292 pub fn sub_root_var ( & mut self , vid : ty:: TyVid ) -> ty:: TyVid {
282- self . sub_relations ( ) . find ( vid)
293+ self . sub_relations ( ) . find ( vid) . vid
283294 }
284295
285296 /// Returns `true` if `a` and `b` have same "sub-root" (i.e., exists some
@@ -326,7 +337,7 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
326337 }
327338
328339 #[ inline]
329- fn sub_relations ( & mut self ) -> super :: UnificationTable < ' _ , ' tcx , ty :: TyVid > {
340+ fn sub_relations ( & mut self ) -> super :: UnificationTable < ' _ , ' tcx , TyVidSubKey > {
330341 self . storage . sub_relations . with_log ( self . undo_log )
331342 }
332343
@@ -443,3 +454,84 @@ impl<'tcx> ut::UnifyValue for TypeVariableValue<'tcx> {
443454 }
444455 }
445456}
457+
458+ ///////////////////////////////////////////////////////////////////////////
459+
460+ /// These structs (a newtyped TyVid) are used as the unification key
461+ /// for the `sub_relations`; they carry a `TyVarUnifiedDiverging`
462+ /// along with them.
463+ #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
464+ pub ( crate ) struct TyVidSubKey {
465+ vid : ty:: TyVid ,
466+ }
467+
468+ /// This enum denotes whether unified type variables are all diverging
469+ /// variables. Note auxiliary type variables (guessed with the help of
470+ /// `TypeVariableOriginKind`) should be ignored.
471+ #[ derive( Copy , Clone , Debug ) ]
472+ pub enum TyVarUnifiedDiverging {
473+ /// All unified type variables are diverging.
474+ Yes ,
475+ /// Some unified type variable are not diverging.
476+ No ,
477+ /// We don't know the final result at all because we haven't seen
478+ /// any non-auxiliary type variables yet.
479+ Maybe ,
480+ }
481+
482+ impl From < ty:: TyVid > for TyVidSubKey {
483+ fn from ( vid : ty:: TyVid ) -> Self {
484+ TyVidSubKey { vid }
485+ }
486+ }
487+
488+ impl ut:: UnifyKey for TyVidSubKey {
489+ type Value = TyVarUnifiedDiverging ;
490+ fn index ( & self ) -> u32 {
491+ self . vid . index
492+ }
493+ fn from_index ( i : u32 ) -> Self {
494+ TyVidSubKey :: from ( ty:: TyVid { index : i } )
495+ }
496+ fn tag ( ) -> & ' static str {
497+ "TyVidSubKey"
498+ }
499+ }
500+
501+ impl ut:: UnifyValue for TyVarUnifiedDiverging {
502+ type Error = ut:: NoError ;
503+
504+ fn unify_values ( value1 : & Self , value2 : & Self ) -> Result < Self , ut:: NoError > {
505+ match ( * value1, * value2) {
506+ // Auxiliary type variables should be ignored.
507+ ( TyVarUnifiedDiverging :: Maybe , other) => Ok ( other) ,
508+ ( other, TyVarUnifiedDiverging :: Maybe ) => Ok ( other) ,
509+
510+ // We've found some non-diverging type variables.
511+ ( TyVarUnifiedDiverging :: No , _) => Ok ( TyVarUnifiedDiverging :: No ) ,
512+ ( _, TyVarUnifiedDiverging :: No ) => Ok ( TyVarUnifiedDiverging :: No ) ,
513+
514+ // All type variables are diverging yet.
515+ ( TyVarUnifiedDiverging :: Yes , TyVarUnifiedDiverging :: Yes ) => {
516+ Ok ( TyVarUnifiedDiverging :: Yes )
517+ }
518+ }
519+ }
520+ }
521+
522+ impl TyVarUnifiedDiverging {
523+ #[ inline]
524+ fn from ( diverging : bool , origin : TypeVariableOriginKind ) -> Self {
525+ if diverging {
526+ return TyVarUnifiedDiverging :: Yes ;
527+ }
528+
529+ // FIXME: Is it a complete list? Probably not.
530+ match origin {
531+ TypeVariableOriginKind :: MiscVariable | TypeVariableOriginKind :: LatticeVariable => {
532+ TyVarUnifiedDiverging :: Maybe
533+ }
534+ _ => TyVarUnifiedDiverging :: No ,
535+ }
536+ }
537+ }
0 commit comments