.rs
This is the link to the sample repo. I couldn't create a playground because the needed crate is not available on the playground.
I get the following error on line 27.
add explicit lifetime \'a` to the type of `cmds`: `&'a mut bumpalo::collections::Vec<'a, Command<'a>>``
If I do what it is saying me to do. I get more errors in the main function.
\cmds` does not live long enough borrowed value does not live long enough`
What i am trying to do in the action_recursive function is, I am creating a vec which will act like a stack. i will insert all the Commands i have encountered and then do some stuff.
use bumpalo::{collections::Vec, Bump};
enum Command<'a> {
Add(Vec<'a, Command<'a>>),
Sub(Vec<'a, Command<'a>>),
Break,
}
fn main() {
let arena = Bump::new();
let mut cmds = Vec::new_in(&arena);
action(&arena, &mut cmds);
}
fn action<'a>(arena: &'a Bump, cmds: &mut Vec<'a, Command<'a>>) {
let mut cmd_stack = Vec::new_in(arena);
action_recursive(arena, cmds, &mut cmd_stack);
}
fn action_recursive<'a>(
arena: &'a Bump,
cmds: &mut Vec<'a, Command<'a>>,
cmd_stack: &mut Vec<'a, Vec<'a, &Command<'a>>>,
) {
let mut breaks = Vec::new_in(arena);
cmds.iter().for_each(|cmd| {
if matches!(cmd, Command::Break) {
breaks.push(cmd)
}
});
cmd_stack.push(breaks)
}
https://github/Aaditya-23/rust-error/blob/main/src/main.rs
This is the link to the sample repo. I couldn't create a playground because the needed crate is not available on the playground.
I get the following error on line 27.
add explicit lifetime \'a` to the type of `cmds`: `&'a mut bumpalo::collections::Vec<'a, Command<'a>>``
If I do what it is saying me to do. I get more errors in the main function.
\cmds` does not live long enough borrowed value does not live long enough`
What i am trying to do in the action_recursive function is, I am creating a vec which will act like a stack. i will insert all the Commands i have encountered and then do some stuff.
use bumpalo::{collections::Vec, Bump};
enum Command<'a> {
Add(Vec<'a, Command<'a>>),
Sub(Vec<'a, Command<'a>>),
Break,
}
fn main() {
let arena = Bump::new();
let mut cmds = Vec::new_in(&arena);
action(&arena, &mut cmds);
}
fn action<'a>(arena: &'a Bump, cmds: &mut Vec<'a, Command<'a>>) {
let mut cmd_stack = Vec::new_in(arena);
action_recursive(arena, cmds, &mut cmd_stack);
}
fn action_recursive<'a>(
arena: &'a Bump,
cmds: &mut Vec<'a, Command<'a>>,
cmd_stack: &mut Vec<'a, Vec<'a, &Command<'a>>>,
) {
let mut breaks = Vec::new_in(arena);
cmds.iter().for_each(|cmd| {
if matches!(cmd, Command::Break) {
breaks.push(cmd)
}
});
cmd_stack.push(breaks)
}
Share
Improve this question
asked Mar 19 at 18:09
Aadi-23Aadi-23
72 bronze badges
1 Answer
Reset to default 1You've attempted to scatter-shot the lifetimes at action_recursive
to satisfy the compiler. Which to be honest often works, but you have a net of lifetimes that are interconnected and just using 'a
for all of them unfortunately ties them in knots. The big foul is that 'a
on the right-hand side of a &mut
makes it invariant which means the compiler can't manipulate it as well as other contexts.
Often it is better to leave everything as inferred and fill-in the blanks when the compiler get fussy. But the error suggestions here are a bit ambitious so we'll have to use our brains.
Our first link needs to tie the arena
to the breaks
that we are putting in cmd_stack
:
fn action_recursive<'a>(
arena: &'a Bump,
// \------------------------------\
cmds: &'_ mut Vec<'_, Command<'_>>, // |
// v----------/
cmd_stack: &mut Vec<'_, Vec<'a, &'_ Command<'_>>>,
)
Our next link is to bind the lifetime from cmds
to where it is stored in cmd_stack
:
fn action_recursive<'a, 'b>(
arena: &'a Bump,
cmds: &'b mut Vec<'_, Command<'_>>,
// \-------------------------v
cmd_stack: &mut Vec<'_, Vec<'a, &'b Command<'_>>>,
)
And out last link is to simply communicate that the lifetime within the Command
s are the same:
fn action_recursive<'a, 'b, 'c>(
arena: &'a Bump,
cmds: &'b mut Vec<'_, Command<'c>>,
// \-------------v
cmd_stack: &mut Vec<'_, Vec<'a, &'b Command<'c>>>,
)
And you'll find that it compiles.
The key disconnect here is that we don't want the top level Vec<'_, ...>
lifetimes to be bound to arena
. We don't actually care about how long they are using the arena. But the reason it was a problem is that Bumpalo's Vec
requires that the elements outlive the arena:
pub struct Vec<'bump, T: 'bump>
This can still allow the arena to store shorter-lived values, but only if we allow the compiler to shorten the reference to the arena (immutable references are naturally covariant). As mentioned above, if we left those all connected then the arena would be forced to have its original lifetime and thus not allow shorter-lived references within itself.
Note that other arenas may not have this limitation: your code nearly-verbatim mapped converted to the bump-scope crate will compile since there is no link between elements and the arena lifetime there.