@@ -12,11 +12,12 @@ use middle::ty::{self, Ty};
12
12
use middle:: ty:: error:: TypeError ;
13
13
use middle:: ty:: relate:: { self , Relate , TypeRelation , RelateResult } ;
14
14
15
- /// A type "A" *matches* "B" if the fresh types in B could be
16
- /// substituted with values so as to make it equal to A. Matching is
17
- /// intended to be used only on freshened types, and it basically
18
- /// indicates if the non-freshened versions of A and B could have been
19
- /// unified.
15
+ /// A type "B" is a "recurrence" of "A" if the fresh types in B could
16
+ /// be substituted with values so as to make it equal to A. Recurrence
17
+ /// checking is intended to be used only on freshened types, and it
18
+ /// basically indicates if the non-freshened versions of A and B could
19
+ /// have been unified. We use it as part of trait match evaluation to
20
+ /// detect and sidestep infinite recursion.
20
21
///
21
22
/// It is only an approximation. If it yields false, unification would
22
23
/// definitely fail, but a true result doesn't mean unification would
@@ -25,21 +26,28 @@ use middle::ty::relate::{self, Relate, TypeRelation, RelateResult};
25
26
/// more than once. To some extent these approximations could be
26
27
/// fixed, given effort.
27
28
///
28
- /// Like subtyping, matching is really a binary relation, so the only
29
- /// important thing about the result is Ok/Err. Also, matching never
30
- /// affects any type variables or unification state.
31
- pub struct Match < ' a , ' tcx : ' a > {
29
+ /// Like subtyping, recurrence is really a binary relation, so the
30
+ /// only important thing about the result is Ok/Err. Also, recurrence
31
+ /// never affects any type variables or unification state.
32
+ pub fn is_recurrence < ' a , ' tcx , T > ( tcx : & ' a ty:: ctxt < ' tcx > , a : & T , b : & T ) -> bool
33
+ where T : Relate < ' a , ' tcx >
34
+ {
35
+ let mut recur = Recurrence :: new ( tcx) ;
36
+ T :: relate ( & mut recur, a, b) . is_ok ( )
37
+ }
38
+
39
+ struct Recurrence < ' a , ' tcx : ' a > {
32
40
tcx : & ' a ty:: ctxt < ' tcx >
33
41
}
34
42
35
- impl < ' a , ' tcx > Match < ' a , ' tcx > {
36
- pub fn new ( tcx : & ' a ty:: ctxt < ' tcx > ) -> Match < ' a , ' tcx > {
37
- Match { tcx : tcx }
43
+ impl < ' a , ' tcx > Recurrence < ' a , ' tcx > {
44
+ pub fn new ( tcx : & ' a ty:: ctxt < ' tcx > ) -> Recurrence < ' a , ' tcx > {
45
+ Recurrence { tcx : tcx }
38
46
}
39
47
}
40
48
41
- impl < ' a , ' tcx > TypeRelation < ' a , ' tcx > for Match < ' a , ' tcx > {
42
- fn tag ( & self ) -> & ' static str { "Match " }
49
+ impl < ' a , ' tcx > TypeRelation < ' a , ' tcx > for Recurrence < ' a , ' tcx > {
50
+ fn tag ( & self ) -> & ' static str { "Recurrence " }
43
51
fn tcx ( & self ) -> & ' a ty:: ctxt < ' tcx > { self . tcx }
44
52
fn a_is_expected ( & self ) -> bool { true } // irrelevant
45
53
0 commit comments