{ fn id(me: i64) -> i64 {me} } fn main() { let x: i64 = ...">

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

  1. 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.
  2. 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