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

0 commit comments

Comments
 (0)