Confusing "Mismatched types" error due to unsatisfied trait bound
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
Code
// #[derive(Clone)] // <- uncomment this to fix it
struct Thing;
fn main() {
message_fn(Message1);
}
fn message_fn<M>(_: M)
where
Thing: HasMessage<M>,
{
unimplemented!()
}
trait HasMessage<T> {}
struct Message1;
impl<M: Clone> HasMessage<Message1> for M {}
struct Message2;
impl<M> HasMessage<Message2> for M {}
Current output
Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
--> src/main.rs:5:16
|
5 | message_fn(Message1);
| ---------- ^^^^^^^^ expected `Message2`, found `Message1`
| |
| arguments to this function are incorrect
|
note: function defined here
--> src/main.rs:8:4
|
8 | fn message_fn<M>(_: M)
| ^^^^^^^^^^ ----
For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` (bin "playground") due to 1 previous error
Desired output
Something mentioning the fact that `Thing` doesn't implement `Clone`.
Rationale and extra context
It's unclear to me why rust decides that the Message2 impl must be the intended impl in main. The intended impl is the Message1 one.
The actual reason the code shouldn't compile is because the author of the code forgot to implement Clone for Thing, which is required for the Message1 impl. However, figuring that out from the error message is difficult, especially in the original code where there are other stuff going on.
Other cases
Adding a Message3 results in a reasonable error
Code and error
// #[derive(Clone)] // <- uncomment this to fix it
struct Thing;
fn main() {
message_fn(Message1);
}
fn message_fn<M>(_: M)
where
Thing: HasMessage<M>,
{
unimplemented!()
}
trait HasMessage<T> {}
struct Message1;
impl<M: Clone> HasMessage<Message1> for M {}
struct Message2;
impl<M> HasMessage<Message2> for M {}
struct Message3;
impl<M> HasMessage<Message3> for M {}
Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `Thing: HasMessage<Message1>` is not satisfied
--> src/main.rs:5:16
|
5 | message_fn(Message1);
| ---------- ^^^^^^^^ the trait `HasMessage<Message1>` is not implemented for `Thing`
| |
| required by a bound introduced by this call
|
note: required for `Thing` to implement `HasMessage<Message1>`
--> src/main.rs:18:16
|
18 | impl<M: Clone> HasMessage<Message1> for M {}
| ----- ^^^^^^^^^^^^^^^^^^^^ ^
| |
| unsatisfied trait bound introduced here
note: required by a bound in `message_fn`
--> src/main.rs:10:12
|
8 | fn message_fn<M>(_: M)
| ---------- required by a bound in this function
9 | where
10 | Thing: HasMessage<M>,
| ^^^^^^^^^^^^^ required by this bound in `message_fn`
help: consider borrowing here
|
5 | message_fn(&Message1);
| +
For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` (bin "playground") due to 1 previous error
Deleting the Message2 also results in a reasonable error
Code and error
// #[derive(Clone)] // <- uncomment this to fix it
struct Thing;
fn main() {
message_fn(Message1);
}
fn message_fn<M>(_: M)
where
Thing: HasMessage<M>,
{
unimplemented!()
}
trait HasMessage<T> {}
struct Message1;
impl<M: Clone> HasMessage<Message1> for M {}
Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `Thing: HasMessage<_>` is not satisfied
--> src/main.rs:5:16
|
5 | message_fn(Message1);
| ---------- ^^^^^^^^ the trait `HasMessage<_>` is not implemented for `Thing`
| |
| required by a bound introduced by this call
|
note: required for `Thing` to implement `HasMessage<Message1>`
--> src/main.rs:18:16
|
18 | impl<M: Clone> HasMessage<Message1> for M {}
| ----- ^^^^^^^^^^^^^^^^^^^^ ^
| |
| unsatisfied trait bound introduced here
note: required by a bound in `message_fn`
--> src/main.rs:10:12
|
8 | fn message_fn<M>(_: M)
| ---------- required by a bound in this function
9 | where
10 | Thing: HasMessage<M>,
| ^^^^^^^^^^^^^ required by this bound in `message_fn`
help: consider borrowing here
|
5 | message_fn(&Message1);
| +
For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` (bin "playground") due to 1 previous error
Rust Version
Playground's nightly rust (1.81.0-nightly (2024-06-17 59e2c01c2217a0154622))
Anything else?
This code is reduced from real code found by @tqwewe
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the example in the Playground's src/main.rs, first with Message2 present and then with it removed or with Message3 added. Compare the diagnostics and trace the compiler's trait-resolution and error-reporting entry points; done means the original case explains the unsatisfied Clone bound without incorrectly reporting Message2 as the expected type.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100