下面这段代码
let calc_ctx = Bump::new();
let mut it_null = std::iter::empty();
let ds = Digits::new(&calc_ctx, &mut it_null);
let mut it = ds.iter();
// ^^ borrowed value does not live long enough
let ds2 = Digits::new(&calc_ctx, &mut it);
let _ = &ds + &ds2;
编译时会报错,说在ds
的drop
过程中可能会使用指出的那处借用。我自己把代码简化成这样,但并没有报错,有没有大佬帮忙分析一下?
相关的定义列在下面:
pub struct Digits<'a, 'b>(
&'a RefCell<DigitsDatum<'a>>,
DigitsGc<'a>, // 实现了`Drop`,对于`'a`协变
PhantomData<&'b &'a ()>,
);
struct DigitsDatum<'a> {
stream: &'a mut dyn Iterator<Item=i32>,
digits: BVec<'a, i32>, // `BVec`是`bumpalo::collections::Vec`,对于`'a`协变
}
impl<'a, 'b> Digits<'a, 'b> {
fn new(bump: &'a Bump, stream: &'a mut dyn Iterator<Item=i32>) -> Self;
pub fn iter(&'b self) -> DigitsStream<'a, 'b>;
}
unsafe impl<#[may_dangle] 'a, #[may_dangle] 'b> Drop for Digits<'a, 'b> {
fn drop(&mut self) {} // 空实现
}
pub struct DigitsStream<'a, 'b> {
datum: &'b RefCell<DigitsDatum<'a>>,
index: usize,
}
fn add<'a1, 'a2: 'a1, 'b>(self: &'b Digits<'a1, 'b>, other: &'b Digits<'a2, 'b>) -> Digits<'a1, 'b>;
1
共 4 条评论, 1 页
评论区
写评论最终的解决方案是把数据结构设计成这样:
这里所有的生命周期都是协变的,需要内部可变性时用unsafe操作从
NonNull
获取可变引用。op 的标注和永久借用造成的 drop 检查失败
我提取出了能够复现问题的代码片段,这里的
Bump
和BVec
相关的函数类型标记是照着库文档写的,奇怪的是使用这里的演示版本并没有编译错误,但使用bumpalo
库就会出问题。对一个复杂的生命周期问题能复现到多精简,对生命周期的理解就多深入。
没有可复现的代码,所以无法解释你遇到什么问题。
我只看到一个
&'a RefCell<DigitsDatum<'a>>
永久借用,那么它会出现 borrowed value does not live long enough,完全是我意料之中的事情。(没有说这一定是导致你代码出现问题的地方,生命周期标注可能是另一个源头:)