@@ -22,6 +22,47 @@ use util::ppaux::Repr;
22
22
use super :: { Obligation , ObligationCause , PredicateObligation ,
23
23
VtableImpl , VtableParam , VtableImplData } ;
24
24
25
+ struct PredicateSet < ' a , ' tcx : ' a > {
26
+ tcx : & ' a ty:: ctxt < ' tcx > ,
27
+ set : FnvHashSet < ty:: Predicate < ' tcx > > ,
28
+ }
29
+
30
+ impl < ' a , ' tcx > PredicateSet < ' a , ' tcx > {
31
+ fn new ( tcx : & ' a ty:: ctxt < ' tcx > ) -> PredicateSet < ' a , ' tcx > {
32
+ PredicateSet { tcx : tcx, set : FnvHashSet ( ) }
33
+ }
34
+
35
+ fn insert ( & mut self , pred : & ty:: Predicate < ' tcx > ) -> bool {
36
+ // We have to be careful here because we want
37
+ //
38
+ // for<'a> Foo<&'a int>
39
+ //
40
+ // and
41
+ //
42
+ // for<'b> Foo<&'b int>
43
+ //
44
+ // to be considered equivalent. So normalize all late-bound
45
+ // regions before we throw things into the underlying set.
46
+ let normalized_pred = match * pred {
47
+ ty:: Predicate :: Trait ( ref data) =>
48
+ ty:: Predicate :: Trait ( ty:: anonymize_late_bound_regions ( self . tcx , data) ) ,
49
+
50
+ ty:: Predicate :: Equate ( ref data) =>
51
+ ty:: Predicate :: Equate ( ty:: anonymize_late_bound_regions ( self . tcx , data) ) ,
52
+
53
+ ty:: Predicate :: RegionOutlives ( ref data) =>
54
+ ty:: Predicate :: RegionOutlives ( ty:: anonymize_late_bound_regions ( self . tcx , data) ) ,
55
+
56
+ ty:: Predicate :: TypeOutlives ( ref data) =>
57
+ ty:: Predicate :: TypeOutlives ( ty:: anonymize_late_bound_regions ( self . tcx , data) ) ,
58
+
59
+ ty:: Predicate :: Projection ( ref data) =>
60
+ ty:: Predicate :: Projection ( ty:: anonymize_late_bound_regions ( self . tcx , data) ) ,
61
+ } ;
62
+ self . set . insert ( normalized_pred)
63
+ }
64
+ }
65
+
25
66
///////////////////////////////////////////////////////////////////////////
26
67
// `Elaboration` iterator
27
68
///////////////////////////////////////////////////////////////////////////
@@ -36,7 +77,7 @@ use super::{Obligation, ObligationCause, PredicateObligation,
36
77
pub struct Elaborator < ' cx , ' tcx : ' cx > {
37
78
tcx : & ' cx ty:: ctxt < ' tcx > ,
38
79
stack : Vec < StackEntry < ' tcx > > ,
39
- visited : FnvHashSet < ty :: Predicate < ' tcx > > ,
80
+ visited : PredicateSet < ' cx , ' tcx > ,
40
81
}
41
82
42
83
struct StackEntry < ' tcx > {
@@ -68,8 +109,8 @@ pub fn elaborate_predicates<'cx, 'tcx>(
68
109
mut predicates : Vec < ty:: Predicate < ' tcx > > )
69
110
-> Elaborator < ' cx , ' tcx >
70
111
{
71
- let mut visited = FnvHashSet ( ) ;
72
- predicates. retain ( |pred| visited. insert ( pred. clone ( ) ) ) ;
112
+ let mut visited = PredicateSet :: new ( tcx ) ;
113
+ predicates. retain ( |pred| visited. insert ( pred) ) ;
73
114
let entry = StackEntry { position : 0 , predicates : predicates } ;
74
115
Elaborator { tcx : tcx, stack : vec ! [ entry] , visited : visited }
75
116
}
@@ -91,7 +132,7 @@ impl<'cx, 'tcx> Elaborator<'cx, 'tcx> {
91
132
// recursion in some cases. One common case is when
92
133
// people define `trait Sized: Sized { }` rather than `trait
93
134
// Sized { }`.
94
- predicates. retain ( |r| self . visited . insert ( r. clone ( ) ) ) ;
135
+ predicates. retain ( |r| self . visited . insert ( r) ) ;
95
136
96
137
self . stack . push ( StackEntry { position : 0 ,
97
138
predicates : predicates } ) ;
0 commit comments