什么时候延长 Arenas 引用的生命周期是安全的?

cut*_*lus 2 unsafe lifetime rust

我有一个使用的结构Arena

struct Foo<'f> {
    a: Arena<u64>, // from the typed-arena crate
    v: Vec<&'f u64>,
}
Run Code Online (Sandbox Code Playgroud)

只要引用的生命周期受主结构体生命周期的约束,延长竞技场引用的生命周期是否安全?

impl<'f> Foo<'f> {
    pub fn bar(&mut self, n: u64) -> Option<&'f u64> {
        if n == 0 {
            None
        } else {
            let n_ref = unsafe { std::mem::transmute(self.a.alloc(n)) };
            Some(n_ref)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

有关更多背景信息,请参阅此Reddit 评论

Pet*_*all 5

\n

只要引用的生命周期受主结构体生命周期的约束,延长竞技场引用的生命周期是否安全?

\n
\n\n

原则上,这Arena将被删除,这是安全的,但也是不必要的,因为它已经活得足够长了。FooArena

\n\n

然而,这并不是您的代码实际所做的!生命周期\'f可能比 struct \xe2\x80\x94 的生命周期更长,它可以与 中最短生命周期的引用一样长v。例如:

\n\n
fn main() {\n    let n = 1u64;\n    let v = vec![&n];\n    let bar;\n    {\n        let mut foo = Foo { a: Arena::new(), v };\n        bar = foo.bar(2);\n        // foo is dropped here, along with the Arena\n    }\n    // bar is still useable here because \'f is the full scope of `n`\n    println!("bar = {:?}", bar); // Some(8021790808186446178) - oops!\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

试图假装生命周期比实际长,这为安全代码中的未定义行为创造了机会。

\n\n
\n\n

一个可能的解决方法是拥有 的Arena外部struct并依靠借用检查器来确保它在仍在使用时不会被丢弃:

\n\n
struct Foo<\'f> {\n    a: &\'f Arena<u64>,\n    v: Vec<&\'f u64>,\n}\n\nimpl<\'f> Foo<\'f> {\n    pub bar(&mut self, n: u64) -> Option<&\'f u64> {\n        if n == 0 {\n            None\n        } else {\n            Some(self.a.alloc(n))\n        }\n    }\n}\n\nfn main() {\n    let arena = Arena::new();\n    let n = 1u64;\n    let v = vec![&n];\n    let bar;\n    {\n        let mut foo = Foo { a: &arena, v };\n        bar = foo.bar(2);\n    }\n    println!("bar = {:?}", bar); // Some(2)\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

就像您的不安全版本一样,生命周期表示对 的引用Arena必须至少与 中的项目一样长有效Vec。不过,这也证实了这个事实是真的!由于不存在不安全代码,您可以相信借用检查器这不会触发 UB。

\n