diff options
| -rw-r--r-- | src/librustc/middle/traits/project.rs | 13 | ||||
| -rw-r--r-- | src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs | 52 |
2 files changed, 55 insertions, 10 deletions
diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index 435babf168e..ab90f567ea2 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -125,21 +125,14 @@ pub fn project_type<'cx,'tcx>( ambiguous: false, }; - let () = assemble_candidates_from_param_env(selcx, - obligation, - &mut candidates); - let () = assemble_candidates_from_object_type(selcx, obligation, &mut candidates); if candidates.vec.is_empty() { - // FIXME(#20297) -- In `select.rs` there is similar logic that - // gives precedence to where-clauses, but it's a bit more - // fine-grained. I was lazy here and just always give - // precedence to where-clauses or other such sources over - // actually dredging through impls. This logic probably should - // be tightened up. + let () = assemble_candidates_from_param_env(selcx, + obligation, + &mut candidates); let () = try!(assemble_candidates_from_impls(selcx, obligation, diff --git a/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs b/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs new file mode 100644 index 00000000000..12018b194ba --- /dev/null +++ b/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs @@ -0,0 +1,52 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test how resolving a projection interacts with inference. In this +// case, we were eagerly unifying the type variable for the iterator +// type with `I` from the where clause, ignoring the in-scope `impl` +// for `ByRef`. The right answer was to consider the result ambiguous +// until more type information was available. + +#![feature(associated_types, lang_items, unboxed_closures)] +#![no_implicit_prelude] + +use std::option::Option::{None, Some, mod}; + +trait Iterator { + type Item; + + fn next(&mut self) -> Option<Self::Item>; +} + +trait IteratorExt: Iterator { + fn by_ref(&mut self) -> ByRef<Self> { + ByRef(self) + } +} + +impl<I> IteratorExt for I where I: Iterator {} + +struct ByRef<'a, I: 'a + Iterator>(&'a mut I); + +impl<'a, A, I> Iterator for ByRef<'a, I> where I: Iterator<Item=A> { + type Item = A; + + fn next(&mut self) -> Option< <I as Iterator>::Item > { + self.0.next() + } +} + +fn is_iterator_of<A, I: Iterator<Item=A>>(_: &I) {} + +fn test<A, I: Iterator<Item=A>>(mut it: I) { + is_iterator_of::<A, _>(&it.by_ref()); +} + +fn main() { } |
