Rollup merge of #84014 - estebank:cool-bears-hot-tip, r=varkor

Improve trait/impl method discrepancy errors

* Use more accurate spans
* Clean up some code by removing previous hack
* Provide structured suggestions

Structured suggestions are particularly useful for cases where arbitrary self types are used, like in custom `Future`s, because the way to write `self: Pin<&mut Self>` is not necessarily self-evident when first encountered.
This commit is contained in:
Dylan DPC 2021-04-12 01:04:04 +02:00 committed by GitHub
commit c905e9d0ca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 258 additions and 117 deletions

View file

@ -15,7 +15,10 @@ LL | fn make() -> Self::Ty {
| -------- type in trait
...
LL | fn make() -> u8 { 0 }
| ^^ expected associated type, found `u8`
| ^^
| |
| expected associated type, found `u8`
| help: change the output type to match the trait: `<A<T> as Tr>::Ty`
|
= note: expected fn pointer `fn() -> <A<T> as Tr>::Ty`
found fn pointer `fn() -> u8`
@ -30,7 +33,10 @@ LL | default type Ty = bool;
| ----------------------- expected this associated type
LL |
LL | fn make() -> bool { true }
| ^^^^ expected associated type, found `bool`
| ^^^^
| |
| expected associated type, found `bool`
| help: change the output type to match the trait: `<B<T> as Tr>::Ty`
|
= note: expected fn pointer `fn() -> <B<T> as Tr>::Ty`
found fn pointer `fn() -> bool`

View file

@ -0,0 +1,26 @@
use std::future::Future;
use std::task::{Context, Poll};
fn main() {}
struct MyFuture {}
impl Future for MyFuture {
type Output = ();
fn poll(self, _: &mut Context<'_>) -> Poll<()> {
//~^ ERROR method `poll` has an incompatible type for trait
todo!()
}
}
trait T {
fn foo(self);
fn bar(self) -> Option<()>;
}
impl T for MyFuture {
fn foo(self: Box<Self>) {}
//~^ ERROR method `foo` has an incompatible type for trait
fn bar(self) {}
//~^ ERROR method `bar` has an incompatible type for trait
}

View file

@ -0,0 +1,46 @@
error[E0053]: method `poll` has an incompatible type for trait
--> $DIR/bad-self-type.rs:10:13
|
LL | fn poll(self, _: &mut Context<'_>) -> Poll<()> {
| ^^^^
| |
| expected struct `Pin`, found struct `MyFuture`
| help: change the self-receiver type to match the trait: `self: Pin<&mut MyFuture>`
|
= note: expected fn pointer `fn(Pin<&mut MyFuture>, &mut Context<'_>) -> Poll<_>`
found fn pointer `fn(MyFuture, &mut Context<'_>) -> Poll<_>`
error[E0053]: method `foo` has an incompatible type for trait
--> $DIR/bad-self-type.rs:22:18
|
LL | fn foo(self);
| ---- type in trait
...
LL | fn foo(self: Box<Self>) {}
| ------^^^^^^^^^
| | |
| | expected struct `MyFuture`, found struct `Box`
| help: change the self-receiver type to match the trait: `self`
|
= note: expected fn pointer `fn(MyFuture)`
found fn pointer `fn(Box<MyFuture>)`
error[E0053]: method `bar` has an incompatible type for trait
--> $DIR/bad-self-type.rs:24:18
|
LL | fn bar(self) -> Option<()>;
| ---------- type in trait
...
LL | fn bar(self) {}
| ^ expected enum `Option`, found `()`
|
= note: expected fn pointer `fn(MyFuture) -> Option<()>`
found fn pointer `fn(MyFuture)`
help: change the output type to match the trait
|
LL | fn bar(self) -> Option<()> {}
| ^^^^^^^^^^^^^
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0053`.

View file

@ -5,8 +5,10 @@ LL | fn b<C:Clone,D>(&self, x: C) -> C;
| - type in trait
...
LL | fn b<F:Clone,G>(&self, _x: G) -> G { panic!() }
| - - ^ expected type parameter `F`, found type parameter `G`
| | |
| - - ^
| | | |
| | | expected type parameter `F`, found type parameter `G`
| | | help: change the parameter type to match the trait: `F`
| | found type parameter
| expected type parameter
|

View file

@ -5,8 +5,10 @@ LL | fn foo<A: Debug>(&self, a: &A, b: &impl Debug);
| -- type in trait
...
LL | fn foo<B: Debug>(&self, a: &impl Debug, b: &B) { }
| - ^^^^^^^^^^^ expected type parameter `B`, found type parameter `impl Debug`
| |
| - ^^^^^^^^^^^
| | |
| | expected type parameter `B`, found type parameter `impl Debug`
| | help: change the parameter type to match the trait: `&B`
| expected type parameter
|
= note: expected fn pointer `fn(&(), &B, &impl Debug)`

View file

@ -1,8 +1,11 @@
error[E0053]: method `fmt` has an incompatible type for trait
--> $DIR/trait_type.rs:7:4
--> $DIR/trait_type.rs:7:21
|
LL | fn fmt(&self, x: &str) -> () { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability
| ^^^^
| |
| types differ in mutability
| help: change the parameter type to match the trait: `&mut Formatter<'_>`
|
= note: expected fn pointer `fn(&MyType, &mut Formatter<'_>) -> Result<(), std::fmt::Error>`
found fn pointer `fn(&MyType, &str)`

View file

@ -8,7 +8,7 @@ LL | fn bar(&mut self, other: &dyn Foo) {}
| ^^^^^^^^
| |
| types differ in mutability
| help: consider changing the mutability to match the trait: `&mut dyn Foo`
| help: change the parameter type to match the trait: `&mut dyn Foo`
|
= note: expected fn pointer `fn(&mut Baz, &mut dyn Foo)`
found fn pointer `fn(&mut Baz, &dyn Foo)`

View file

@ -1,33 +1,42 @@
error[E0053]: method `call` has an incompatible type for trait
--> $DIR/issue-20225.rs:6:3
--> $DIR/issue-20225.rs:6:43
|
LL | impl<'a, T> Fn<(&'a T,)> for Foo {
| - this type parameter
LL | extern "rust-call" fn call(&self, (_,): (T,)) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&T`, found type parameter `T`
| ^^^^
| |
| expected `&T`, found type parameter `T`
| help: change the parameter type to match the trait: `(&'a T,)`
|
= note: expected fn pointer `extern "rust-call" fn(&Foo, (&'a T,))`
found fn pointer `extern "rust-call" fn(&Foo, (T,))`
error[E0053]: method `call_mut` has an incompatible type for trait
--> $DIR/issue-20225.rs:11:3
--> $DIR/issue-20225.rs:11:51
|
LL | impl<'a, T> FnMut<(&'a T,)> for Foo {
| - this type parameter
LL | extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&T`, found type parameter `T`
| ^^^^
| |
| expected `&T`, found type parameter `T`
| help: change the parameter type to match the trait: `(&'a T,)`
|
= note: expected fn pointer `extern "rust-call" fn(&mut Foo, (&'a T,))`
found fn pointer `extern "rust-call" fn(&mut Foo, (T,))`
error[E0053]: method `call_once` has an incompatible type for trait
--> $DIR/issue-20225.rs:18:3
--> $DIR/issue-20225.rs:18:47
|
LL | impl<'a, T> FnOnce<(&'a T,)> for Foo {
| - this type parameter
...
LL | extern "rust-call" fn call_once(self, (_,): (T,)) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&T`, found type parameter `T`
| ^^^^
| |
| expected `&T`, found type parameter `T`
| help: change the parameter type to match the trait: `(&'a T,)`
|
= note: expected fn pointer `extern "rust-call" fn(Foo, (&'a T,))`
found fn pointer `extern "rust-call" fn(Foo, (T,))`

View file

@ -1,8 +1,11 @@
error[E0053]: method `next` has an incompatible type for trait
--> $DIR/issue-21332.rs:5:5
--> $DIR/issue-21332.rs:5:27
|
LL | fn next(&mut self) -> Result<i32, i32> { Ok(7) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Option`, found enum `Result`
| ^^^^^^^^^^^^^^^^
| |
| expected enum `Option`, found enum `Result`
| help: change the output type to match the trait: `Option<i32>`
|
= note: expected fn pointer `fn(&mut S) -> Option<i32>`
found fn pointer `fn(&mut S) -> Result<i32, i32>`

View file

@ -5,7 +5,10 @@ LL | fn foo(_: fn(u8) -> ());
| ------------ type in trait
...
LL | fn foo(_: fn(u16) -> ()) {}
| ^^^^^^^^^^^^^ expected `u8`, found `u16`
| ^^^^^^^^^^^^^
| |
| expected `u8`, found `u16`
| help: change the parameter type to match the trait: `fn(u8)`
|
= note: expected fn pointer `fn(fn(u8))`
found fn pointer `fn(fn(u16))`
@ -17,7 +20,10 @@ LL | fn bar(_: Option<u8>);
| ---------- type in trait
...
LL | fn bar(_: Option<u16>) {}
| ^^^^^^^^^^^ expected `u8`, found `u16`
| ^^^^^^^^^^^
| |
| expected `u8`, found `u16`
| help: change the parameter type to match the trait: `Option<u8>`
|
= note: expected fn pointer `fn(Option<u8>)`
found fn pointer `fn(Option<u16>)`
@ -29,7 +35,10 @@ LL | fn baz(_: (u8, u16));
| --------- type in trait
...
LL | fn baz(_: (u16, u16)) {}
| ^^^^^^^^^^ expected `u8`, found `u16`
| ^^^^^^^^^^
| |
| expected `u8`, found `u16`
| help: change the parameter type to match the trait: `(u8, u16)`
|
= note: expected fn pointer `fn((u8, _))`
found fn pointer `fn((u16, _))`
@ -41,7 +50,10 @@ LL | fn qux() -> u8;
| -- type in trait
...
LL | fn qux() -> u16 { 5u16 }
| ^^^ expected `u8`, found `u16`
| ^^^
| |
| expected `u8`, found `u16`
| help: change the output type to match the trait: `u8`
|
= note: expected fn pointer `fn() -> u8`
found fn pointer `fn() -> u16`

View file

@ -5,7 +5,10 @@ LL | fn foo(x: u16);
| --- type in trait
...
LL | fn foo(x: i16) { }
| ^^^ expected `u16`, found `i16`
| ^^^
| |
| expected `u16`, found `i16`
| help: change the parameter type to match the trait: `u16`
|
= note: expected fn pointer `fn(u16)`
found fn pointer `fn(i16)`
@ -20,7 +23,7 @@ LL | fn bar(&mut self) { }
| ^^^^^^^^^
| |
| types differ in mutability
| help: consider changing the mutability to match the trait: `&self`
| help: change the self-receiver type to match the trait: `self: &Bar`
|
= note: expected fn pointer `fn(&Bar)`
found fn pointer `fn(&mut Bar)`

View file

@ -5,7 +5,10 @@ LL | fn foo(x: u16);
| --- type in trait
...
LL | fn foo(x: i16) { }
| ^^^ expected `u16`, found `i16`
| ^^^
| |
| expected `u16`, found `i16`
| help: change the parameter type to match the trait: `u16`
|
= note: expected fn pointer `fn(u16)`
found fn pointer `fn(i16)`
@ -20,7 +23,7 @@ LL | fn bar(&mut self, bar: &Bar) { }
| ^^^^
| |
| types differ in mutability
| help: consider changing the mutability to match the trait: `&mut Bar`
| help: change the parameter type to match the trait: `&mut Bar`
|
= note: expected fn pointer `fn(&mut Bar, &mut Bar)`
found fn pointer `fn(&mut Bar, &Bar)`

View file

@ -1,26 +1,35 @@
error[E0053]: method `mul` has an incompatible type for trait
--> $DIR/wrong-mul-method-signature.rs:16:5
--> $DIR/wrong-mul-method-signature.rs:16:21
|
LL | fn mul(self, s: &f64) -> Vec1 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `f64`, found `&f64`
| ^^^^
| |
| expected `f64`, found `&f64`
| help: change the parameter type to match the trait: `f64`
|
= note: expected fn pointer `fn(Vec1, f64) -> Vec1`
found fn pointer `fn(Vec1, &f64) -> Vec1`
error[E0053]: method `mul` has an incompatible type for trait
--> $DIR/wrong-mul-method-signature.rs:33:5
--> $DIR/wrong-mul-method-signature.rs:33:21
|
LL | fn mul(self, s: f64) -> Vec2 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Vec2`, found `f64`
| ^^^
| |
| expected struct `Vec2`, found `f64`
| help: change the parameter type to match the trait: `Vec2`
|
= note: expected fn pointer `fn(Vec2, Vec2) -> f64`
found fn pointer `fn(Vec2, f64) -> Vec2`
error[E0053]: method `mul` has an incompatible type for trait
--> $DIR/wrong-mul-method-signature.rs:52:5
--> $DIR/wrong-mul-method-signature.rs:52:29
|
LL | fn mul(self, s: f64) -> f64 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `f64`
| ^^^
| |
| expected `i32`, found `f64`
| help: change the output type to match the trait: `i32`
|
= note: expected fn pointer `fn(Vec3, _) -> i32`
found fn pointer `fn(Vec3, _) -> f64`