为什么Rust编译器报多重可变引用错误而非悬垂引用错误?
核心原因
你对可变引用重借用(reborrow)的生命周期绑定逻辑存在误解,重借用的生命周期并非天生被限制在函数调用内部,而是由函数签名的生命周期标注决定,只要父借用(原始的可变引用)的生命周期足够支撑,重借用的生命周期可以延伸到函数调用之外,不会产生悬垂引用。
具体推导过程
你的函数签名如下:
fn my_fun<'b>(x: &'b mut String, y: &'b mut String) -> &'b mut String { y }
这里两个入参、返回值都绑定了同一个生命周期'b,调用my_fun(aa, &mut b)时,编译器会做如下生命周期推导:
- 返回值
c的生命周期是'b,而c在第8行println!中才被使用,因此'b的长度至少要覆盖从函数调用到第8行结束的范围。 - 第一个入参
x是对aa的重借用,它的生命周期也被绑定为'b,这就要求aa本身对a的可变借用必须持续生效到'b结束(也就是第8行)。 - 第7行你尝试再次对
a做可变借用,此时上一个aa的借用还没结束,自然触发E0499多重可变引用错误,整个过程中没有引用超出作用域的情况,所以不会报悬垂引用错误。
验证方案
你可以修改函数签名,将两个入参的生命周期拆分:
fn my_fun<'x, 'b>(x: &'x mut String, y: &'b mut String) -> &'b mut String { y }
修改后重新编译就不会报错了:此时x的生命周期'x和返回值的'b没有关联,重借用x的生命周期只需要覆盖函数调用本身即可,调用结束后aa对a的借用就自动释放,第7行再借a完全符合规则。
内容的提问来源于stack exchange,提问作者raj
相关产品推荐
相关产品推荐

