I have a trait Foo
pub trait Foo {
fn do_something(&self) -> f64;
}
and a struct which references that trait
pub struct Bar {
foo: Foo,
}
Trying to compile I get
error: reference to trait `Foo` where a type is expected; try `Box<Foo>` or `&Foo`
Changing the struct to
struct Bar {
foo: &Foo,
}
Tells me error: missing lifetime specifier
Changing the definition to
struct Bar {
foo: Box<Foo>,
}
Compiles — yay!
However, when I want a function to return foo
on bar
- something like:
impl Bar {
fn get_foo(&self) -> Foo {
self.foo
}
}
Well obviously bar.foo
is a Box<Foo>
, so expectedly I get error: reference to trait `Foo` where a type is expected; try `Box<Foo>` or `&Foo`
Changing the signature to
impl Bar {
fn get_foo(&self) -> Box<Foo> {
let this = *self;
this.foo
}
}
But now I get error: cannot move out of dereference of `&`-pointer
on trying to dereference self
.
Changing to
impl Bar {
fn get_foo(self) -> Box<Foo> {
self.foo
}
}
Is all good.
So....
- Why doesn't
&
in thebar
struct work? I'm assuming I have to box as structs have a set memory layout so we have to say it's a pointer to a trait (as we can't know how big that will be), but why does the compiler suggest something that wont compile? - Why can't I dereference
self
inget_foo()
- All examples I've seen use the borrowedself
syntax? - What's the implication of removing the
&
and just usingself
?
Learning Rust is fascinating, but the memory safety is both fascinating and intimidating!
Code in full that compiles:
trait Foo {
fn do_something(&self) -> f64;
}
struct Bar {
foo: Box<Foo>,
}
impl Bar {
fn get_foo(self) -> Box<Foo> {
let foo = self.foo;
foo.do_something();
foo
}
}
fn main() {}