Repository: rust
Issue: impl for dyn Trait + deref to dyn Trait + Marker unhelpful messages
Labels: A-diagnostics,A-trait-system,T-compiler,D-terse

### Code

```Rust
use std::error::Error;

trait ErrorReport {
    fn report(&self);
}
impl<E: Error + Sized> ErrorReport for E {
    fn report(&self) { /* real impl does something requiring Self: Sized */ }
}
impl ErrorReport for dyn Error /* missing marker traits  + Send + Sync */ {
    fn report(&self) {}
}

trait ErrorReportWithoutBlanket {
    fn report_without_blanket(&self);
}
impl ErrorReportWithoutBlanket for dyn Error /* missing marker traits  + Send + Sync */ {
    fn report_without_blanket(&self) {}
}

#[derive(Debug, thiserror::Error)]
#[error("my error")]
struct MyError;

fn main() {
    MyError.report();
    let ae: anyhow::Error = MyError.into();
    
    // >  error[E0599]: the method `report` exists for trait object `dyn Error + Send + Sync`,
    // >                but its trait bounds were not satisfied
    // this message ^ if you read it carefully does highlight the problem,
    // namely that dyn Error != dyn Error + Send + Sync
    (*ae).report();
    (*ae).report_without_blanket();
    
    // >  error[E0599]: the method `report` exists for struct `Error`,
    // >                but its trait bounds were not satisfied
    // the programmer is hoping to get the method via the deref so this isn't relevant
    //
    // >   ::: /playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/error.rs:32:1
    // >     |
    // > 32  | pub trait Error: Debug + Display {
    // >     | --------------------------------
    // >     | |
    // >     | doesn't satisfy `dyn std::error::Error + Send + Sync: ErrorReport`
    // >     | doesn't satisfy `dyn std::error::Error + Send + Sync: Sized`
    // this is a complaint that the blanket impl isn't relevant:
    // as the programmer can see from the complaint about Sized
    //
    // >   ::: /playground/.cargo/registry/src/index.crates.io-6f17d22bba15001f/anyhow-1.0.75/src/lib.rs:374:1
    // >     |
    // > 374 | pub struct Error {
    // >     | ----------------
    // >     | |
    // >     | doesn't satisfy `anyhow::Error: ErrorReport`
    // >     | doesn't satisfy `anyhow::Error: std::error::Error`
    // >     |
    // > note: the following trait bounds were not satisfied:
    // >       `anyhow::Error: std::error::Error`
    // >       `dyn std::error::Error + Send + Sync: Sized`
    // >    --> src/main.rs:6:6
    // >     |
    // > 6   | impl<E: Error + Sized> ErrorReport for E {
    // >     |      ^  ^^^^^   ^^^^^  -----------     -
    // >     |      |  |       |
    // >     |      |  |       unsatisfied trait bound introduced here
    // >     |      |  unsatisfied trait bound introduced here
    // >     |      unsatisfied trait bound introduced here
    // > help: consider relaxing the type parameter's implicit `Sized` bound
    // >     |
    // > 6   | impl<E: ?Sized + Error + Sized> ErrorReport for E {
    // >     |         ++++++++
    // this is an essay about the same thing.
    //
    // Note there is no message explaining why the impl for dyn Error isn't relevant.
    ae.report();

    // > error[E0599]: no method named `report_without_blanket` found for struct `anyhow::Error` in the current scope
    // >   --> src/main.rs:78:8
    // >    |
    // > 78 |     ae.report_without_blanket();
    // >    |        ^^^^^^^^^^^^^^^^^^^^^^ method not found in `Error`
    // >    |
    // >    = help: items from traits can only be used if the trait is implemented and in scope
    // > note: `ErrorReportWithoutBlanket` defines an item `report_without_blanket`, perhaps you need to implement it
    // >   --> src/main.rs:13:1
    // >    |
    // > 13 | trait ErrorReportWithoutBlanket {
    // >    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    //
    // No mention of the impl for the Deref.
    ae.report_without_blanket();
}
```


### Current output

```Shell
error[E0599]: the method `report` exists for trait object `dyn Error + Send + Sync`, but its trait bounds were not satisfied
  --> src/main.rs:32:11
   |
32 |     (*ae).report();
   |           ^^^^^^ method cannot be called on `dyn Error + Send + Sync` due to unsatisfied trait bounds
   |
  ::: /playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/error.rs:32:1
   |
32 | pub trait Error: Debug + Display {
   | --------------------------------
   | |
   | doesn't satisfy `dyn std::error::Error + Send + Sync: ErrorReport`
   | doesn't satisfy `dyn std::error::Error + Send + Sync: Sized`
   |
note: trait bound `dyn std::error::Error + Send + Sync: Sized` was not satisfied
  --> src/main.rs:6:6
   |
6  | impl<E: Error + Sized> ErrorReport for E {
   |      ^          ^^^^^  -----------     -
   |      |          |
   |      |          unsatisfied trait bound introduced here
   |      unsatisfied trait bound introduced here
help: consider relaxing the type parameter's implicit `Sized` bound
   |
6  | impl<E: ?Sized + Error + Sized> ErrorReport for E {
   |         ++++++++

error[E0599]: no method named `report_without_blanket` found for trait object `(dyn std::error::Error + Send + Sync + 'static)` in the current scope
  --> src/main.rs:33:11
   |
33 |     (*ae).report_without_blanket();
   |           ^^^^^^^^^^^^^^^^^^^^^^ method not found in `dyn Error + Send + Sync`
   |
   = help: items from traits can only be used if the trait is implemented and in scope
note: `ErrorReportWithoutBlanket` defines an item `report_without_blanket`, perhaps you need to implement it
  --> src/main.rs:13:1
   |
13 | trait ErrorReportWithoutBlanket {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0599]: the method `report` exists for struct `Error`, but its trait bounds were not satisfied
   --> src/main.rs:75:8
    |
75  |     ae.report();
    |        ^^^^^^ method cannot be called on `Error` due to unsatisfied trait bounds
    |
   ::: /playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/error.rs:32:1
    |
32  | pub trait Error: Debug + Display {
    | --------------------------------
    | |
    | doesn't satisfy `dyn std::error::Error + Send + Sync: ErrorReport`
    | doesn't satisfy `dyn std::error::Error + Send + Sync: Sized`
    |
   ::: /playground/.cargo/registry/src/index.crates.io-6f17d22bba15001f/anyhow-1.0.75/src/lib.rs:374:1
    |
374 | pub struct Error {
    | ----------------
    | |
    | doesn't satisfy `anyhow::Error: ErrorReport`
    | doesn't satisfy `anyhow::Error: std::error::Error`
    |
note: the following trait bounds were not satisfied:
      `anyhow::Error: std::error::Error`
      `dyn std::error::Error + Send + Sync: Sized`
   --> src/main.rs:6:6
    |
6   | impl<E: Error + Sized> ErrorReport for E {
    |      ^  ^^^^^   ^^^^^  -----------     -
    |      |  |       |
    |      |  |       unsatisfied trait bound introduced here
    |      |  unsatisfied trait bound introduced here
    |      unsatisfied trait bound introduced here
help: consider relaxing the type parameter's implicit `Sized` bound
    |
6   | impl<E: ?Sized + Error + Sized> ErrorReport for E {
    |         ++++++++

error[E0599]: no method named `report_without_blanket` found for struct `anyhow::Error` in the current scope
  --> src/main.rs:91:8
   |
91 |     ae.report_without_blanket();
   |        ^^^^^^^^^^^^^^^^^^^^^^ method not found in `Error`
   |
   = help: items from traits can only be used if the trait is implemented and in scope
note: `ErrorReportWithoutBlanket` defines an item `report_without_blanket`, perhaps you need to implement it
  --> src/main.rs:13:1
   |
13 | trait ErrorReportWithoutBlanket {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```


### Desired output

Additional output should ideally say something like:

```Shell
help: ErrorReport is implemented for dyn Error
      whereas anyhow::Error dereferences to dyn Error + Send + Sync
      which is not the same type.  Perhaps you should change the trait implementation
      or dereference implementation so that the trait bounds match.
```


### Rationale and extra context

Implementing a trait for dyn Trait is a common workaround for various missing affordances.  When this happens in combination with expectations of Deref, it would be nice if the compiler would explain the "near miss".

### Other cases

This near miss logic should probably be applied sparingly to avoid generating a lot of noise from deref chains.  If the miss is purely due to Send/Sync bounds discrepancies, it is probably very relevant.

### Anything else?

Playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=e392d92f7912e5b7db2ff16ee580601a