I am trying to improve the Cacher
type described in The Rust Programming Language. One of the improvements suggested states that Cacher
should be usable with many types. To do this, I have written the following code:
struct Cacher<T, U>
where
T: Fn(&U) -> U,
{
calculation: T,
value: Option<U>,
}
impl<T, U> Cacher<T, U>
where
T: Fn(&U) -> U,
{
fn new(calculation: T) -> Cacher<T, U> {
Cacher {
calculation,
value: None,
}
}
fn value(&mut self, arg: &U) -> &U {
match self.value {
Some(v) => &v,
None => {
let v = (self.calculation)(arg);
self.value = Some(v);
&v
}
}
}
}
The compiler complains:
error[E0507]: cannot move out of `self.value.0` which is behind a mutable reference
--> src/lib.rs:21:15
|
21 | match self.value {
| ^^^^^^^^^^ help: consider borrowing here: `&self.value`
22 | Some(v) => &v,
| -
| |
| data moved here
| move occurs because `v` has type `U`, which does not implement the `Copy` trait
error[E0515]: cannot return reference to local variable `v`
--> src/lib.rs:22:24
|
22 | Some(v) => &v,
| ^^ returns a reference to data owned by the current function
error[E0515]: cannot return reference to local variable `v`
--> src/lib.rs:26:17
|
26 | &v
| ^^ returns a reference to data owned by the current function
error[E0382]: borrow of moved value: `v`
--> src/lib.rs:26:17
|
24 | let v = (self.calculation)(arg);
| - move occurs because `v` has type `U`, which does not implement the `Copy` trait
25 | self.value = Some(v);
| - value moved here
26 | &v
| ^^ value borrowed here after move
I imagine this is because v
is local to the function. However, given that the actual data exists within the struct which exists beyond the value
method, is it not possible to return reference to this data in any way? If not this way, then what would I have to do to get the functionality of a Cacher
that owns the calculated data and returns the references whenever required?