@@ -13,7 +13,7 @@ use rustc::ty::subst::Substs;
13
13
14
14
use semcheck:: mapping:: IdMapping ;
15
15
16
- use std:: collections:: { HashMap , VecDeque } ;
16
+ use std:: collections:: { HashMap , HashSet , VecDeque } ;
17
17
18
18
/// A relation searching for items appearing at the same spot in a type.
19
19
///
@@ -27,6 +27,10 @@ pub struct MismatchRelation<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
27
27
item_queue : VecDeque < ( DefId , DefId ) > ,
28
28
/// The id mapping to use.
29
29
id_mapping : & ' a mut IdMapping ,
30
+ /// Type cache holding all old types currently being processed to avoid loops.
31
+ current_old_types : HashSet < Ty < ' tcx > > ,
32
+ /// Type cache holding all new types currently being processed to avoid loops.
33
+ current_new_types : HashSet < Ty < ' tcx > > ,
30
34
}
31
35
32
36
impl < ' a , ' gcx : ' a + ' tcx , ' tcx : ' a > MismatchRelation < ' a , ' gcx , ' tcx > {
@@ -37,6 +41,8 @@ impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> MismatchRelation<'a, 'gcx, 'tcx> {
37
41
tcx : tcx,
38
42
item_queue : id_mapping. toplevel_queue ( ) ,
39
43
id_mapping : id_mapping,
44
+ current_old_types : Default :: default ( ) ,
45
+ current_new_types : Default :: default ( ) ,
40
46
}
41
47
}
42
48
@@ -100,6 +106,13 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx,
100
106
fn tys ( & mut self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> RelateResult < ' tcx , Ty < ' tcx > > {
101
107
use rustc:: ty:: TypeVariants :: * ;
102
108
109
+ if self . current_old_types . contains ( a) || self . current_new_types . contains ( b) {
110
+ return Ok ( self . tcx . types . err ) ;
111
+ }
112
+
113
+ self . current_old_types . insert ( a) ;
114
+ self . current_new_types . insert ( b) ;
115
+
103
116
debug ! ( "tys: mismatch relation: a: {:?}, b: {:?}" , a, b) ;
104
117
let matching = match ( & a. sty , & b. sty ) {
105
118
( & TyAdt ( a_def, a_substs) , & TyAdt ( b_def, b_substs) ) => {
@@ -193,6 +206,9 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx,
193
206
_ => None ,
194
207
} ;
195
208
209
+ self . current_old_types . remove ( a) ;
210
+ self . current_new_types . remove ( b) ;
211
+
196
212
if let Some ( ( old_def_id, new_def_id) ) = matching {
197
213
if !self . id_mapping . contains_old_id ( old_def_id) &&
198
214
self . id_mapping . in_old_crate ( old_def_id) {
0 commit comments