Reputation: 662
I am trying to implement a simple trait which returns a reference to some data (GetData
).
For different reasons, I need to implement this trait for reference to my type (&Base<T>
). I also would like to have a wrapper type that owns the base type and implements the trait.
The simplified example looks like this:
// Trait
trait GetData<T> {
fn get_data(&self) -> &T;
}
// Base type
struct Base<T> {
pub data: T,
}
impl<T> GetData<T> for &Base<T> {
fn get_data(&self) -> &T {
&self.data
}
}
// Wrapper type owning a Base type
struct Wrapper<T> {
base: Base<T>,
//...
}
impl<T> GetData<T> for &Wrapper<T> {
fn get_data(&self) -> &T {
(&self.base).get_data() // E0515: returns a value referencing data owned by the current function
//&self.base.data // This works fine!
}
}
When implementing get_data
for a &Wrapper<T>
I get an error of returning a temporary value from my function. As I understand &self.base
is borrowed by GetData::get_data
. I am not sure how to resolve it though. All my attempts to add explicit lifetimes didn't work so far.
Upvotes: 1
Views: 112
Reputation: 42227
The issue is with this:
impl<T> GetData<T> for &Base<T> {
fn get_data(&self) -> &T {
&self.data
}
}
Now in all honesty I've no idea why you'd bother implementing only for &Base
instead of just implementing for Base
. But that's the cause of the issue because the lifetime of the Base and the lifetime of the self are not the same and your self
is an &&Base<T>
.
This means in:
fn get_data(&self) -> &T {
(&self.base).get_data() // E0515: returns a value referencing data owned by the current function
//&self.base.data // This works fine!
}
the lifetime of the result is that of &self.base
which is purely local to the function, instead of being the expected lifetime of self
.
If you
impl<T> GetData<T> for Base<T> {
fn get_data(&self) -> &T {
&self.data
}
}
then everything works out of the box.
Can't help but think the entire thing smells of OO-thinking, a GetData
trait stinks of Java/C# interface.
Upvotes: 2