Rust中为什么while let Some()=xxx循环结束后tail仍处于被借用状态
问题原因分析
这个问题本质是Rust借用检查器对不同借用路径的生命周期推断精度差异导致的,和临时借用的作用域判定规则直接相关:
三种写法的核心差异在于可变借用的来源:
- 第一种
while tail.is_some()的写法:每次循环内的as_mut()产生的可变借用仅作用于当前循环体,当你把&mut tail.as_mut().unwrap().next赋值给tail后,旧的tail对应的借用会被NLL(非词法生命周期)判定为不再使用,自动释放,因此循环结束后没有残留的未释放借用,后续对*tail的赋值合法。 - 第二种
while let Some(ref mut node) = tail的写法:直接对tail本身做模式匹配拆出可变引用,借用检查器可以准确识别到每次给tail赋新值后,旧的借用已经没有持有者,生命周期自动结束,循环结束后tail的借用状态是合法可修改的。 - 第三种报错的
while let Some(node) = tail.as_mut()的写法:首先调用tail.as_mut()会对*tail产生一个临时可变借用,这个借用的生命周期会和你后续赋值给tail的&mut node.next绑定在一起,当前版本的借用检查器无法推断出循环结束后这个衍生借用已经不再和最初的as_mut()借用冲突,因此会判定*tail仍然处于被借用状态,禁止直接修改。
这个属于当前借用检查器的已知局限性,它对于跨循环、通过方法调用(比如as_mut())衍生的借用生命周期的收缩判定,精度低于直接模式匹配的场景,实际开发中优先用第二种写法即可避开这个问题。
内容的提问来源于stack exchange,提问作者Svetlin Zarev
相关产品推荐
相关产品推荐

