Repository: rust
Issue: Undetailed diagnostics for object safety of supertraits defined in dependencies
Labels: A-diagnostics,A-trait-system,T-compiler,D-terse

<!--
Thank you for filing a bug report! 🐛 Please provide a short summary of the bug,
along with any information you feel relevant to replicating the bug.

If you cannot produce a minimal reproduction case (something that would work in
isolation), please provide the steps or even link to a repository that causes
the problematic output to occur.
-->

Currently, the diagnostics for object safety are not very good if the object safety issue is caused by a trait defined outside the current crate, as it just points that some supertrait is not object safe and doesn't explain why from there. It's possible to argue that the current way this works is correct and that exposing implementation details of your libraries is a bad idea, but it's not necessarily good for teaching the user that object safety is not some magic.

Given the following code: also at https://github.com/lf-/object-safety-issue

`cargo new --lib v`
`v/src/lib.rs`:
```rust
pub trait T0: Clone {}
pub trait T1: T0 {}
```

`Cargo.toml`:
```toml
[package]
name = "play-si1zd_4v"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
v = {path = "./v"}
```

`src/main.rs`:
```rust
trait T2: v::T1 {
    fn a(self) -> u32;
}

#[derive(Clone)]
struct S;

impl v::T0 for S {}
impl v::T1 for S {}
impl T2 for S {
    fn a(self) -> u32 {
        4
    }
}

fn f(a: Box<dyn T2>) {}
fn main() {}
```

The current output is:

```
error[E0038]: the trait `T2` cannot be made into an object
  --> src/main.rs:16:9
   |
16 | fn f(a: Box<dyn T2>) {}
   |         ^^^^^^^^^^^ `T2` cannot be made into an object
   |
note: for a trait to be "object safe" it needs to allow building a vtable to allow the c
all to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/
reference/items/traits.html#object-safety>
  --> src/main.rs:1:11
   |
1  | trait T2: v::T1 {
   |       --  ^^^^^ ...because it requires `Self: Sized`
   |       |
   |       this trait cannot be made into an object...

error: aborting due to previous error

For more information about this error, try `rustc --explain E0038`.
error: could not compile `play-si1zd_4v`
```

<!-- The following is not always necessary. -->
Ideally the output should look like:

```
error[E0038]: the trait `T2` cannot be made into an object
  --> src/main.rs:16:9
   |
16 | fn f(a: Box<dyn T2>) {}
   |         ^^^^^^^^^^^ `T2` cannot be made into an object
   |
note: for a trait to be "object safe" it needs to allow building a vtable to allow the c
all to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/
reference/items/traits.html#object-safety>
note: because of requirement `T2: T1`
note: because of requirement `T1: T0`
note: because of requirement `T0: Clone`
note: because of requirement `Clone: Sized`
  --> src/main.rs:1:11
   |
1  | trait T2: v::T1 {
   |       --  ^^^^^ ...because it requires `Self: Sized`
   |       |
   |       this trait cannot be made into an object...

error: aborting due to previous error

For more information about this error, try `rustc --explain E0038`.
error: could not compile `play-si1zd_4v`
```

<!--
If the problem is not self-explanatory, please provide a rationale for the
change.
-->

<!--
If dramatically different output is caused by small changes, consider also
adding them here.

If you're using the stable version of the compiler, you should also check if the
bug also exists in the beta or nightly versions. The output might also be
different depending on the Edition.
-->

Filed based on nightly 2021-07-08.

If the traits are all declared in the same crate, the error is *much* better and points further along to the cause, although it *still* does not say that `Clone: Sized`, so you'd have to read the rustdocs or source to figure that out.

`src/main.rs`
```rust
mod v {
    pub trait T0: Clone {}
    pub trait T1: T0 {}
}

trait T2: v::T1 {
    fn a(self) -> u32;
}

#[derive(Clone)]
struct S;

impl v::T0 for S {}
impl v::T1 for S {}
impl T2 for S {
    fn a(self) -> u32 {
        4
    }
}

fn f(a: Box<dyn T2>) {}
```


```
error[E0038]: the trait `T2` cannot be made into an object
  --> src/main.rs:21:9
   |
21 | fn f(a: Box<dyn T2>) {}
   |         ^^^^^^^^^^^ `T2` cannot be made into an object
   |
note: for a trait to be "object safe" it needs to allow building a vtable to allow the c
all to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/
reference/items/traits.html#object-safety>
  --> src/main.rs:2:19
   |
2  |     pub trait T0: Clone {}
   |                   ^^^^^ ...because it requires `Self: Sized`
3  |     pub trait T1: T0 {}
   |                   ^^ ...because it requires `Self: Sized`
...
6  | trait T2: v::T1 {
   |       --  ^^^^^ ...because it requires `Self: Sized`
   |       |
   |       this trait cannot be made into an object...

error: aborting due to previous error

For more information about this error, try `rustc --explain E0038`.
error: could not compile `play-si1zd_4v`

To learn more, run the command again with --verbose.
```