@@ -16,7 +16,7 @@ use rustc_data_structures::undo_log::{Rollback, UndoLogs};
16
16
/// Represents a single undo-able action that affects a type inference variable.
17
17
pub ( crate ) enum UndoLog < ' tcx > {
18
18
EqRelation ( sv:: UndoLog < ut:: Delegate < TyVidEqKey < ' tcx > > > ) ,
19
- SubRelation ( sv:: UndoLog < ut:: Delegate < ty :: TyVid > > ) ,
19
+ SubRelation ( sv:: UndoLog < ut:: Delegate < TyVidSubKey > > ) ,
20
20
Values ( sv:: UndoLog < Delegate > ) ,
21
21
}
22
22
@@ -28,8 +28,8 @@ impl<'tcx> From<sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>> for UndoLog<'tcx> {
28
28
}
29
29
30
30
/// 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 {
33
33
UndoLog :: SubRelation ( l)
34
34
}
35
35
}
@@ -83,7 +83,7 @@ pub struct TypeVariableStorage<'tcx> {
83
83
/// This is reasonable because, in Rust, subtypes have the same
84
84
/// "skeleton" and hence there is no possible type such that
85
85
/// (e.g.) `Box<?3> <: ?3` for any `?3`.
86
- sub_relations : ut:: UnificationTableStorage < ty :: TyVid > ,
86
+ sub_relations : ut:: UnificationTableStorage < TyVidSubKey > ,
87
87
}
88
88
89
89
pub struct TypeVariableTable < ' a , ' tcx > {
@@ -169,6 +169,16 @@ impl<'tcx> TypeVariableStorage<'tcx> {
169
169
}
170
170
171
171
impl < ' 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
+
172
182
/// Returns the diverges flag given when `vid` was created.
173
183
///
174
184
/// Note that this function does not return care whether
@@ -243,8 +253,9 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
243
253
) -> ty:: TyVid {
244
254
let eq_key = self . eq_relations ( ) . new_key ( TypeVariableValue :: Unknown { universe } ) ;
245
255
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) ;
248
259
249
260
let index = self . values ( ) . push ( TypeVariableData { origin, diverging } ) ;
250
261
assert_eq ! ( eq_key. vid. index, index as u32 ) ;
@@ -279,7 +290,7 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
279
290
///
280
291
/// exists X. (a <: X || X <: a) && (b <: X || X <: b)
281
292
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
283
294
}
284
295
285
296
/// Returns `true` if `a` and `b` have same "sub-root" (i.e., exists some
@@ -326,7 +337,7 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
326
337
}
327
338
328
339
#[ inline]
329
- fn sub_relations ( & mut self ) -> super :: UnificationTable < ' _ , ' tcx , ty :: TyVid > {
340
+ fn sub_relations ( & mut self ) -> super :: UnificationTable < ' _ , ' tcx , TyVidSubKey > {
330
341
self . storage . sub_relations . with_log ( self . undo_log )
331
342
}
332
343
@@ -443,3 +454,84 @@ impl<'tcx> ut::UnifyValue for TypeVariableValue<'tcx> {
443
454
}
444
455
}
445
456
}
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