Reputation: 44807
Editor's note: The code presented in the question compiles as-is in Rust 1.0.
I've tried:
trait Inner {}
struct Outer<'a> {
inner: &'a Inner,
}
but the compiler complains:
Compiling tst v0.1.0 (file:///home/chris/rust/tst)
/home/chris/rust/tst/src/main.rs:4:14: 4:19 error: explicit lifetime bound required
/home/chris/rust/tst/src/main.rs:4 inner: &'a Inner,
Upvotes: 1
Views: 4569
Reputation: 128001
How do I tell Rust that I want a struct which contains a reference to something which implements a trait?
There are two ways. First, the preferred one, is to use generics:
struct Outer<'a, T> {
inner: &'a T,
}
impl<'a, T: Inner> Outer<'a, T> {
// ...
}
This method is the most efficient as all function calls are statically dispatched. It's also the most type-safe one, but its disadvantage is that you will have to specify the trait bound everywhere you use Outer<T>
and you won't be able to hold different implementations of Inner
in the same structure at different times because T
must be known in advance.
Another way is to use a trait object:
struct Outer<'a> {
inner: &'a (Inner + 'a),
}
This is what you have already tried, and the error you see is caused by not specifying the lifetime bound: that + 'a
thing. You need to specify a lifetime bound because traits can be implemented for structs with lifetime parameters (like Outer
), and if you box such a structure into a trait object, you need a way to specify its lifetime parameter in trait object type.
The advantage of trait objects is a fewer amount of annotations and the ability to use an arbitrary type as inner
field of the same Outer
value, as long it satisfies Inner
bound. The downside is that you will get dynamic dispatch instead, which may be slightly less efficient. You also wouldn't be able to get back the original type of the trait object without additional machinery.
Upvotes: 6
Reputation: 2217
This is an example of a struct which uses a lifetime specifier.
I had to create a struct with a field that is a reference to the type SWide
. This field needs to be a reference inside the struct, so I added a lifetime specifier to the struct, and also added a lifetime specifier to the impl, notice how you must use the same lifetime specifier twice in the impl line:
extern crate mysql;
use mysql::Pool;
use swide::SWide;
pub struct Context<'a> {
pub connection_pool: Pool,
pub cache: Option<&'a SWide>,
}
impl<'a> Context<'a> {
pub fn new_with_cache(connection_pool: Pool, cache: Option<&'a SWide>) -> Self {
Context {
connection_pool: connection_pool,
cache: cache,
}
}
}
Upvotes: -1