rust-lang / rust-lang/rust

Use supertrait as the suggested bound for a blanket impl instead of the bounds from a different blanket impl

Open
#118,415 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-diagnostics A-trait-system D-confusing T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Code
trait A: B {
    fn a();
}

trait B {
    fn b();
}

trait C {}

impl<T> B for T
where
    T: C,
{
    fn b() {}
}

impl<T> A for T {
    fn a(){
        Self::b();
    }
}
Current output
error[E0277]: the trait bound `T: C` is not satisfied
  --> src/main.rs:18:15
   |
18 | impl<T> A for T {
   |               ^ the trait `C` is not implemented for `T`
   |
note: required for `T` to implement `B`
  --> src/main.rs:11:9
   |
11 | impl<T> B for T
   |         ^     ^
12 | where
13 |     T: C,
   |        - unsatisfied trait bound introduced here
note: required by a bound in `A`
  --> src/main.rs:1:10
   |
1  | trait A: B {
   |          ^ required by this bound in `A`
help: consider restricting type parameter `T`
   |
18 | impl<T: C> A for T {
   |       +++

For more information about this error, try `rustc --explain E0277`.
Desired output
error[E0277]: the trait bound `T: B` is not satisfied
  --> src/main.rs:18:15
   |
18 | impl<T> A for T {
   |               ^ the trait `B` is not implemented for `T`
   |
note: required by a bound in `A`
  --> src/main.rs:1:10
   |
1  | trait A: B {
   |          ^ required by this bound in `A`
help: consider restricting type parameter `T`
   |
18 | impl<T: B> A for T {
   |       +++

For more information about this error, try `rustc --explain E0277`.
Rationale and extra context

When providing a blanket impl for some trait A with a supertrait B, and B also has a blanket impl bounded on some other trait C, rustc will suggest bounding A's blanket impl on C rather than the supertrait B. This is a little confusing and likely the incorrect bound to suggest, as it would cause types that directly implement B to not satisfy the blanket impl for A, like the following example:

...

impl<T: C> A for T {
    fn a(){
        Self::b();
    }
}

struct D;

impl C for D {}

struct E;

impl B for E {
    fn b() {}
}

pub fn main() {
    D::a();
    E::a(); // error: method cannot be called on `E` due to unsatisfied trait bounds
}

This works as expected if T: B is specified as the bound for the blanket impl on A instead.

playground link

Other cases

No response

Anything else?

No response

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 reproducing the minimal Rust example or the linked Playground case and compare rustc's current E0277 output with the desired diagnostic. Trace the compiler's handling of this trait-bound suggestion, add a regression test for the blanket-impl and supertrait case, and verify that the suggested bound is B rather than C.

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
Clearly specified
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.