Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1261,18 +1261,36 @@ 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 `{}`",
assoc_name,
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();
}
Expand Down
18 changes: 14 additions & 4 deletions src/test/compile-fail/E0221.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) { }
}

Expand All @@ -29,24 +35,18 @@ pub trait BoxCar : Box + Vehicle {
fn dent<C:BoxCar>(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<COLOR>(c: BoxCar<Color=COLOR>) {
//~^ 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:BoxCar>(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() { }