Skip to content

Commit 8aa21c9

Browse files
committed
---
yaml --- r: 161122 b: refs/heads/try c: 3b91a39 h: refs/heads/master v: v3
1 parent 09eaae9 commit 8aa21c9

File tree

3 files changed

+30
-26
lines changed

3 files changed

+30
-26
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
refs/heads/master: 4eb72d268f337a8f117c86a2ac1b98336cab9e9d
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: c9f6d696420107f82304b992cf623b806995fe18
5-
refs/heads/try: dd5ce5ae2f254cc42763518909f6e7c486d9502a
5+
refs/heads/try: 3b91a39d890b2d355dab70deabb713cff9dc558c
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
88
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596

branches/try/src/librustc/middle/traits/fulfill.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
use middle::mem_categorization::Typer;
1212
use middle::ty;
1313
use middle::typeck::infer::InferCtxt;
14+
use std::collections::HashSet;
15+
use std::rc::Rc;
1416
use util::ppaux::Repr;
1517

1618
use super::CodeAmbiguity;
@@ -32,6 +34,13 @@ use super::select::SelectionContext;
3234
* ambiguous cases as errors.
3335
*/
3436
pub struct FulfillmentContext<'tcx> {
37+
// a simple cache that aims to cache *exact duplicate obligations*
38+
// and avoid adding them twice. This serves a different purpose
39+
// than the `SelectionCache`: it avoids duplicate errors and
40+
// permits recursive obligations, which are often generated from
41+
// traits like `Send` et al.
42+
duplicate_set: HashSet<Rc<ty::TraitRef<'tcx>>>,
43+
3544
// A list of all obligations that have been registered with this
3645
// fulfillment context.
3746
trait_obligations: Vec<Obligation<'tcx>>,
@@ -45,6 +54,7 @@ pub struct FulfillmentContext<'tcx> {
4554
impl<'tcx> FulfillmentContext<'tcx> {
4655
pub fn new() -> FulfillmentContext<'tcx> {
4756
FulfillmentContext {
57+
duplicate_set: HashSet::new(),
4858
trait_obligations: Vec::new(),
4959
attempted_mark: 0,
5060
}
@@ -54,9 +64,13 @@ impl<'tcx> FulfillmentContext<'tcx> {
5464
tcx: &ty::ctxt<'tcx>,
5565
obligation: Obligation<'tcx>)
5666
{
57-
debug!("register_obligation({})", obligation.repr(tcx));
58-
assert!(!obligation.trait_ref.has_escaping_regions());
59-
self.trait_obligations.push(obligation);
67+
if self.duplicate_set.insert(obligation.trait_ref.clone()) {
68+
debug!("register_obligation({})", obligation.repr(tcx));
69+
assert!(!obligation.trait_ref.has_escaping_regions());
70+
self.trait_obligations.push(obligation);
71+
} else {
72+
debug!("register_obligation({}) -- already seen, skip", obligation.repr(tcx));
73+
}
6074
}
6175

6276
pub fn select_all_or_error<'a>(&mut self,

branches/try/src/librustc/middle/traits/select.rs

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ pub enum MethodMatchedData {
114114
* candidate is one that might match or might not, depending on how
115115
* type variables wind up being resolved. This only occurs during inference.
116116
*
117-
* For selection to suceed, there must be exactly one non-ambiguous
117+
* For selection to succeed, there must be exactly one non-ambiguous
118118
* candidate. Usually, it is not possible to have more than one
119119
* definitive candidate, due to the coherence rules. However, there is
120120
* one case where it could occur: if there is a blanket impl for a
@@ -1202,24 +1202,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12021202
candidates: &mut CandidateSet<'tcx>)
12031203
-> Result<(),SelectionError<'tcx>>
12041204
{
1205-
// FIXME -- To be more like a normal impl, we should just
1206-
// ignore the nested cases here, and instead generate nested
1207-
// obligations in `confirm_candidate`. However, this doesn't
1208-
// work because we require handling the recursive cases to
1209-
// avoid infinite cycles (that is, with recursive types,
1210-
// sometimes `Foo : Copy` only holds if `Foo : Copy`).
1211-
12121205
match self.builtin_bound(bound, stack.obligation.self_ty()) {
1213-
Ok(If(nested)) => {
1214-
debug!("builtin_bound: bound={} nested={}",
1215-
bound.repr(self.tcx()),
1216-
nested.repr(self.tcx()));
1217-
let data = self.vtable_builtin_data(stack.obligation, bound, nested);
1218-
match self.winnow_selection(Some(stack), VtableBuiltin(data)) {
1219-
EvaluatedToOk => { Ok(candidates.vec.push(BuiltinCandidate(bound))) }
1220-
EvaluatedToAmbig => { Ok(candidates.ambiguous = true) }
1221-
EvaluatedToErr => { Err(Unimplemented) }
1222-
}
1206+
Ok(If(_)) => {
1207+
debug!("builtin_bound: bound={}",
1208+
bound.repr(self.tcx()));
1209+
candidates.vec.push(BuiltinCandidate(bound));
1210+
Ok(())
12231211
}
12241212
Ok(ParameterBuiltin) => { Ok(()) }
12251213
Ok(AmbiguousBuiltin) => { Ok(candidates.ambiguous = true) }
@@ -1575,8 +1563,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15751563
candidate.repr(self.tcx()));
15761564

15771565
match candidate {
1578-
// FIXME -- see assemble_builtin_bound_candidates()
1579-
BuiltinCandidate(_) |
1566+
BuiltinCandidate(builtin_bound) => {
1567+
Ok(VtableBuiltin(
1568+
try!(self.confirm_builtin_candidate(obligation, builtin_bound))))
1569+
}
1570+
15801571
ErrorCandidate => {
15811572
Ok(VtableBuiltin(VtableBuiltinData { nested: VecPerParamSpace::empty() }))
15821573
}
@@ -1626,8 +1617,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
16261617

16271618
match try!(self.builtin_bound(bound, obligation.self_ty())) {
16281619
If(nested) => Ok(self.vtable_builtin_data(obligation, bound, nested)),
1629-
AmbiguousBuiltin |
1630-
ParameterBuiltin => {
1620+
AmbiguousBuiltin | ParameterBuiltin => {
16311621
self.tcx().sess.span_bug(
16321622
obligation.cause.span,
16331623
format!("builtin bound for {} was ambig",

0 commit comments

Comments
 (0)