I'm using a library which has the concept of a Context
which has to be initialized before using any other functions. I use that context to create objects to operate with. The context needs to be maintained as long as you're using those objects, so their type ties their lifetime to the Context
. It looks somewhat like this:
struct Thing<'a, 'b> {
aa: &'a i32,
bb: &'b i32,
}
struct Context;
impl Context {
fn init() -> Self {
Context
}
fn thing<'a>(&'a self) -> Thing<'a, 'static> {
// mock function, but it might require reading files or other
// costly operations in order to create the `Thing`
Thing { aa: &9, bb: &10 }
}
}
I want to hold both the Context
and one or more Thing
s. I haven't been able to because creating both in the same function makes it so that I have to borrow Context
, then move it to the struct, which is not allowed.
Is there a way to do this? Maybe a different way to create the Context
so that it's clear it belongs to the struct rather than the function?
struct Friend<'a> {
context: Context,
thing: Thing<'a, 'static>,
}
impl Friend<'_> {
fn new() -> Self {
let context = Context::init();
let thing = context.thing();
Self { context, thing }
}
}
fn main() {
let boy = Friend::new();
println!("value is {}", boy.thing.bb);
}
error[E0515]: cannot return value referencing local variable `context`
--> src/main.rs:28:9
|
27 | let thing = context.thing();
| ------- `context` is borrowed here
28 | Self { context, thing }
| ^^^^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
error[E0505]: cannot move out of `context` because it is borrowed
--> src/main.rs:28:16
|
25 | fn new() -> Self {
| ---- return type is Friend<'1>
26 | let context = Context::init();
27 | let thing = context.thing();
| ------- borrow of `context` occurs here
28 | Self { context, thing }
| -------^^^^^^^---------
| | |
| | move out of `context` occurs here
| returning this value requires that `context` is borrowed for `'1`
In practice, Context
is always going to be part of Friend
, except for those few lines in the constructor function. The move exists because I'm not allowed to initialize the Friend
before I have a Thing
.