Skip to content

Commit 29a66c7

Browse files
committed
Provide more context when an expected type was a type parameter
This becomes particularly confusing when a type parameter has a default. ``` --> $DIR/default-type-parameter.rs:8:17 | LL | fn foo() -> u32 { 0 } | ^^^ expected `()`, found `u32` | note: type in trait --> $DIR/default-type-parameter.rs:2:17 | LL | fn foo() -> T; | ^ = note: expected signature `fn() -> ()` found signature `fn() -> u32` note: expected to match this type parameter --> $DIR/default-type-parameter.rs:1:13 | LL | trait Trait<T = ()> { | ^^^^^^ help: change the output type to match the trait | LL - fn foo() -> u32 { 0 } LL + fn foo() -> () { 0 } ```
1 parent ce69831 commit 29a66c7

8 files changed

Lines changed: 103 additions & 0 deletions

File tree

‎compiler/rustc_hir_analysis/src/check/compare_impl_item.rs‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,6 +1001,9 @@ fn report_trait_method_mismatch<'tcx>(
10011001
impl_trait_ref: ty::TraitRef<'tcx>,
10021002
) -> ErrorGuaranteed {
10031003
let tcx = infcx.tcx;
1004+
let x = cause.code();
1005+
let y = trait_sig.output();
1006+
tracing::info!(?cause, ?x, ?terr, ?trait_m, ?trait_sig, ?y);
10041007
let (impl_err_span, trait_err_span) =
10051008
extract_spans_for_error_reporting(infcx, terr, &cause, impl_m, trait_m);
10061009

@@ -1089,6 +1092,19 @@ fn report_trait_method_mismatch<'tcx>(
10891092
None,
10901093
);
10911094

1095+
if let TypeError::ArgumentSorts(_, i) = &terr
1096+
&& let Some(ty) =
1097+
tcx.fn_sig(trait_m.def_id).skip_binder().inputs_and_output().skip_binder().get(*i)
1098+
&& let ty::Param(param) = ty.kind()
1099+
{
1100+
// The expected type corresponds to a type parameter, which migh thave a default type or
1101+
// have been explicitly set in the `impl` with a different type.
1102+
let generics = tcx.generics_of(trait_m.def_id);
1103+
let param = generics.type_param(*param, tcx);
1104+
let span = tcx.def_span(param.def_id);
1105+
diag.span_note(span, format!("expected to match this type parameter"));
1106+
}
1107+
10921108
diag.emit()
10931109
}
10941110

‎tests/ui/compare-method/bad-self-type.stderr‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ LL | fn foo(self);
2424
| ^^^^
2525
= note: expected signature `fn(MyFuture)`
2626
found signature `fn(Box<MyFuture>)`
27+
note: expected to match this type parameter
28+
--> $DIR/bad-self-type.rs:16:1
29+
|
30+
LL | trait T {
31+
| ^^^^^^^
2732
help: change the self-receiver type to match the trait
2833
|
2934
LL - fn foo(self: Box<Self>) {}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
trait Trait<T = ()> {
2+
fn foo() -> T;
3+
}
4+
5+
struct S;
6+
7+
impl Trait for S {
8+
fn foo() -> u32 { 0 } //~ ERROR
9+
}
10+
impl Trait<i32> for () {
11+
fn foo() -> u32 { 0 } //~ ERROR
12+
}
13+
14+
fn main() {}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
error[E0053]: method `foo` has an incompatible type for trait
2+
--> $DIR/default-type-parameter.rs:8:17
3+
|
4+
LL | fn foo() -> u32 { 0 }
5+
| ^^^ expected `()`, found `u32`
6+
|
7+
note: type in trait
8+
--> $DIR/default-type-parameter.rs:2:17
9+
|
10+
LL | fn foo() -> T;
11+
| ^
12+
= note: expected signature `fn() -> ()`
13+
found signature `fn() -> u32`
14+
note: expected to match this type parameter
15+
--> $DIR/default-type-parameter.rs:1:13
16+
|
17+
LL | trait Trait<T = ()> {
18+
| ^^^^^^
19+
help: change the output type to match the trait
20+
|
21+
LL - fn foo() -> u32 { 0 }
22+
LL + fn foo() -> () { 0 }
23+
|
24+
25+
error[E0053]: method `foo` has an incompatible type for trait
26+
--> $DIR/default-type-parameter.rs:11:17
27+
|
28+
LL | fn foo() -> u32 { 0 }
29+
| ^^^ expected `i32`, found `u32`
30+
|
31+
note: type in trait
32+
--> $DIR/default-type-parameter.rs:2:17
33+
|
34+
LL | fn foo() -> T;
35+
| ^
36+
= note: expected signature `fn() -> i32`
37+
found signature `fn() -> u32`
38+
note: expected to match this type parameter
39+
--> $DIR/default-type-parameter.rs:1:13
40+
|
41+
LL | trait Trait<T = ()> {
42+
| ^^^^^^
43+
help: change the output type to match the trait
44+
|
45+
LL - fn foo() -> u32 { 0 }
46+
LL + fn foo() -> i32 { 0 }
47+
|
48+
49+
error: aborting due to 2 previous errors
50+
51+
For more information about this error, try `rustc --explain E0053`.

‎tests/ui/compare-method/issue-90444.stderr‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ LL | fn from(_: fn((), (), u64)) -> Self {
2020
|
2121
= note: expected signature `fn(fn((), (), u32)) -> B`
2222
found signature `fn(fn((), (), u64)) -> B`
23+
note: expected to match this type parameter
24+
--> $SRC_DIR/core/src/convert/mod.rs:LL:COL
2325
help: change the parameter type to match the trait
2426
|
2527
LL - fn from(_: fn((), (), u64)) -> Self {

‎tests/ui/compare-method/reordered-type-param.stderr‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ LL | fn b<C:Clone,D>(&self, x: C) -> C;
1616
found signature `fn(&E, G) -> G`
1717
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
1818
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
19+
note: expected to match this type parameter
20+
--> $DIR/reordered-type-param.rs:7:8
21+
|
22+
LL | fn b<C:Clone,D>(&self, x: C) -> C;
23+
| ^
1924
help: change the parameter type to match the trait
2025
|
2126
LL - fn b<F:Clone,G>(&self, _x: G) -> G { panic!() }

‎tests/ui/fn_traits/fn-impl-mismatched-param-type.stderr‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ LL | extern "rust-call" fn call(&self, (_,): (T,)) {}
88
|
99
= note: expected signature `extern "rust-call" fn(&Foo, (&'a _,))`
1010
found signature `extern "rust-call" fn(&Foo, (_,))`
11+
note: expected to match this type parameter
12+
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
1113
help: change the parameter type to match the trait
1214
|
1315
LL | extern "rust-call" fn call(&self, (_,): (&'a T,)) {}
@@ -23,6 +25,8 @@ LL | extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {}
2325
|
2426
= note: expected signature `extern "rust-call" fn(&mut Foo, (&'a _,))`
2527
found signature `extern "rust-call" fn(&mut Foo, (_,))`
28+
note: expected to match this type parameter
29+
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
2630
help: change the parameter type to match the trait
2731
|
2832
LL | extern "rust-call" fn call_mut(&mut self, (_,): (&'a T,)) {}
@@ -39,6 +43,8 @@ LL | extern "rust-call" fn call_once(self, (_,): (T,)) {}
3943
|
4044
= note: expected signature `extern "rust-call" fn(Foo, (&'a _,))`
4145
found signature `extern "rust-call" fn(Foo, (_,))`
46+
note: expected to match this type parameter
47+
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
4248
help: change the parameter type to match the trait
4349
|
4450
LL | extern "rust-call" fn call_once(self, (_,): (&'a T,)) {}

‎tests/ui/traits/wrong-mul-method-signature.stderr‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ LL | fn mul(self, s: &f64) -> Vec1 {
66
|
77
= note: expected signature `fn(Vec1, _) -> Vec1`
88
found signature `fn(Vec1, &_) -> Vec1`
9+
note: expected to match this type parameter
10+
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
911
help: change the parameter type to match the trait
1012
|
1113
LL - fn mul(self, s: &f64) -> Vec1 {
@@ -20,6 +22,8 @@ LL | fn mul(self, s: f64) -> Vec2 {
2022
|
2123
= note: expected signature `fn(Vec2, Vec2) -> f64`
2224
found signature `fn(Vec2, f64) -> Vec2`
25+
note: expected to match this type parameter
26+
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
2327
help: change the parameter type to match the trait
2428
|
2529
LL - fn mul(self, s: f64) -> Vec2 {

0 commit comments

Comments
 (0)