]> git.lizzy.rs Git - rust.git/commitdiff
Make the existential type errors a little bit more helpful
authorOliver Scherer <github35764891676564198441@oli-obk.de>
Tue, 29 Jan 2019 16:10:08 +0000 (17:10 +0100)
committerOliver Scherer <github35764891676564198441@oli-obk.de>
Fri, 1 Feb 2019 15:39:50 +0000 (16:39 +0100)
src/librustc_typeck/collect.rs
src/test/ui/existential_types/different_defining_uses.stderr
src/test/ui/existential_types/different_defining_uses_never_type.stderr
src/test/ui/existential_types/generic_different_defining_uses.stderr
src/test/ui/existential_types/generic_duplicate_param_use3.stderr
src/test/ui/existential_types/generic_duplicate_param_use5.stderr
src/test/ui/existential_types/generic_duplicate_param_use6.stderr

index 7cdcfec339eeeed6eb41cd479e0be4e9d8a17544..b26a6a2292a04c6bcd064496d021a7985cff94fb 100644 (file)
@@ -1355,10 +1355,9 @@ fn check(&mut self, def_id: DefId) {
                 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 check(&mut self, def_id: DefId) {
                 }).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 check(&mut self, def_id: DefId) {
                             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();
                     }
index 3b3449bbf11f4944dec725e14b6a22fbe7236c86..3f9ed96400b54ac4e29d670dc5dc4190d9ab3c95 100644 (file)
@@ -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
index 161111e3379f5a2be2d78742211d908e9438d697..e29256a5014f9fede3c8eecc84b6a96c14288712 100644 (file)
@@ -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
index 89f70a873d9dc6799fcdea6d39b8a356462619db..3f129658b8fd0d119e865201c98db329e6d927e2 100644 (file)
@@ -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
index 8f860e7ee0a40a2474d5106a8d69b28051ad6e98..1c96c15a76919696af6185af61c4755b03ebf14c 100644 (file)
@@ -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
index 52befb9c2e12c8f9ca729c4178a294512ef54d9e..166623801c246496ab8e935d2691bd625eef63b3 100644 (file)
@@ -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
index 2bf1d0c05e625d4a731e5f74fe89f5dcffe89aae..da49a83be1f70801d279543cde3addc284607a75 100644 (file)
@@ -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