Skip to content

Commit 8d9bb17

Browse files
committed
Extend the solution to encompass HRTB
1 parent be8d9bb commit 8d9bb17

File tree

2 files changed

+54
-4
lines changed

2 files changed

+54
-4
lines changed

src/librustc/middle/traits/util.rs

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,47 @@ use util::ppaux::Repr;
2222
use super::{Obligation, ObligationCause, PredicateObligation,
2323
VtableImpl, VtableParam, VtableImplData};
2424

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+
2566
///////////////////////////////////////////////////////////////////////////
2667
// `Elaboration` iterator
2768
///////////////////////////////////////////////////////////////////////////
@@ -36,7 +77,7 @@ use super::{Obligation, ObligationCause, PredicateObligation,
3677
pub struct Elaborator<'cx, 'tcx:'cx> {
3778
tcx: &'cx ty::ctxt<'tcx>,
3879
stack: Vec<StackEntry<'tcx>>,
39-
visited: FnvHashSet<ty::Predicate<'tcx>>,
80+
visited: PredicateSet<'cx,'tcx>,
4081
}
4182

4283
struct StackEntry<'tcx> {
@@ -68,8 +109,8 @@ pub fn elaborate_predicates<'cx, 'tcx>(
68109
mut predicates: Vec<ty::Predicate<'tcx>>)
69110
-> Elaborator<'cx, 'tcx>
70111
{
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));
73114
let entry = StackEntry { position: 0, predicates: predicates };
74115
Elaborator { tcx: tcx, stack: vec![entry], visited: visited }
75116
}
@@ -91,7 +132,7 @@ impl<'cx, 'tcx> Elaborator<'cx, 'tcx> {
91132
// recursion in some cases. One common case is when
92133
// people define `trait Sized: Sized { }` rather than `trait
93134
// Sized { }`.
94-
predicates.retain(|r| self.visited.insert(r.clone()));
135+
predicates.retain(|r| self.visited.insert(r));
95136

96137
self.stack.push(StackEntry { position: 0,
97138
predicates: predicates });
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
fn foo<T>(t: T) -> i32
2+
where T : for<'a> Fn(&'a u8) -> i32,
3+
T : for<'b> Fn(&'b u8) -> i32,
4+
{
5+
t(&3)
6+
}
7+
8+
fn main() {
9+
}

0 commit comments

Comments
 (0)