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:
pub trait T0: Clone {}
pub trait T1: T0 {}
Cargo.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:
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`
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`
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
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.
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 vv/src/lib.rs:Cargo.toml:src/main.rs:The current output is:
Ideally the output should look like:
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