So I have some code that looks like this (this is a stand-in for me using a library, so I have to use a lifetime parameter for my struct):
#[derive(Debug)]
struct HelpMe<'a> {
data: &'a [u8],
}
#[derive(Debug)]
struct HelpMeHelper<'a> {
helper: &'a HelpMe<'a>,
}
fn help_me_new<'a>(data: &'a [u8]) -> HelpMeHelper<'a> {
let helper = HelpMe { data: &data };
return HelpMeHelper { helper: &helper };
}
fn help_me() {
let data: Vec<u8> = Vec::new();
let helper = help_me_new(&data);
}
Compiling it gives me this error:
error[E0515]: cannot return value referencing local variable `helper`
--> src/main.rs:237:12
|
237 | return HelpMeHelper { helper: &helper };
| ^^^^^^^^^^^^^^^^^^^^^^^-------^^
| | |
| | `helper` is borrowed here
| returns a value referencing data owned by the current function
Fair enough, I need to provide storage for my data. But how? My immediate attempt is to provide a mutable option:
#[derive(Debug)]
struct HelpMe<'a> {
data: &'a [u8],
}
#[derive(Debug)]
struct HelpMeHelper<'a> {
helper: &'a HelpMe<'a>,
}
fn help_me_new<'a>(data: &'a [u8], opt: &'a mut Option<HelpMe<'a>>) -> HelpMeHelper<'a> {
let new = Some(HelpMe { data: &data });
*opt = new;
return HelpMeHelper { helper: &opt.as_ref().unwrap() };
}
fn print_help_me<'a>(help: &'a HelpMe<'a>) {
println!("option is {:?}", help);
}
fn help_me() {
let data: Vec<u8> = Vec::new();
let mut option = None;
let helper = help_me_new(&data, &mut option);
print_help_me(option.as_ref().unwrap());
}
This gives the error:
error[E0502]: cannot borrow `option` as immutable because it is also borrowed as mutable
--> src/main.rs:249:19
|
248 | let helper = help_me_new(&data, &mut option);
| ----------- mutable borrow occurs here
249 | print_help_me(option.as_ref().unwrap());
| ^^^^^^
| |
| immutable borrow occurs here
| mutable borrow later used here
I can simplify the problem down to this:
struct HelpMe<'a> {
}
fn help_me_new<'a>(_: &'a mut HelpMe<'a>) {
todo!();
}
fn help_me_really<'a>(_: &'a HelpMe<'a>) {
todo!();
}
fn help_me() {
let mut help = HelpMe {};
help_me_new(&mut help);
help_me_really(&help);
}
In my mind this is because there's two lifetimes here: One for mut help and one for the immutable version, but I'm asking for an explicit lifetime. But my intention was to have HelpMe<'a> exist as long as <'a>, not be a specific single lifetime. I know there's subtyping and variance, but either way it's not happening here.
More broadly I'm also not too sure if this is even the right approach? I feel like maybe this is the case for Cell and friends?