为何从&mut T重借用&T的代码可编译?疑似违反Rust借用规则
为什么这段Rust代码中可变与不可变借用共存却能编译?
先看代码:
let mut a = String::from("abc"); let b = &mut a; let c = &*b; println!("{}", b); println!("{}", c);
按照Rust的常规借用规则,可变引用(&mut T)和不可变引用(&T)通常不能同时存在,预期会触发如下错误:
cannot borrow `a` as immutable because it is also borrowed as mutable
但这段代码却能成功编译,原因在于以下两点:
1. 借用的派生关系,而非独立借用
c并不是直接对原始变量a的不可变借用,而是通过可变引用b派生出来的:&*b本质是对b指向的内容创建不可变引用,属于从可变引用派生不可变引用的场景。
Rust的借用检查器会将这种派生的引用与原可变引用的生命周期绑定,而非视为两个平行的、对a的独立借用——此时不存在“同时对a持有可变和不可变引用”的情况,c的存在依赖于b,而非直接抢占a的借用权。
2. 非 lexical lifetimes (NLL) 的精确分析
Rust 1.31引入的NLL特性,让借用检查器不再仅以变量的作用域为判断依据,而是分析引用的实际使用时机:
- 在这段代码中,
b作为可变引用,在创建c之后仅被用于读取操作(println!("{}", b)是读取它指向的字符串内容,而非修改); c的使用发生在b的读取操作之后,且整个过程中b没有被用于修改数据,NLL能够识别这种场景的安全性,因此允许代码通过编译。
如果尝试在c存在期间修改b(比如*b = String::from("def")),代码就会触发预期的借用错误,因为此时可变引用的修改权限与不可变引用的读取权限产生了冲突。
内容的提问来源于stack exchange,提问作者clon
相关产品推荐
相关产品推荐

