about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorOliver Scherer <github35764891676564198441@oli-obk.de>2019-01-29 17:10:08 +0100
committerOliver Scherer <github35764891676564198441@oli-obk.de>2019-02-01 16:39:50 +0100
commitf2241f640bb9f04cce88b2d28092cbfcee04c43e (patch)
tree210533260525fd49bfc718ea94c21f1fb6dc4ea3 /src
parent984688ace34ec0add8f365ead6587237537fc230 (diff)
downloadrust-f2241f640bb9f04cce88b2d28092cbfcee04c43e.tar.gz
rust-f2241f640bb9f04cce88b2d28092cbfcee04c43e.zip
Make the existential type errors a little bit more helpful
Diffstat (limited to 'src')
-rw-r--r--src/librustc_typeck/collect.rs30
-rw-r--r--src/test/ui/existential_types/different_defining_uses.stderr2
-rw-r--r--src/test/ui/existential_types/different_defining_uses_never_type.stderr4
-rw-r--r--src/test/ui/existential_types/generic_different_defining_uses.stderr2
-rw-r--r--src/test/ui/existential_types/generic_duplicate_param_use3.stderr2
-rw-r--r--src/test/ui/existential_types/generic_duplicate_param_use5.stderr2
-rw-r--r--src/test/ui/existential_types/generic_duplicate_param_use6.stderr2
7 files changed, 32 insertions, 12 deletions
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 7cdcfec339e..b26a6a2292a 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1355,10 +1355,9 @@ fn find_existential_constraints<'a, 'tcx>(
                 let mut index_map: FxHashMap<ty::ParamTy, usize> = FxHashMap::default();
                 // skip binder is ok, since we only use this to find generic parameters and their
                 // positions.
-                for subst in substs.iter() {
+                for (idx, subst) in substs.iter().enumerate() {
                     if let UnpackedKind::Type(ty) = subst.unpack() {
                         if let ty::Param(p) = ty.sty {
-                            let idx = index_map.len();
                             if index_map.insert(p, idx).is_some() {
                                 // there was already an entry for `p`, meaning a generic parameter
                                 // was used twice
@@ -1391,20 +1390,24 @@ fn find_existential_constraints<'a, 'tcx>(
                 }).collect();
                 if let Some((prev_span, prev_ty, ref prev_indices)) = self.found {
                     let mut ty = concrete_type.walk().fuse();
-                    let mut prev_ty = prev_ty.walk().fuse();
-                    let iter_eq = (&mut ty).zip(&mut prev_ty).all(|(t, p)| match (&t.sty, &p.sty) {
+                    let mut p_ty = prev_ty.walk().fuse();
+                    let iter_eq = (&mut ty).zip(&mut p_ty).all(|(t, p)| match (&t.sty, &p.sty) {
                         // type parameters are equal to any other type parameter for the purpose of
                         // concrete type equality, as it is possible to obtain the same type just
                         // by passing matching parameters to a function.
                         (ty::Param(_), ty::Param(_)) => true,
                         _ => t == p,
                     });
-                    if !iter_eq || ty.next().is_some() || prev_ty.next().is_some() {
+                    if !iter_eq || ty.next().is_some() || p_ty.next().is_some() {
                         // found different concrete types for the existential type
                         let mut err = self.tcx.sess.struct_span_err(
                             span,
                             "concrete type differs from previous defining existential type use",
                         );
+                        err.span_label(
+                            span,
+                            format!("expected `{}`, got `{}`", prev_ty, concrete_type),
+                        );
                         err.span_note(prev_span, "previous use here");
                         err.emit();
                     } else if indices != *prev_indices {
@@ -1413,6 +1416,23 @@ fn find_existential_constraints<'a, 'tcx>(
                             span,
                             "concrete type's generic parameters differ from previous defining use",
                         );
+                        use std::fmt::Write;
+                        let mut s = String::new();
+                        write!(s, "expected [").unwrap();
+                        let list = |s: &mut String, indices: &Vec<usize>| {
+                            let mut indices = indices.iter().cloned();
+                            if let Some(first) = indices.next() {
+                                write!(s, "`{}`", substs[first]).unwrap();
+                                for i in indices {
+                                    write!(s, ", `{}`", substs[i]).unwrap();
+                                }
+                            }
+                        };
+                        list(&mut s, prev_indices);
+                        write!(s, "], got [").unwrap();
+                        list(&mut s, &indices);
+                        write!(s, "]").unwrap();
+                        err.span_label(span, s);
                         err.span_note(prev_span, "previous use here");
                         err.emit();
                     }
diff --git a/src/test/ui/existential_types/different_defining_uses.stderr b/src/test/ui/existential_types/different_defining_uses.stderr
index 3b3449bbf11..3f9ed96400b 100644
--- a/src/test/ui/existential_types/different_defining_uses.stderr
+++ b/src/test/ui/existential_types/different_defining_uses.stderr
@@ -4,7 +4,7 @@ error: concrete type differs from previous defining existential type use
 LL | / fn bar() -> Foo { //~ ERROR concrete type differs from previous
 LL | |     42i32
 LL | | }
-   | |_^
+   | |_^ expected `&'static str`, got `i32`
    |
 note: previous use here
   --> $DIR/different_defining_uses.rs:8:1
diff --git a/src/test/ui/existential_types/different_defining_uses_never_type.stderr b/src/test/ui/existential_types/different_defining_uses_never_type.stderr
index 161111e3379..e29256a5014 100644
--- a/src/test/ui/existential_types/different_defining_uses_never_type.stderr
+++ b/src/test/ui/existential_types/different_defining_uses_never_type.stderr
@@ -4,7 +4,7 @@ error: concrete type differs from previous defining existential type use
 LL | / fn bar() -> Foo { //~ ERROR concrete type differs from previous
 LL | |     panic!()
 LL | | }
-   | |_^
+   | |_^ expected `&'static str`, got `()`
    |
 note: previous use here
   --> $DIR/different_defining_uses_never_type.rs:8:1
@@ -20,7 +20,7 @@ error: concrete type differs from previous defining existential type use
 LL | / fn boo() -> Foo { //~ ERROR concrete type differs from previous
 LL | |     loop {}
 LL | | }
-   | |_^
+   | |_^ expected `&'static str`, got `()`
    |
 note: previous use here
   --> $DIR/different_defining_uses_never_type.rs:8:1
diff --git a/src/test/ui/existential_types/generic_different_defining_uses.stderr b/src/test/ui/existential_types/generic_different_defining_uses.stderr
index 89f70a873d9..3f129658b8f 100644
--- a/src/test/ui/existential_types/generic_different_defining_uses.stderr
+++ b/src/test/ui/existential_types/generic_different_defining_uses.stderr
@@ -4,7 +4,7 @@ error: concrete type differs from previous defining existential type use
 LL | / fn my_iter2<T>(t: T) -> MyIter<T> { //~ ERROR concrete type differs from previous
 LL | |     Some(t).into_iter()
 LL | | }
-   | |_^
+   | |_^ expected `std::iter::Once<T>`, got `std::option::IntoIter<T>`
    |
 note: previous use here
   --> $DIR/generic_different_defining_uses.rs:7:1
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use3.stderr b/src/test/ui/existential_types/generic_duplicate_param_use3.stderr
index 8f860e7ee0a..1c96c15a769 100644
--- a/src/test/ui/existential_types/generic_duplicate_param_use3.stderr
+++ b/src/test/ui/existential_types/generic_duplicate_param_use3.stderr
@@ -14,7 +14,7 @@ LL | / fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
 LL | | //~^ concrete type's generic parameters differ from previous defining use
 LL | |     u
 LL | | }
-   | |_^
+   | |_^ expected [`T`], got [`U`]
    |
 note: previous use here
   --> $DIR/generic_duplicate_param_use3.rs:15:1
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use5.stderr b/src/test/ui/existential_types/generic_duplicate_param_use5.stderr
index 52befb9c2e1..166623801c2 100644
--- a/src/test/ui/existential_types/generic_duplicate_param_use5.stderr
+++ b/src/test/ui/existential_types/generic_duplicate_param_use5.stderr
@@ -5,7 +5,7 @@ LL | / fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
 LL | | //~^ concrete type differs from previous
 LL | |     (u, t)
 LL | | }
-   | |_^
+   | |_^ expected `(T, U)`, got `(U, T)`
    |
 note: previous use here
   --> $DIR/generic_duplicate_param_use5.rs:10:1
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use6.stderr b/src/test/ui/existential_types/generic_duplicate_param_use6.stderr
index 2bf1d0c05e6..da49a83be1f 100644
--- a/src/test/ui/existential_types/generic_duplicate_param_use6.stderr
+++ b/src/test/ui/existential_types/generic_duplicate_param_use6.stderr
@@ -5,7 +5,7 @@ LL | / fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
 LL | | //~^ concrete type differs from previous
 LL | |     (u, t)
 LL | | }
-   | |_^
+   | |_^ expected `(T, T)`, got `(U, T)`
    |
 note: previous use here
   --> $DIR/generic_duplicate_param_use6.rs:10:1