Editor's note: This code example is from a version of Rust prior to 1.0 and is not syntactically valid Rust 1.0 code. Updated versions of this code produce different errors, but the answers still contain valuable information.
I tried this with and without Box
, with and without lifetimes:
trait TraitToImpl {
fn do_something(self, val: i32);
}
struct Cont {
value: i32,
}
impl TraitToImpl for Cont {
fn do_something(self, val: i32) {
println!("{}", val);
}
}
struct StoreTrait<'a> {
field: Box<TraitToImpl + 'a>,
}
fn main() {
let cont = Box::new(Cont { value: 12 }) as Box<TraitToImpl>;
let a = StoreTrait { field: cont };
a.field.do_something(123);
}
All I get is this error:
error: cannot convert to a trait object because trait `TraitToImpl` is not object-safe
The problem is, as the error message says, that the trait TraitToImpl
is not object safe. That is, it is not safe to use that particular trait through a reference (i.e. &TraitToImpl
or Box<TraitToImpl>
.
Specifically, the do_something
method takes self
by value. Consider: how does the compiler call this method on a Cont
that's been placed in a Box<TraitToImpl>
? It has to copy the value into an argument of type Cont
(which is what the impl
expects), but this call has to work for any type of any size that might implement TraitToImpl
!
Practical upshot: if you have a trait which contains by-value self
, or generics, it cannot be used via a reference. At the point the call happens, the compiler no longer has enough information to actually generate the necessary code.
Maybe try taking &self
instead? :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With