about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMikhail Modin <mikhailm1@gmail.com>2016-10-23 21:53:31 +0300
committerMikhail Modin <mikhailm1@gmail.com>2016-10-23 21:53:31 +0300
commit585f835b8e53d48c5ee41275d728e931f4c62a00 (patch)
tree6d1be0eb088744a1988cb72bb7af35f34ed984e7
parent7bccb829d0fe9a733bd6efcf6f7313186ae237ab (diff)
downloadrust-585f835b8e53d48c5ee41275d728e931f4c62a00.tar.gz
rust-585f835b8e53d48c5ee41275d728e931f4c62a00.zip
Make error E0221 more helpful
-rw-r--r--src/librustc_typeck/astconv.rs28
-rw-r--r--src/test/compile-fail/E0221.rs18
-rw-r--r--src/test/compile-fail/associated-type-projection-from-multiple-supertraits.rs14
3 files changed, 44 insertions, 16 deletions
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 4fbb31cf0a5..dcb94bfa4aa 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: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() { }