Skip to content

Commit f2241f6

Browse files
committed
Make the existential type errors a little bit more helpful
1 parent 984688a commit f2241f6

7 files changed

+32
-12
lines changed

src/librustc_typeck/collect.rs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,10 +1355,9 @@ fn find_existential_constraints<'a, 'tcx>(
13551355
let mut index_map: FxHashMap<ty::ParamTy, usize> = FxHashMap::default();
13561356
// skip binder is ok, since we only use this to find generic parameters and their
13571357
// positions.
1358-
for subst in substs.iter() {
1358+
for (idx, subst) in substs.iter().enumerate() {
13591359
if let UnpackedKind::Type(ty) = subst.unpack() {
13601360
if let ty::Param(p) = ty.sty {
1361-
let idx = index_map.len();
13621361
if index_map.insert(p, idx).is_some() {
13631362
// there was already an entry for `p`, meaning a generic parameter
13641363
// was used twice
@@ -1391,20 +1390,24 @@ fn find_existential_constraints<'a, 'tcx>(
13911390
}).collect();
13921391
if let Some((prev_span, prev_ty, ref prev_indices)) = self.found {
13931392
let mut ty = concrete_type.walk().fuse();
1394-
let mut prev_ty = prev_ty.walk().fuse();
1395-
let iter_eq = (&mut ty).zip(&mut prev_ty).all(|(t, p)| match (&t.sty, &p.sty) {
1393+
let mut p_ty = prev_ty.walk().fuse();
1394+
let iter_eq = (&mut ty).zip(&mut p_ty).all(|(t, p)| match (&t.sty, &p.sty) {
13961395
// type parameters are equal to any other type parameter for the purpose of
13971396
// concrete type equality, as it is possible to obtain the same type just
13981397
// by passing matching parameters to a function.
13991398
(ty::Param(_), ty::Param(_)) => true,
14001399
_ => t == p,
14011400
});
1402-
if !iter_eq || ty.next().is_some() || prev_ty.next().is_some() {
1401+
if !iter_eq || ty.next().is_some() || p_ty.next().is_some() {
14031402
// found different concrete types for the existential type
14041403
let mut err = self.tcx.sess.struct_span_err(
14051404
span,
14061405
"concrete type differs from previous defining existential type use",
14071406
);
1407+
err.span_label(
1408+
span,
1409+
format!("expected `{}`, got `{}`", prev_ty, concrete_type),
1410+
);
14081411
err.span_note(prev_span, "previous use here");
14091412
err.emit();
14101413
} else if indices != *prev_indices {
@@ -1413,6 +1416,23 @@ fn find_existential_constraints<'a, 'tcx>(
14131416
span,
14141417
"concrete type's generic parameters differ from previous defining use",
14151418
);
1419+
use std::fmt::Write;
1420+
let mut s = String::new();
1421+
write!(s, "expected [").unwrap();
1422+
let list = |s: &mut String, indices: &Vec<usize>| {
1423+
let mut indices = indices.iter().cloned();
1424+
if let Some(first) = indices.next() {
1425+
write!(s, "`{}`", substs[first]).unwrap();
1426+
for i in indices {
1427+
write!(s, ", `{}`", substs[i]).unwrap();
1428+
}
1429+
}
1430+
};
1431+
list(&mut s, prev_indices);
1432+
write!(s, "], got [").unwrap();
1433+
list(&mut s, &indices);
1434+
write!(s, "]").unwrap();
1435+
err.span_label(span, s);
14161436
err.span_note(prev_span, "previous use here");
14171437
err.emit();
14181438
}

src/test/ui/existential_types/different_defining_uses.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: concrete type differs from previous defining existential type use
44
LL | / fn bar() -> Foo { //~ ERROR concrete type differs from previous
55
LL | | 42i32
66
LL | | }
7-
| |_^
7+
| |_^ expected `&'static str`, got `i32`
88
|
99
note: previous use here
1010
--> $DIR/different_defining_uses.rs:8:1

src/test/ui/existential_types/different_defining_uses_never_type.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: concrete type differs from previous defining existential type use
44
LL | / fn bar() -> Foo { //~ ERROR concrete type differs from previous
55
LL | | panic!()
66
LL | | }
7-
| |_^
7+
| |_^ expected `&'static str`, got `()`
88
|
99
note: previous use here
1010
--> $DIR/different_defining_uses_never_type.rs:8:1
@@ -20,7 +20,7 @@ error: concrete type differs from previous defining existential type use
2020
LL | / fn boo() -> Foo { //~ ERROR concrete type differs from previous
2121
LL | | loop {}
2222
LL | | }
23-
| |_^
23+
| |_^ expected `&'static str`, got `()`
2424
|
2525
note: previous use here
2626
--> $DIR/different_defining_uses_never_type.rs:8:1

src/test/ui/existential_types/generic_different_defining_uses.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: concrete type differs from previous defining existential type use
44
LL | / fn my_iter2<T>(t: T) -> MyIter<T> { //~ ERROR concrete type differs from previous
55
LL | | Some(t).into_iter()
66
LL | | }
7-
| |_^
7+
| |_^ expected `std::iter::Once<T>`, got `std::option::IntoIter<T>`
88
|
99
note: previous use here
1010
--> $DIR/generic_different_defining_uses.rs:7:1

src/test/ui/existential_types/generic_duplicate_param_use3.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ LL | / fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
1414
LL | | //~^ concrete type's generic parameters differ from previous defining use
1515
LL | | u
1616
LL | | }
17-
| |_^
17+
| |_^ expected [`T`], got [`U`]
1818
|
1919
note: previous use here
2020
--> $DIR/generic_duplicate_param_use3.rs:15:1

src/test/ui/existential_types/generic_duplicate_param_use5.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | / fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
55
LL | | //~^ concrete type differs from previous
66
LL | | (u, t)
77
LL | | }
8-
| |_^
8+
| |_^ expected `(T, U)`, got `(U, T)`
99
|
1010
note: previous use here
1111
--> $DIR/generic_duplicate_param_use5.rs:10:1

src/test/ui/existential_types/generic_duplicate_param_use6.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | / fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
55
LL | | //~^ concrete type differs from previous
66
LL | | (u, t)
77
LL | | }
8-
| |_^
8+
| |_^ expected `(T, T)`, got `(U, T)`
99
|
1010
note: previous use here
1111
--> $DIR/generic_duplicate_param_use6.rs:10:1

0 commit comments

Comments
 (0)