Skip to content

Commit

Permalink
Rollup merge of rust-lang#37396 - mikhail-m1:e0221, r=jonathandturner
Browse files Browse the repository at this point in the history
Make error E0221 more helpful

fix rust-lang#35970 as part of rust-lang#35233
r? @jonathandturner
  • Loading branch information
GuillaumeGomez committed Oct 26, 2016
2 parents cf6f885 + 585f835 commit 46c5c6c
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 16 deletions.
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() { }

0 comments on commit 46c5c6c

Please sign in to comment.