Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
sfleener opened this issue Nov 28, 2023 · 1 comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-traits Area: Trait system D-confusing Diagnostics: Confusing error or lint that should be reworked. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@sfleener
Copy link

sfleener commented Nov 28, 2023

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

@sfleener sfleener added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Nov 28, 2023
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Nov 28, 2023
@fmease fmease added A-traits Area: Trait system D-confusing Diagnostics: Confusing error or lint that should be reworked. and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Jan 23, 2024
@fmease
Copy link
Member

fmease commented Jan 23, 2024

CC rust-lang/rfcs#2397 & #51992 (#[do_not_recommend]).

estebank added a commit to estebank/rust that referenced this issue Mar 1, 2024
When encountering trait bound errors that satisfy some heuristics that
tell us that the relevant trait for the user comes from the root
obligation and not the current obligation, we use the root predicate for
the main message.

This allows to talk about "X doesn't implement Pattern<'_>" over the
most specific case that just happened to fail, like  "char doesn't
implement Fn(&mut char)" in
`tests/ui/traits/suggest-dereferences/root-obligation.rs`

The heuristics are:

 - the type of the leaf predicate is (roughly) the same as the type
   from the root predicate, as a proxy for "we care about the root"
 - the leaf trait and the root trait are different, so as to avoid
   talking about `&mut T: Trait` and instead remain talking about
   `T: Trait` instead
 - the root trait is not `Unsize`, as to avoid talking about it in
   `tests/ui/coercion/coerce-issue-49593-box-never.rs`.

```
error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied
  --> $DIR/root-obligation.rs:6:38
   |
LL |         .filter(|c| "aeiou".contains(c))
   |                             -------- ^ the trait `Fn<(char,)>` is not implemented for `&char`, which is required by `&char: Pattern<'_>`
   |                             |
   |                             required by a bound introduced by this call
   |
   = note: required for `&char` to implement `FnOnce<(char,)>`
   = note: required for `&char` to implement `Pattern<'_>`
note: required by a bound in `core::str::<impl str>::contains`
  --> $SRC_DIR/core/src/str/mod.rs:LL:COL
help: consider dereferencing here
   |
LL |         .filter(|c| "aeiou".contains(*c))
   |                                      +
```

Fix rust-lang#79359, fix rust-lang#119983, fix rust-lang#118779, cc rust-lang#118415 (the suggestion needs
to change).
estebank added a commit to estebank/rust that referenced this issue Mar 1, 2024
When encountering trait bound errors that satisfy some heuristics that
tell us that the relevant trait for the user comes from the root
obligation and not the current obligation, we use the root predicate for
the main message.

This allows to talk about "X doesn't implement Pattern<'_>" over the
most specific case that just happened to fail, like  "char doesn't
implement Fn(&mut char)" in
`tests/ui/traits/suggest-dereferences/root-obligation.rs`

The heuristics are:

 - the type of the leaf predicate is (roughly) the same as the type
   from the root predicate, as a proxy for "we care about the root"
 - the leaf trait and the root trait are different, so as to avoid
   talking about `&mut T: Trait` and instead remain talking about
   `T: Trait` instead
 - the root trait is not `Unsize`, as to avoid talking about it in
   `tests/ui/coercion/coerce-issue-49593-box-never.rs`.

```
error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied
  --> $DIR/root-obligation.rs:6:38
   |
LL |         .filter(|c| "aeiou".contains(c))
   |                             -------- ^ the trait `Fn<(char,)>` is not implemented for `&char`, which is required by `&char: Pattern<'_>`
   |                             |
   |                             required by a bound introduced by this call
   |
   = note: required for `&char` to implement `FnOnce<(char,)>`
   = note: required for `&char` to implement `Pattern<'_>`
note: required by a bound in `core::str::<impl str>::contains`
  --> $SRC_DIR/core/src/str/mod.rs:LL:COL
help: consider dereferencing here
   |
LL |         .filter(|c| "aeiou".contains(*c))
   |                                      +
```

Fix rust-lang#79359, fix rust-lang#119983, fix rust-lang#118779, cc rust-lang#118415 (the suggestion needs
to change).
estebank added a commit to estebank/rust that referenced this issue Mar 1, 2024
When encountering trait bound errors that satisfy some heuristics that
tell us that the relevant trait for the user comes from the root
obligation and not the current obligation, we use the root predicate for
the main message.

This allows to talk about "X doesn't implement Pattern<'_>" over the
most specific case that just happened to fail, like  "char doesn't
implement Fn(&mut char)" in
`tests/ui/traits/suggest-dereferences/root-obligation.rs`

The heuristics are:

 - the type of the leaf predicate is (roughly) the same as the type
   from the root predicate, as a proxy for "we care about the root"
 - the leaf trait and the root trait are different, so as to avoid
   talking about `&mut T: Trait` and instead remain talking about
   `T: Trait` instead
 - the root trait is not `Unsize`, as to avoid talking about it in
   `tests/ui/coercion/coerce-issue-49593-box-never.rs`.

```
error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied
  --> $DIR/root-obligation.rs:6:38
   |
LL |         .filter(|c| "aeiou".contains(c))
   |                             -------- ^ the trait `Fn<(char,)>` is not implemented for `&char`, which is required by `&char: Pattern<'_>`
   |                             |
   |                             required by a bound introduced by this call
   |
   = note: required for `&char` to implement `FnOnce<(char,)>`
   = note: required for `&char` to implement `Pattern<'_>`
note: required by a bound in `core::str::<impl str>::contains`
  --> $SRC_DIR/core/src/str/mod.rs:LL:COL
help: consider dereferencing here
   |
LL |         .filter(|c| "aeiou".contains(*c))
   |                                      +
```

Fix rust-lang#79359, fix rust-lang#119983, fix rust-lang#118779, cc rust-lang#118415 (the suggestion needs
to change).
estebank added a commit to estebank/rust that referenced this issue Mar 1, 2024
When encountering trait bound errors that satisfy some heuristics that
tell us that the relevant trait for the user comes from the root
obligation and not the current obligation, we use the root predicate for
the main message.

This allows to talk about "X doesn't implement Pattern<'_>" over the
most specific case that just happened to fail, like  "char doesn't
implement Fn(&mut char)" in
`tests/ui/traits/suggest-dereferences/root-obligation.rs`

The heuristics are:

 - the type of the leaf predicate is (roughly) the same as the type
   from the root predicate, as a proxy for "we care about the root"
 - the leaf trait and the root trait are different, so as to avoid
   talking about `&mut T: Trait` and instead remain talking about
   `T: Trait` instead
 - the root trait is not `Unsize`, as to avoid talking about it in
   `tests/ui/coercion/coerce-issue-49593-box-never.rs`.

```
error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied
  --> $DIR/root-obligation.rs:6:38
   |
LL |         .filter(|c| "aeiou".contains(c))
   |                             -------- ^ the trait `Fn<(char,)>` is not implemented for `&char`, which is required by `&char: Pattern<'_>`
   |                             |
   |                             required by a bound introduced by this call
   |
   = note: required for `&char` to implement `FnOnce<(char,)>`
   = note: required for `&char` to implement `Pattern<'_>`
note: required by a bound in `core::str::<impl str>::contains`
  --> $SRC_DIR/core/src/str/mod.rs:LL:COL
help: consider dereferencing here
   |
LL |         .filter(|c| "aeiou".contains(*c))
   |                                      +
```

Fix rust-lang#79359, fix rust-lang#119983, fix rust-lang#118779, cc rust-lang#118415 (the suggestion needs
to change).
estebank added a commit to estebank/rust that referenced this issue Mar 1, 2024
When encountering trait bound errors that satisfy some heuristics that
tell us that the relevant trait for the user comes from the root
obligation and not the current obligation, we use the root predicate for
the main message.

This allows to talk about "X doesn't implement Pattern<'_>" over the
most specific case that just happened to fail, like  "char doesn't
implement Fn(&mut char)" in
`tests/ui/traits/suggest-dereferences/root-obligation.rs`

The heuristics are:

 - the type of the leaf predicate is (roughly) the same as the type
   from the root predicate, as a proxy for "we care about the root"
 - the leaf trait and the root trait are different, so as to avoid
   talking about `&mut T: Trait` and instead remain talking about
   `T: Trait` instead
 - the root trait is not `Unsize`, as to avoid talking about it in
   `tests/ui/coercion/coerce-issue-49593-box-never.rs`.

```
error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied
  --> $DIR/root-obligation.rs:6:38
   |
LL |         .filter(|c| "aeiou".contains(c))
   |                             -------- ^ the trait `Fn<(char,)>` is not implemented for `&char`, which is required by `&char: Pattern<'_>`
   |                             |
   |                             required by a bound introduced by this call
   |
   = note: required for `&char` to implement `FnOnce<(char,)>`
   = note: required for `&char` to implement `Pattern<'_>`
note: required by a bound in `core::str::<impl str>::contains`
  --> $SRC_DIR/core/src/str/mod.rs:LL:COL
help: consider dereferencing here
   |
LL |         .filter(|c| "aeiou".contains(*c))
   |                                      +
```

Fix rust-lang#79359, fix rust-lang#119983, fix rust-lang#118779, cc rust-lang#118415 (the suggestion needs
to change).
estebank added a commit to estebank/rust that referenced this issue Mar 3, 2024
When encountering trait bound errors that satisfy some heuristics that
tell us that the relevant trait for the user comes from the root
obligation and not the current obligation, we use the root predicate for
the main message.

This allows to talk about "X doesn't implement Pattern<'_>" over the
most specific case that just happened to fail, like  "char doesn't
implement Fn(&mut char)" in
`tests/ui/traits/suggest-dereferences/root-obligation.rs`

The heuristics are:

 - the type of the leaf predicate is (roughly) the same as the type
   from the root predicate, as a proxy for "we care about the root"
 - the leaf trait and the root trait are different, so as to avoid
   talking about `&mut T: Trait` and instead remain talking about
   `T: Trait` instead
 - the root trait is not `Unsize`, as to avoid talking about it in
   `tests/ui/coercion/coerce-issue-49593-box-never.rs`.

```
error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied
  --> $DIR/root-obligation.rs:6:38
   |
LL |         .filter(|c| "aeiou".contains(c))
   |                             -------- ^ the trait `Fn<(char,)>` is not implemented for `&char`, which is required by `&char: Pattern<'_>`
   |                             |
   |                             required by a bound introduced by this call
   |
   = note: required for `&char` to implement `FnOnce<(char,)>`
   = note: required for `&char` to implement `Pattern<'_>`
note: required by a bound in `core::str::<impl str>::contains`
  --> $SRC_DIR/core/src/str/mod.rs:LL:COL
help: consider dereferencing here
   |
LL |         .filter(|c| "aeiou".contains(*c))
   |                                      +
```

Fix rust-lang#79359, fix rust-lang#119983, fix rust-lang#118779, cc rust-lang#118415 (the suggestion needs
to change).
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Mar 4, 2024
…r=oli-obk

Use root obligation on E0277 for some cases

When encountering trait bound errors that satisfy some heuristics that tell us that the relevant trait for the user comes from the root obligation and not the current obligation, we use the root predicate for the main message.

This allows to talk about "X doesn't implement Pattern<'_>" over the most specific case that just happened to fail, like  "char doesn't implement Fn(&mut char)" in
`tests/ui/traits/suggest-dereferences/root-obligation.rs`

The heuristics are:

 - the type of the leaf predicate is (roughly) the same as the type from the root predicate, as a proxy for "we care about the root"
 - the leaf trait and the root trait are different, so as to avoid talking about `&mut T: Trait` and instead remain talking about `T: Trait` instead
 - the root trait is not `Unsize`, as to avoid talking about it in `tests/ui/coercion/coerce-issue-49593-box-never.rs`.

```
error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied
  --> $DIR/root-obligation.rs:6:38
   |
LL |         .filter(|c| "aeiou".contains(c))
   |                             -------- ^ the trait `Fn<(char,)>` is not implemented for `&char`, which is required by `&char: Pattern<'_>`
   |                             |
   |                             required by a bound introduced by this call
   |
   = note: required for `&char` to implement `FnOnce<(char,)>`
   = note: required for `&char` to implement `Pattern<'_>`
note: required by a bound in `core::str::<impl str>::contains`
  --> $SRC_DIR/core/src/str/mod.rs:LL:COL
help: consider dereferencing here
   |
LL |         .filter(|c| "aeiou".contains(*c))
   |                                      +
```

Fix rust-lang#79359, fix rust-lang#119983, fix rust-lang#118779, cc rust-lang#118415 (the suggestion needs to change), cc rust-lang#121398 (doesn't fix the underlying issue).
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Mar 5, 2024
…r=oli-obk

Use root obligation on E0277 for some cases

When encountering trait bound errors that satisfy some heuristics that tell us that the relevant trait for the user comes from the root obligation and not the current obligation, we use the root predicate for the main message.

This allows to talk about "X doesn't implement Pattern<'_>" over the most specific case that just happened to fail, like  "char doesn't implement Fn(&mut char)" in
`tests/ui/traits/suggest-dereferences/root-obligation.rs`

The heuristics are:

 - the type of the leaf predicate is (roughly) the same as the type from the root predicate, as a proxy for "we care about the root"
 - the leaf trait and the root trait are different, so as to avoid talking about `&mut T: Trait` and instead remain talking about `T: Trait` instead
 - the root trait is not `Unsize`, as to avoid talking about it in `tests/ui/coercion/coerce-issue-49593-box-never.rs`.

```
error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied
  --> $DIR/root-obligation.rs:6:38
   |
LL |         .filter(|c| "aeiou".contains(c))
   |                             -------- ^ the trait `Fn<(char,)>` is not implemented for `&char`, which is required by `&char: Pattern<'_>`
   |                             |
   |                             required by a bound introduced by this call
   |
   = note: required for `&char` to implement `FnOnce<(char,)>`
   = note: required for `&char` to implement `Pattern<'_>`
note: required by a bound in `core::str::<impl str>::contains`
  --> $SRC_DIR/core/src/str/mod.rs:LL:COL
help: consider dereferencing here
   |
LL |         .filter(|c| "aeiou".contains(*c))
   |                                      +
```

Fix rust-lang#79359, fix rust-lang#119983, fix rust-lang#118779, cc rust-lang#118415 (the suggestion needs to change), cc rust-lang#121398 (doesn't fix the underlying issue).
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Mar 5, 2024
…r=oli-obk

Use root obligation on E0277 for some cases

When encountering trait bound errors that satisfy some heuristics that tell us that the relevant trait for the user comes from the root obligation and not the current obligation, we use the root predicate for the main message.

This allows to talk about "X doesn't implement Pattern<'_>" over the most specific case that just happened to fail, like  "char doesn't implement Fn(&mut char)" in
`tests/ui/traits/suggest-dereferences/root-obligation.rs`

The heuristics are:

 - the type of the leaf predicate is (roughly) the same as the type from the root predicate, as a proxy for "we care about the root"
 - the leaf trait and the root trait are different, so as to avoid talking about `&mut T: Trait` and instead remain talking about `T: Trait` instead
 - the root trait is not `Unsize`, as to avoid talking about it in `tests/ui/coercion/coerce-issue-49593-box-never.rs`.

```
error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied
  --> $DIR/root-obligation.rs:6:38
   |
LL |         .filter(|c| "aeiou".contains(c))
   |                             -------- ^ the trait `Fn<(char,)>` is not implemented for `&char`, which is required by `&char: Pattern<'_>`
   |                             |
   |                             required by a bound introduced by this call
   |
   = note: required for `&char` to implement `FnOnce<(char,)>`
   = note: required for `&char` to implement `Pattern<'_>`
note: required by a bound in `core::str::<impl str>::contains`
  --> $SRC_DIR/core/src/str/mod.rs:LL:COL
help: consider dereferencing here
   |
LL |         .filter(|c| "aeiou".contains(*c))
   |                                      +
```

Fix rust-lang#79359, fix rust-lang#119983, fix rust-lang#118779, cc rust-lang#118415 (the suggestion needs to change), cc rust-lang#121398 (doesn't fix the underlying issue).
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Mar 5, 2024
Rollup merge of rust-lang#121826 - estebank:e0277-root-obligation-2, r=oli-obk

Use root obligation on E0277 for some cases

When encountering trait bound errors that satisfy some heuristics that tell us that the relevant trait for the user comes from the root obligation and not the current obligation, we use the root predicate for the main message.

This allows to talk about "X doesn't implement Pattern<'_>" over the most specific case that just happened to fail, like  "char doesn't implement Fn(&mut char)" in
`tests/ui/traits/suggest-dereferences/root-obligation.rs`

The heuristics are:

 - the type of the leaf predicate is (roughly) the same as the type from the root predicate, as a proxy for "we care about the root"
 - the leaf trait and the root trait are different, so as to avoid talking about `&mut T: Trait` and instead remain talking about `T: Trait` instead
 - the root trait is not `Unsize`, as to avoid talking about it in `tests/ui/coercion/coerce-issue-49593-box-never.rs`.

```
error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied
  --> $DIR/root-obligation.rs:6:38
   |
LL |         .filter(|c| "aeiou".contains(c))
   |                             -------- ^ the trait `Fn<(char,)>` is not implemented for `&char`, which is required by `&char: Pattern<'_>`
   |                             |
   |                             required by a bound introduced by this call
   |
   = note: required for `&char` to implement `FnOnce<(char,)>`
   = note: required for `&char` to implement `Pattern<'_>`
note: required by a bound in `core::str::<impl str>::contains`
  --> $SRC_DIR/core/src/str/mod.rs:LL:COL
help: consider dereferencing here
   |
LL |         .filter(|c| "aeiou".contains(*c))
   |                                      +
```

Fix rust-lang#79359, fix rust-lang#119983, fix rust-lang#118779, cc rust-lang#118415 (the suggestion needs to change), cc rust-lang#121398 (doesn't fix the underlying issue).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-traits Area: Trait system D-confusing Diagnostics: Confusing error or lint that should be reworked. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants