Skip to content

Commit 13fee42

Browse files
authored
Rollup merge of #63907 - estebank:assoc-type-mismatch, r=oli-obk
Add explanation to type mismatch involving type params and assoc types CC #63711
2 parents ed8b708 + 479ce39 commit 13fee42

27 files changed

+181
-23
lines changed

src/librustc/traits/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -659,11 +659,11 @@ pub struct VtableTraitAliasData<'tcx, N> {
659659
}
660660

661661
/// Creates predicate obligations from the generic bounds.
662-
pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
663-
param_env: ty::ParamEnv<'tcx>,
664-
generic_bounds: &ty::InstantiatedPredicates<'tcx>)
665-
-> PredicateObligations<'tcx>
666-
{
662+
pub fn predicates_for_generics<'tcx>(
663+
cause: ObligationCause<'tcx>,
664+
param_env: ty::ParamEnv<'tcx>,
665+
generic_bounds: &ty::InstantiatedPredicates<'tcx>,
666+
) -> PredicateObligations<'tcx> {
667667
util::predicates_for_generics(cause, 0, param_env, generic_bounds)
668668
}
669669

src/librustc/traits/util.rs

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -513,20 +513,19 @@ pub fn impl_trait_ref_and_oblig<'a, 'tcx>(
513513
}
514514

515515
/// See [`super::obligations_for_generics`].
516-
pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
517-
recursion_depth: usize,
518-
param_env: ty::ParamEnv<'tcx>,
519-
generic_bounds: &ty::InstantiatedPredicates<'tcx>)
520-
-> Vec<PredicateObligation<'tcx>>
521-
{
522-
debug!("predicates_for_generics(generic_bounds={:?})",
523-
generic_bounds);
524-
525-
generic_bounds.predicates.iter().map(|predicate| {
526-
Obligation { cause: cause.clone(),
527-
recursion_depth,
528-
param_env,
529-
predicate: predicate.clone() }
516+
pub fn predicates_for_generics<'tcx>(
517+
cause: ObligationCause<'tcx>,
518+
recursion_depth: usize,
519+
param_env: ty::ParamEnv<'tcx>,
520+
generic_bounds: &ty::InstantiatedPredicates<'tcx>,
521+
) -> Vec<PredicateObligation<'tcx>> {
522+
debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds);
523+
524+
generic_bounds.predicates.iter().map(|predicate| Obligation {
525+
cause: cause.clone(),
526+
recursion_depth,
527+
param_env,
528+
predicate: predicate.clone(),
530529
}).collect()
531530
}
532531

src/librustc/ty/error.rs

Lines changed: 92 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -275,10 +275,10 @@ impl<'tcx> TyCtxt<'tcx> {
275275
`.await`ing on both of them");
276276
}
277277
}
278-
if let (ty::Infer(ty::IntVar(_)), ty::Float(_)) =
279-
(&values.found.sty, &values.expected.sty) // Issue #53280
280-
{
281-
if let Ok(snippet) = self.sess.source_map().span_to_snippet(sp) {
278+
match (&values.expected.sty, &values.found.sty) {
279+
(ty::Float(_), ty::Infer(ty::IntVar(_))) => if let Ok( // Issue #53280
280+
snippet,
281+
) = self.sess.source_map().span_to_snippet(sp) {
282282
if snippet.chars().all(|c| c.is_digit(10) || c == '-' || c == '_') {
283283
db.span_suggestion(
284284
sp,
@@ -287,8 +287,96 @@ impl<'tcx> TyCtxt<'tcx> {
287287
Applicability::MachineApplicable
288288
);
289289
}
290+
},
291+
(ty::Param(_), ty::Param(_)) => {
292+
db.note("a type parameter was expected, but a different one was found; \
293+
you might be missing a type parameter or trait bound");
294+
db.note("for more information, visit \
295+
https://doc.rust-lang.org/book/ch10-02-traits.html\
296+
#traits-as-parameters");
297+
}
298+
(ty::Projection(_), ty::Projection(_)) => {
299+
db.note("an associated type was expected, but a different one was found");
300+
}
301+
(ty::Param(_), ty::Projection(_)) | (ty::Projection(_), ty::Param(_)) => {
302+
db.note("you might be missing a type parameter or trait bound");
303+
}
304+
(ty::Param(_), _) | (_, ty::Param(_)) => {
305+
db.help("type parameters must be constrained to match other types");
306+
if self.sess.teach(&db.get_code().unwrap()) {
307+
db.help("given a type parameter `T` and a method `foo`:
308+
```
309+
trait Trait<T> { fn foo(&self) -> T; }
310+
```
311+
the only ways to implement method `foo` are:
312+
- constrain `T` with an explicit type:
313+
```
314+
impl Trait<String> for X {
315+
fn foo(&self) -> String { String::new() }
316+
}
317+
```
318+
- add a trait bound to `T` and call a method on that trait that returns `Self`:
319+
```
320+
impl<T: std::default::Default> Trait<T> for X {
321+
fn foo(&self) -> T { <T as std::default::Default>::default() }
322+
}
323+
```
324+
- change `foo` to return an argument of type `T`:
325+
```
326+
impl<T> Trait<T> for X {
327+
fn foo(&self, x: T) -> T { x }
328+
}
329+
```");
330+
}
331+
db.note("for more information, visit \
332+
https://doc.rust-lang.org/book/ch10-02-traits.html\
333+
#traits-as-parameters");
334+
}
335+
(ty::Projection(_), _) => {
336+
db.note(&format!(
337+
"consider constraining the associated type `{}` to `{}` or calling a \
338+
method that returns `{}`",
339+
values.expected,
340+
values.found,
341+
values.expected,
342+
));
343+
if self.sess.teach(&db.get_code().unwrap()) {
344+
db.help("given an associated type `T` and a method `foo`:
345+
```
346+
trait Trait {
347+
type T;
348+
fn foo(&self) -> Self::T;
349+
}
350+
```
351+
the only way of implementing method `foo` is to constrain `T` with an explicit associated type:
352+
```
353+
impl Trait for X {
354+
type T = String;
355+
fn foo(&self) -> Self::T { String::new() }
356+
}
357+
```");
358+
}
359+
db.note("for more information, visit \
360+
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html");
361+
}
362+
(_, ty::Projection(_)) => {
363+
db.note(&format!(
364+
"consider constraining the associated type `{}` to `{}`",
365+
values.found,
366+
values.expected,
367+
));
368+
db.note("for more information, visit \
369+
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html");
290370
}
371+
_ => {}
291372
}
373+
debug!(
374+
"note_and_explain_type_err expected={:?} ({:?}) found={:?} ({:?})",
375+
values.expected,
376+
values.expected.sty,
377+
values.found,
378+
values.found.sty,
379+
);
292380
},
293381
CyclicTy(ty) => {
294382
// Watch out for various cases of cyclic types and try to explain.

src/test/ui/associated-const/associated-const-generic-obligations.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ LL | const FROM: &'static str = "foo";
99
|
1010
= note: expected type `<T as Foo>::Out`
1111
found type `&'static str`
12+
= note: consider constraining the associated type `<T as Foo>::Out` to `&'static str` or calling a method that returns `<T as Foo>::Out`
13+
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
1214

1315
error: aborting due to previous error
1416

src/test/ui/associated-types/associated-types-eq-3.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ LL | let _: Bar = x.boo();
66
|
77
= note: expected type `Bar`
88
found type `<I as Foo>::A`
9+
= note: consider constraining the associated type `<I as Foo>::A` to `Bar`
10+
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
911

1012
error[E0271]: type mismatch resolving `<isize as Foo>::A == Bar`
1113
--> $DIR/associated-types-eq-3.rs:38:5

src/test/ui/associated-types/associated-types-issue-20346.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ LL | is_iterator_of::<Option<T>, _>(&adapter);
99
|
1010
= note: expected type `T`
1111
found type `std::option::Option<T>`
12+
= help: type parameters must be constrained to match other types
13+
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
1214

1315
error: aborting due to previous error
1416

src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ LL | fn want_y<T:Foo<Y=i32>>(t: &T) { }
99
|
1010
= note: expected type `<T as Foo>::Y`
1111
found type `i32`
12+
= note: consider constraining the associated type `<T as Foo>::Y` to `i32` or calling a method that returns `<T as Foo>::Y`
13+
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
1214

1315
error[E0271]: type mismatch resolving `<T as Foo>::X == u32`
1416
--> $DIR/associated-types-multiple-types-one-trait.rs:18:5
@@ -21,6 +23,8 @@ LL | fn want_x<T:Foo<X=u32>>(t: &T) { }
2123
|
2224
= note: expected type `<T as Foo>::X`
2325
found type `u32`
26+
= note: consider constraining the associated type `<T as Foo>::X` to `u32` or calling a method that returns `<T as Foo>::X`
27+
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
2428

2529
error: aborting due to 2 previous errors
2630

src/test/ui/compare-method/reordered-type-param.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ LL | fn b<F:Clone,G>(&self, _x: G) -> G { panic!() }
99
|
1010
= note: expected type `fn(&E, F) -> F`
1111
found type `fn(&E, G) -> G`
12+
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
13+
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
1214

1315
error: aborting due to previous error
1416

src/test/ui/hrtb/issue-62203-hrtb-ice.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ LL | let v = Unit2.m(
66
|
77
= note: expected type `Unit4`
88
found type `<_ as Ty<'_>>::V`
9+
= note: consider constraining the associated type `<_ as Ty<'_>>::V` to `Unit4`
10+
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
911

1012
error[E0271]: type mismatch resolving `<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39] as std::ops::FnOnce<((&u8,),)>>::Output == Unit3`
1113
--> $DIR/issue-62203-hrtb-ice.rs:38:19

src/test/ui/impl-trait/bound-normalization-fail.stderr

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ LL | fn foo_fail<T: Trait>() -> impl FooLike<Output=T::Assoc> {
1414
|
1515
= note: expected type `()`
1616
found type `<T as impl_trait::Trait>::Assoc`
17+
= note: consider constraining the associated type `<T as impl_trait::Trait>::Assoc` to `()`
18+
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
1719
= note: the return type of a function must have a statically known size
1820

1921
error: `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
@@ -30,6 +32,8 @@ LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> {
3032
|
3133
= note: expected type `()`
3234
found type `<T as lifetimes::Trait<'static>>::Assoc`
35+
= note: consider constraining the associated type `<T as lifetimes::Trait<'static>>::Assoc` to `()`
36+
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
3337
= note: the return type of a function must have a statically known size
3438

3539
error: aborting due to 3 previous errors

src/test/ui/impl-trait/equality2.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ LL | let _: i32 = Leak::leak(hide(0_i32));
1515
|
1616
= note: expected type `i32`
1717
found type `<impl Foo as Leak>::T`
18+
= note: consider constraining the associated type `<impl Foo as Leak>::T` to `i32`
19+
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
1820

1921
error[E0308]: mismatched types
2022
--> $DIR/equality2.rs:38:10

src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ LL | fn foo<B: Debug>(&self, a: &impl Debug, b: &B) { }
99
|
1010
= note: expected type `fn(&(), &B, &impl Debug)`
1111
found type `fn(&(), &impl Debug, &B)`
12+
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
13+
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
1214

1315
error: aborting due to previous error
1416

src/test/ui/impl-trait/universal-mismatched-type.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ LL | x
88
|
99
= note: expected type `std::string::String`
1010
found type `impl Debug`
11+
= help: type parameters must be constrained to match other types
12+
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
1113

1214
error: aborting due to previous error
1315

src/test/ui/impl-trait/universal-two-impl-traits.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ LL | a = y;
66
|
77
= note: expected type `impl Debug` (type parameter)
88
found type `impl Debug` (type parameter)
9+
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
10+
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
911

1012
error: aborting due to previous error
1113

src/test/ui/issues/issue-13853.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ LL | self.iter()
99
|
1010
= note: expected type `I`
1111
found type `std::slice::Iter<'_, N>`
12+
= help: type parameters must be constrained to match other types
13+
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
1214

1315
error[E0599]: no method named `iter` found for type `&G` in the current scope
1416
--> $DIR/issue-13853.rs:27:23

src/test/ui/issues/issue-20225.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ LL | extern "rust-call" fn call(&self, (_,): (T,)) {}
66
|
77
= note: expected type `extern "rust-call" fn(&Foo, (&'a T,))`
88
found type `extern "rust-call" fn(&Foo, (T,))`
9+
= help: type parameters must be constrained to match other types
10+
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
911

1012
error[E0053]: method `call_mut` has an incompatible type for trait
1113
--> $DIR/issue-20225.rs:12:3
@@ -15,6 +17,8 @@ LL | extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {}
1517
|
1618
= note: expected type `extern "rust-call" fn(&mut Foo, (&'a T,))`
1719
found type `extern "rust-call" fn(&mut Foo, (T,))`
20+
= help: type parameters must be constrained to match other types
21+
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
1822

1923
error[E0053]: method `call_once` has an incompatible type for trait
2024
--> $DIR/issue-20225.rs:20:3
@@ -24,6 +28,8 @@ LL | extern "rust-call" fn call_once(self, (_,): (T,)) {}
2428
|
2529
= note: expected type `extern "rust-call" fn(Foo, (&'a T,))`
2630
found type `extern "rust-call" fn(Foo, (T,))`
31+
= help: type parameters must be constrained to match other types
32+
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
2733

2834
error: aborting due to 3 previous errors
2935

src/test/ui/issues/issue-24204.stderr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ LL | fn test<T: Trait<B=i32>>(b: i32) -> T where T::A: MultiDispatch<i32> { T::n
99
|
1010
= note: expected type `<<T as Trait>::A as MultiDispatch<i32>>::O`
1111
found type `T`
12+
= note: you might be missing a type parameter or trait bound
1213

1314
error: aborting due to previous error
1415

src/test/ui/issues/issue-2951.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ LL | xx = y;
66
|
77
= note: expected type `T`
88
found type `U`
9+
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
10+
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
911

1012
error: aborting due to previous error
1113

src/test/ui/issues/issue-32323.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ LL | pub fn f<'a, T: Tr<'a>>() -> <T as Tr<'a>>::Out {}
88
|
99
= note: expected type `<T as Tr<'a>>::Out`
1010
found type `()`
11+
= note: consider constraining the associated type `<T as Tr<'a>>::Out` to `()` or calling a method that returns `<T as Tr<'a>>::Out`
12+
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
1113

1214
error: aborting due to previous error
1315

src/test/ui/mismatched_types/issue-35030.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ LL | Some(true)
66
|
77
= note: expected type `bool` (type parameter)
88
found type `bool` (bool)
9+
= help: type parameters must be constrained to match other types
10+
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
911

1012
error: aborting due to previous error
1113

src/test/ui/specialization/specialization-default-projection.stderr

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ LL | ()
99
|
1010
= note: expected type `<T as Foo>::Assoc`
1111
found type `()`
12+
= note: consider constraining the associated type `<T as Foo>::Assoc` to `()` or calling a method that returns `<T as Foo>::Assoc`
13+
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
1214

1315
error[E0308]: mismatched types
1416
--> $DIR/specialization-default-projection.rs:28:5
@@ -23,6 +25,8 @@ LL | generic::<()>()
2325
|
2426
= note: expected type `()`
2527
found type `<() as Foo>::Assoc`
28+
= note: consider constraining the associated type `<() as Foo>::Assoc` to `()`
29+
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
2630

2731
error: aborting due to 2 previous errors
2832

src/test/ui/specialization/specialization-default-types.stderr

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ LL | Box::new(self)
88
|
99
= note: expected type `<T as Example>::Output`
1010
found type `std::boxed::Box<T>`
11+
= note: consider constraining the associated type `<T as Example>::Output` to `std::boxed::Box<T>` or calling a method that returns `<T as Example>::Output`
12+
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
1113

1214
error[E0308]: mismatched types
1315
--> $DIR/specialization-default-types.rs:25:5
@@ -19,6 +21,8 @@ LL | Example::generate(t)
1921
|
2022
= note: expected type `std::boxed::Box<T>`
2123
found type `<T as Example>::Output`
24+
= note: consider constraining the associated type `<T as Example>::Output` to `std::boxed::Box<T>`
25+
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
2226

2327
error: aborting due to 2 previous errors
2428

0 commit comments

Comments
 (0)