rust-lang / rust-lang/rust

Blanket, recursive impls cause bad compiler suggestions

Open
#127,247 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-diagnostics T-compiler
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.