Misleading suggestions for trait objects in modern rust · Issue #131051 · rust-lang/rust (original) (raw)
Code
trait Foo { fn id(me: T) -> T; }
/* note the "missing" for ... (in this case for i64, in order for this to compile) */ impl Foo { fn id(me: i64) -> i64 {me} }
fn main() { let x: i64 = <i64 as Foo>::id(10); println!("{}",x); }
Current output
error[E0038]: the trait Foo
cannot be made into an object
--> :5:6
|
5 | impl Foo {
| ^^^^^^^^ Foo
cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit https://doc.rust-lang.org/reference/items/traits.html#object-safety
--> :2:8
|
1 | trait Foo {
| --- this trait cannot be made into an object...
2 | fn id(me: T) -> T;
| ^^ ...because associated function id
has no self
parameter
help: consider turning id
into a method by giving it a &self
argument
|
2 | fn id(&self, me: T) -> T;
| ++++++
help: alternatively, consider constraining id
so it does not apply to trait objects
|
2 | fn id(me: T) -> T where Self: Sized;
| +++++++++++++++++
error[E0277]: the trait bound i64: Foo<i64>
is not satisfied
--> :10:19
|
10 | let x: i64 = <i64 as Foo>::id(10);
| ^^^ the trait Foo<i64>
is not implemented for i64
|
help: this trait has no implementations, consider adding one
--> :1:1
|
1 | trait Foo {
| ^^^^^^^^^^^^
error[E0782]: trait objects must include the dyn
keyword
--> :5:6
|
5 | impl Foo {
| ^^^^^^^^
|
help: add dyn
keyword before this trait
|
5 | impl dyn Foo {
| +++
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0038, E0277, E0782.
For more information about an error, try rustc --explain E0038
.
Compiler returned: 1
Desired output
- At least some suggestion that a
for
may be missing (ie to signal an implementation of a trait), instead of only a suggestion around anonymous trait objects, which is somewhat misleading in this case. - The object-safety error would ideally not appear.
Rationale and extra context
The lack of a for ...
here, to implement Foo
for some type, causes two large unrelated errors, both of which are only relevant for code not migrated from Rust 2015. While these are obviously good to keep around, I would think that a suggestion that a for ...
might be missing could also be useful, as it's a very plausible error to make.
Additionally, having the object-safety error come up in a modern rust edition, when it is known that that impl
cannot be for a trait object, seems like it may cause more confusion than it solves. That error is obviously still needed, but for it to be "blocked" behind impl ...
being changed to impl dyn ...
if the Rust edition is >=2018, ensuring the "intentional" presence of a trait object, seems to me like a good approach.
This would be a very easy mistake to make if you were attempting to use Rust traits like Haskell typeclasses because the below compiles and runs fine, due to the lack of implicit self:
class Foo t where id' :: t -> t instance Foo Int where id' x = x main = print (id' (10 :: Int))
Rust Version
rustc 1.81.0 (eeb90cd 2024-09-04)
binary: rustc
commit-hash: eeb90cd
commit-date: 2024-09-04
host: x86_64-unknown-linux-gnu
release: 1.81.0
LLVM version: 18.1.7
Compiler returned: 0