I'm trying to make two structs that operate on an underlying dataset; one providing immutable "read" operations, the other allowing modification. For this to work, I need to be able to use the read functions from within the modifying object - as such I create a temporary new read object within the modifier function with a view onto the underlying data.
Here's some code:
struct Read<'db> {
x: &'db i32
}
impl<'db> Read<'db> {
pub fn get(&'db self) -> &'db i32 { self.x }
}
struct Write<'db> {
x: &'db mut i32
}
impl<'db> Write<'db> {
fn new(x: &mut i32) -> Write { Write{x: x} }
fn as_read(&'db self) -> Read<'db> {
Read{x: self.x}
}
pub fn get(&'db self) -> &'db i32 { self.as_read().get() }
}
fn main() {
let mut x = 69i32;
let y = Write::new(&mut x);
println!("{}", y.get());
}
It doesn't compile - it seems that despite my best efforts, the lifetime of the reference returned from Read::get
is bound to the Write::get
's scope, rather than the Write
's 'db
lifetime. How can I make it compile? (And, is what I want to do possible? Is it the simplest/most concise way of doing it?)
The point the compiler is trying to get across is that &'db self
actually means self: &'db Write<'db>
. This means that you tie the reference AND the type to the same lifetime. What you actually want in your case is self: &'a Write<'db>
where 'a
lives just for the as_read
function. To be able to return a 'db
reference from a 'a
reference, you need to specify that 'a
lives at least as long as 'db
by constraining 'a: 'db
.
fn as_read<'a: 'db>(self: &'a Write<'db>) -> Read<'db> {
Read{x: self.x}
}
pub fn get<'a: 'db>(self: &'a Write<'db>) -> &'db i32 { self.as_read().get() }
or more concisely
fn as_read<'a: 'db>(&'a self) -> Read<'db> {
Read{x: self.x}
}
pub fn get<'a: 'db>(&'a self) -> &'db i32 { self.as_read().get() }
Try it out in the Playground
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