Rust中绕过non-lexical lifetimes限制的unsafe用法是否安全
问题1:代码是否安全,是否为借用检查器的保守限制
你的判断完全正确,这段代码逻辑上100%安全,报错确实是当前非词法生命周期(NLL)实现的保守限制。
当前稳定版Rust的借用检查器还未集成更精准的Polonius借用检查规则,会将ref_to_value的不可变借用生命周期延长到整个函数作用域,哪怕它在修改分支中完全没有被使用。你提到的分支互斥逻辑完全成立:返回ref_to_value的分支不会对thing做任何修改,引用始终有效;走修改分支时ref_to_value已经不会再被访问,不存在同时持有可变+不可变借用的冲突。
问题2:指针洗白的unsafe用法是否安全
你写的这段unsafe用法在当前场景下是完全安全的。
你只是把引用转成原生指针再转回来,没有改变指针指向的内存位置,也没有延长引用的生命周期:返回的引用生命周期依然和输入的&mut Thing生命周期绑定,且返回该引用的分支中不会对thing做任何修改,完全符合unsafe块的安全约定,不存在悬垂引用或别名冲突问题。唯一需要注意的是如果后续修改函数逻辑,在返回该指针前修改了thing的值,才会引入不安全风险,当前代码逻辑下可以放心使用。
问题3:安全Rust的改写方案
有两种符合你约束的实现方案:
- 如果你可以使用nightly版本Rust,只需要在crate根文件添加
#![feature(polonius)]编译选项,无需修改任何代码就能直接编译通过,全程不需要使用unsafe。Polonius是下一代Rust借用检查器,已经可以正确识别你代码中的分支互斥借用逻辑。 - 如果你必须使用稳定版Rust,目前没有纯安全的写法可以同时满足「非修改路径仅调用一次
value()」的约束,要么接受非修改路径调用两次value()的写法,要么使用你提到的unsafe方案。等后续Polonius在稳定版上线后,直接删掉unsafe块就能切换到纯安全实现,不需要修改其他逻辑。
内容的提问来源于stack exchange,提问作者James Fennell
相关产品推荐
相关产品推荐

