diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index aa3c9a711fa..c137fca58af 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1261,6 +1261,18 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } if bounds.len() > 1 { + let spans = bounds.iter().map(|b| { + self.tcx().impl_or_trait_items(b.def_id()).iter() + .find(|&&def_id| { + match self.tcx().impl_or_trait_item(def_id) { + ty::TypeTraitItem(ref item) => item.name.as_str() == assoc_name, + _ => false + } + }) + .and_then(|&def_id| self.tcx().map.as_local_node_id(def_id)) + .and_then(|node_id| self.tcx().map.opt_span(node_id)) + }); + let mut err = struct_span_err!( self.tcx().sess, span, E0221, "ambiguous associated type `{}` in bounds of `{}`", @@ -1268,11 +1280,17 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { ty_param_name); err.span_label(span, &format!("ambiguous associated type `{}`", assoc_name)); - for bound in &bounds { - span_note!(&mut err, span, - "associated type `{}` could derive from `{}`", - ty_param_name, - bound); + for span_and_bound in spans.zip(&bounds) { + if let Some(span) = span_and_bound.0 { + err.span_label(span, &format!("ambiguous `{}` from `{}`", + assoc_name, + span_and_bound.1)); + } else { + span_note!(&mut err, span, + "associated type `{}` could derive from `{}`", + ty_param_name, + span_and_bound.1); + } } err.emit(); } diff --git a/src/test/compile-fail/E0221.rs b/src/test/compile-fail/E0221.rs index 65105458040..aed2b4084e8 100644 --- a/src/test/compile-fail/E0221.rs +++ b/src/test/compile-fail/E0221.rs @@ -12,17 +12,27 @@ trait T1 {} trait T2 {} trait Foo { - type A: T1; + type A: T1; //~ NOTE: ambiguous `A` from `Foo` } trait Bar : Foo { - type A: T2; + type A: T2; //~ NOTE: ambiguous `A` from `Bar` fn do_something() { let _: Self::A; //~^ ERROR E0221 //~| NOTE ambiguous associated type `A` - //~| NOTE associated type `Self` could derive from `Foo` - //~| NOTE associated type `Self` could derive from `Bar` + } +} + +trait T3 {} + +trait My : std::str::FromStr { + type Err: T3; //~ NOTE: ambiguous `Err` from `My` + fn test() { + let _: Self::Err; + //~^ ERROR E0221 + //~| NOTE ambiguous associated type `Err` + //~| NOTE associated type `Self` could derive from `std::str::FromStr` } } diff --git a/src/test/compile-fail/associated-type-projection-from-multiple-supertraits.rs b/src/test/compile-fail/associated-type-projection-from-multiple-supertraits.rs index a2a11c62bb8..b33bbfd8425 100644 --- a/src/test/compile-fail/associated-type-projection-from-multiple-supertraits.rs +++ b/src/test/compile-fail/associated-type-projection-from-multiple-supertraits.rs @@ -13,13 +13,19 @@ pub trait Vehicle { type Color; + //~^ NOTE ambiguous `Color` from `Vehicle` + //~| NOTE ambiguous `Color` from `Vehicle` + //~| NOTE ambiguous `Color` from `Vehicle` fn go(&self) { } } pub trait Box { type Color; - + //~^ NOTE ambiguous `Color` from `Box` + //~| NOTE ambiguous `Color` from `Box` + //~| NOTE ambiguous `Color` from `Box` + // fn mail(&self) { } } @@ -29,24 +35,18 @@ pub trait BoxCar : Box + Vehicle { fn dent(c: C, color: C::Color) { //~^ ERROR ambiguous associated type `Color` in bounds of `C` //~| NOTE ambiguous associated type `Color` - //~| NOTE could derive from `Vehicle` - //~| NOTE could derive from `Box` } fn dent_object(c: BoxCar) { //~^ ERROR ambiguous associated type //~| ERROR the value of the associated type `Color` (from the trait `Vehicle`) must be specified //~| NOTE ambiguous associated type `Color` - //~| NOTE could derive from `Vehicle` - //~| NOTE could derive from `Box` //~| NOTE missing associated type `Color` value } fn paint(c: C, d: C::Color) { //~^ ERROR ambiguous associated type `Color` in bounds of `C` //~| NOTE ambiguous associated type `Color` - //~| NOTE could derive from `Vehicle` - //~| NOTE could derive from `Box` } pub fn main() { }