@@ -13,12 +13,48 @@ use tracing::debug;
1313
1414use crate :: infer:: InferCtxtUndoLogs ;
1515
16+ /// Represents a single undo-able action that affects a type inference variable.
17+ #[ derive( Clone ) ]
18+ pub ( crate ) enum UndoLog < ' tcx > {
19+ EqRelation ( sv:: UndoLog < ut:: Delegate < TyVidEqKey < ' tcx > > > ) ,
20+ SubRelation ( sv:: UndoLog < ut:: Delegate < TyVidSubKey > > ) ,
21+ }
22+
23+ /// Convert from a specific kind of undo to the more general UndoLog
24+ impl < ' tcx > From < sv:: UndoLog < ut:: Delegate < TyVidEqKey < ' tcx > > > > for UndoLog < ' tcx > {
25+ fn from ( l : sv:: UndoLog < ut:: Delegate < TyVidEqKey < ' tcx > > > ) -> Self {
26+ UndoLog :: EqRelation ( l)
27+ }
28+ }
29+
30+ /// Convert from a specific kind of undo to the more general UndoLog
31+ impl < ' tcx > From < sv:: UndoLog < ut:: Delegate < TyVidSubKey > > > for UndoLog < ' tcx > {
32+ fn from ( l : sv:: UndoLog < ut:: Delegate < TyVidSubKey > > ) -> Self {
33+ UndoLog :: SubRelation ( l)
34+ }
35+ }
36+
1637impl < ' tcx > Rollback < sv:: UndoLog < ut:: Delegate < TyVidEqKey < ' tcx > > > > for TypeVariableStorage < ' tcx > {
1738 fn reverse ( & mut self , undo : sv:: UndoLog < ut:: Delegate < TyVidEqKey < ' tcx > > > ) {
1839 self . eq_relations . reverse ( undo)
1940 }
2041}
2142
43+ impl < ' tcx > Rollback < sv:: UndoLog < ut:: Delegate < TyVidSubKey > > > for TypeVariableStorage < ' tcx > {
44+ fn reverse ( & mut self , undo : sv:: UndoLog < ut:: Delegate < TyVidSubKey > > ) {
45+ self . sub_relations . reverse ( undo)
46+ }
47+ }
48+
49+ impl < ' tcx > Rollback < UndoLog < ' tcx > > for TypeVariableStorage < ' tcx > {
50+ fn reverse ( & mut self , undo : UndoLog < ' tcx > ) {
51+ match undo {
52+ UndoLog :: EqRelation ( undo) => self . eq_relations . reverse ( undo) ,
53+ UndoLog :: SubRelation ( undo) => self . sub_relations . reverse ( undo) ,
54+ }
55+ }
56+ }
57+
2258#[ derive( Clone , Default ) ]
2359pub ( crate ) struct TypeVariableStorage < ' tcx > {
2460 /// The origins of each type variable.
@@ -27,6 +63,23 @@ pub(crate) struct TypeVariableStorage<'tcx> {
2763 /// constraint `?X == ?Y`. This table also stores, for each key,
2864 /// the known value.
2965 eq_relations : ut:: UnificationTableStorage < TyVidEqKey < ' tcx > > ,
66+ /// Only used by `-Znext-solver` and for diagnostics.
67+ ///
68+ /// When reporting ambiguity errors, we sometimes want to
69+ /// treat all inference vars which are subtypes of each
70+ /// others as if they are equal. For this case we compute
71+ /// the transitive closure of our subtype obligations here.
72+ ///
73+ /// E.g. when encountering ambiguity errors, we want to suggest
74+ /// specifying some method argument or to add a type annotation
75+ /// to a local variable. Because subtyping cannot change the
76+ /// shape of a type, it's fine if the cause of the ambiguity error
77+ /// is only related to the suggested variable via subtyping.
78+ ///
79+ /// Even for something like `let x = returns_arg(); x.method();` the
80+ /// type of `x` is only a supertype of the argument of `returns_arg`. We
81+ /// still want to suggest specifying the type of the argument.
82+ sub_relations : ut:: UnificationTableStorage < TyVidSubKey > ,
3083}
3184
3285pub ( crate ) struct TypeVariableTable < ' a , ' tcx > {
@@ -109,6 +162,16 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
109162 debug_assert ! ( self . probe( a) . is_unknown( ) ) ;
110163 debug_assert ! ( self . probe( b) . is_unknown( ) ) ;
111164 self . eq_relations ( ) . union ( a, b) ;
165+ self . sub_relations ( ) . union ( a, b) ;
166+ }
167+
168+ /// Records that `a <: b`, depending on `dir`.
169+ ///
170+ /// Precondition: neither `a` nor `b` are known.
171+ pub ( crate ) fn sub ( & mut self , a : ty:: TyVid , b : ty:: TyVid ) {
172+ debug_assert ! ( self . probe( a) . is_unknown( ) ) ;
173+ debug_assert ! ( self . probe( b) . is_unknown( ) ) ;
174+ self . sub_relations ( ) . union ( a, b) ;
112175 }
113176
114177 /// Instantiates `vid` with the type `ty`.
@@ -142,6 +205,10 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
142205 origin : TypeVariableOrigin ,
143206 ) -> ty:: TyVid {
144207 let eq_key = self . eq_relations ( ) . new_key ( TypeVariableValue :: Unknown { universe } ) ;
208+
209+ let sub_key = self . sub_relations ( ) . new_key ( ( ) ) ;
210+ debug_assert_eq ! ( eq_key. vid, sub_key. vid) ;
211+
145212 let index = self . storage . values . push ( TypeVariableData { origin } ) ;
146213 debug_assert_eq ! ( eq_key. vid, index) ;
147214
@@ -164,6 +231,18 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
164231 self . eq_relations ( ) . find ( vid) . vid
165232 }
166233
234+ /// Returns the "root" variable of `vid` in the `sub_relations`
235+ /// equivalence table. All type variables that have been are
236+ /// related via equality or subtyping will yield the same root
237+ /// variable (per the union-find algorithm), so `sub_root_var(a)
238+ /// == sub_root_var(b)` implies that:
239+ /// ```text
240+ /// exists X. (a <: X || X <: a) && (b <: X || X <: b)
241+ /// ```
242+ pub ( crate ) fn sub_root_var ( & mut self , vid : ty:: TyVid ) -> ty:: TyVid {
243+ self . sub_relations ( ) . find ( vid) . vid
244+ }
245+
167246 /// Retrieves the type to which `vid` has been instantiated, if
168247 /// any.
169248 pub ( crate ) fn probe ( & mut self , vid : ty:: TyVid ) -> TypeVariableValue < ' tcx > {
@@ -181,6 +260,11 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
181260 self . storage . eq_relations . with_log ( self . undo_log )
182261 }
183262
263+ #[ inline]
264+ fn sub_relations ( & mut self ) -> super :: UnificationTable < ' _ , ' tcx , TyVidSubKey > {
265+ self . storage . sub_relations . with_log ( self . undo_log )
266+ }
267+
184268 /// Returns a range of the type variables created during the snapshot.
185269 pub ( crate ) fn vars_since_snapshot (
186270 & mut self ,
@@ -243,6 +327,33 @@ impl<'tcx> ut::UnifyKey for TyVidEqKey<'tcx> {
243327 }
244328}
245329
330+ #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
331+ pub ( crate ) struct TyVidSubKey {
332+ vid : ty:: TyVid ,
333+ }
334+
335+ impl From < ty:: TyVid > for TyVidSubKey {
336+ #[ inline] // make this function eligible for inlining - it is quite hot.
337+ fn from ( vid : ty:: TyVid ) -> Self {
338+ TyVidSubKey { vid }
339+ }
340+ }
341+
342+ impl ut:: UnifyKey for TyVidSubKey {
343+ type Value = ( ) ;
344+ #[ inline]
345+ fn index ( & self ) -> u32 {
346+ self . vid . as_u32 ( )
347+ }
348+ #[ inline]
349+ fn from_index ( i : u32 ) -> TyVidSubKey {
350+ TyVidSubKey { vid : ty:: TyVid :: from_u32 ( i) }
351+ }
352+ fn tag ( ) -> & ' static str {
353+ "TyVidSubKey"
354+ }
355+ }
356+
246357impl < ' tcx > ut:: UnifyValue for TypeVariableValue < ' tcx > {
247358 type Error = ut:: NoError ;
248359
0 commit comments