如何为Bumpalo Arena多参数标注生命周期?编译报错求助
Rust中Bumpalo Arena结合生命周期的报错修复
问题场景
我尝试用Bumpalo Arena分配所有对象,在action_recursive函数里创建一个Vec作为栈,存储遍历到的所有Command::Break实例。原代码如下:
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) }
报错情况
- 初始报错(第27行):
add explicit lifetime `'a` to the type of `cmds`: `&'a mut bumpalo::collections::Vec<'a, Command<'a>>`
- 按照提示给
cmds添加'a生命周期后,main函数出现新报错:
`cmds` does not live long enough borrowed value does not live long enough
问题根源
- 初始报错是因为Rust无法推导
cmds的引用生命周期与'a(arena的生命周期)的关系,强制指定'a后,相当于要求cmds的引用必须和arena存活时间一样久。 - 但
cmds是main函数栈上的局部变量,生命周期比arena短(arena也是main栈变量,但cmds创建更晚、销毁更早),因此违反了生命周期约束。
修复方案
核心是分离arena的生命周期与引用的生命周期,不需要让cmds的引用绑定到arena的生命周期'a。调整函数的生命周期参数,明确不同引用的生命周期范围:
- 给
action_recursive添加额外的生命周期'b,并指定'a: 'b(保证arena分配的Command生命周期足够覆盖引用的生命周期)。 - 修改
cmd_stack的类型,让存储的引用生命周期匹配cmds的引用生命周期'b,而Vec本身仍在arena('a)中分配。
修复后完整代码
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, 'b>( arena: &'a Bump, cmds: &'b mut Vec<'a, Command<'a>>, cmd_stack: &mut Vec<'a, Vec<'b, &'b Command<'a>>>, ) where 'a: 'b { let mut breaks = Vec::new_in(arena); cmds.iter().for_each(|cmd| { if matches!(cmd, Command::Break) { breaks.push(cmd) } }); cmd_stack.push(breaks) }
关键修改说明
- 新增生命周期
'b,用于标记cmds的引用生命周期,where 'a: 'b确保arena中的Command(生命周期'a)比cmds的引用('b)存活更久,避免悬垂引用。 cmd_stack的类型从Vec<'a, Vec<'a, &Command<'a>>>改为Vec<'a, Vec<'b, &'b Command<'a>>>,明确存储的引用是指向cmds中存活'b时间的Command实例,而外层Vec仍由arena分配。
内容的提问来源于stack exchange,提问作者Aadi-23
相关产品推荐
相关产品推荐

