Blanket, recursive impls cause bad compiler suggestions
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
Code
use std::cmp::PartialEq;
#[derive(Debug)]
enum MyOption<T> {
Some(T),
None,
}
impl<T, U: PartialEq<T>> PartialEq<Option<T>> for MyOption<U> {
fn eq(&self, other: &Option<T>) -> bool {
match (self, other) {
(MyOption::Some(a), Some(b)) => a == b,
(MyOption::None, None) => true,
_ => false
}
}
}
// This impl causes a worse error message. Comment out the impl to see the ideal one
impl<T: PartialEq<U>, U> PartialEq<MyOption<T>> for Option<U> {
#[inline]
fn eq(&self, other: &MyOption<T>) -> bool {
other.eq(self)
}
}
#[derive(Debug)]
struct S;
fn main() {
// Want: note: an implementation of `PartialEq` might be missing for `S`
// Actual: = note: expected enum `MyOption<_>`
// found enum `Option<S>`
assert_eq!(Some(S), Some(S));
}
Current output
error[E0308]: mismatched types
--> src/main.rs:34:25
|
34 | assert_eq!(Some(S), Some(S));
| ^^^^^^^ expected `MyOption<_>`, found `Option<S>`
|
= note: expected enum `MyOption<_>`
found enum `Option<S>`
help: try wrapping the expression in `MyOption::Some`
|
34 | assert_eq!(Some(S), MyOption::Some(Some(S)));
| +++++++++++++++ +
Desired output
error[E0369]: binary operation `==` cannot be applied to type `Option<S>`
--> src/main.rs:34:5
|
34 | assert_eq!(Some(S), Some(S));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| Option<S>
| Option<S>
|
note: an implementation of `PartialEq` might be missing for `S`
--> src/main.rs:28:1
|
28 | struct S;
| ^^^^^^^^ must implement `PartialEq`
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `S` with `#[derive(PartialEq)]`
|
28 + #[derive(PartialEq)]
29 | struct S;
|
Rationale and extra context
The actual issue in the code is that S does not implement PartialEq, and ideally the error message would tell me to implement PartialEq for S. rustc looks for an implementation of PartialEq on Option<S> and due to the blanket impls for comparing Option and MyOption, it thinks that wrapping in MyOption will resolve it (it won't) and suggests to use MyOption, even though the type MyOption is not used at all on the relevant line.
The MyOption type in the repro is inspired by rkyv::option::ArchivedOption which has this issue in the real world. I have helped several beginners with this exact compile error due to ArchivedOption
Other cases
No response
Rust Version
% rustc --version --verbose
rustc 1.81.0-nightly (cf2df68d1 2024-07-01)
binary: rustc
commit-hash: cf2df68d1f5e56803c97d91e2b1a9f1c9923c533
commit-date: 2024-07-01
host: x86_64-apple-darwin
release: 1.81.0-nightly
LLVM version: 18.1.7
Anything else?
Playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=7a349cc3cb9f841f52b4f07e58501226
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
Start by compiling the minimal reproducer in src/main.rs with the Rust version shown and compare the current and desired diagnostics. Investigate rustc's PartialEq obligation handling and compiler suggestion generation for the recursive blanket implementations. Done means the example reports the missing PartialEq implementation for S without suggesting an unrelated MyOption conversion.
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
- 45/100