@@ -13,12 +13,48 @@ use tracing::debug;
13
13
14
14
use crate :: infer:: InferCtxtUndoLogs ;
15
15
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
+
16
37
impl < ' tcx > Rollback < sv:: UndoLog < ut:: Delegate < TyVidEqKey < ' tcx > > > > for TypeVariableStorage < ' tcx > {
17
38
fn reverse ( & mut self , undo : sv:: UndoLog < ut:: Delegate < TyVidEqKey < ' tcx > > > ) {
18
39
self . eq_relations . reverse ( undo)
19
40
}
20
41
}
21
42
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
+
22
58
#[ derive( Clone , Default ) ]
23
59
pub ( crate ) struct TypeVariableStorage < ' tcx > {
24
60
/// The origins of each type variable.
@@ -27,6 +63,23 @@ pub(crate) struct TypeVariableStorage<'tcx> {
27
63
/// constraint `?X == ?Y`. This table also stores, for each key,
28
64
/// the known value.
29
65
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 > ,
30
83
}
31
84
32
85
pub ( crate ) struct TypeVariableTable < ' a , ' tcx > {
@@ -109,6 +162,16 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
109
162
debug_assert ! ( self . probe( a) . is_unknown( ) ) ;
110
163
debug_assert ! ( self . probe( b) . is_unknown( ) ) ;
111
164
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) ;
112
175
}
113
176
114
177
/// Instantiates `vid` with the type `ty`.
@@ -142,6 +205,10 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
142
205
origin : TypeVariableOrigin ,
143
206
) -> ty:: TyVid {
144
207
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
+
145
212
let index = self . storage . values . push ( TypeVariableData { origin } ) ;
146
213
debug_assert_eq ! ( eq_key. vid, index) ;
147
214
@@ -164,6 +231,18 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
164
231
self . eq_relations ( ) . find ( vid) . vid
165
232
}
166
233
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
+
167
246
/// Retrieves the type to which `vid` has been instantiated, if
168
247
/// any.
169
248
pub ( crate ) fn probe ( & mut self , vid : ty:: TyVid ) -> TypeVariableValue < ' tcx > {
@@ -181,6 +260,11 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
181
260
self . storage . eq_relations . with_log ( self . undo_log )
182
261
}
183
262
263
+ #[ inline]
264
+ fn sub_relations ( & mut self ) -> super :: UnificationTable < ' _ , ' tcx , TyVidSubKey > {
265
+ self . storage . sub_relations . with_log ( self . undo_log )
266
+ }
267
+
184
268
/// Returns a range of the type variables created during the snapshot.
185
269
pub ( crate ) fn vars_since_snapshot (
186
270
& mut self ,
@@ -243,6 +327,33 @@ impl<'tcx> ut::UnifyKey for TyVidEqKey<'tcx> {
243
327
}
244
328
}
245
329
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
+
246
357
impl < ' tcx > ut:: UnifyValue for TypeVariableValue < ' tcx > {
247
358
type Error = ut:: NoError ;
248
359
0 commit comments