Rust E0499 多次可变借用报错原因咨询
Rust 可变借用冲突问题解答
以下示例代码可在Rust官方playground中运行查看。
第一种无法编译的写法
let c = manager.add_currency(Currency { name: "EUR".to_string(), }); let _i = manager.add_instrument(Instrument { name: "RRR".to_string(), currency: c.clone(), });
对应编译报错:
Compiling playground v0.0.1 (/playground) error[E0499]: cannot borrow `manager` as mutable more than once at a time --> src/main.rs:59:18 | 55 | let c = manager.add_currency(Currency { | _________________- 56 | | name: "EUR".to_string(), 57 | | }); | |__________- first mutable borrow occurs here 58 | 59 | let _i = manager.add_instrument(Instrument { | __________________^ 60 | | name: "RRR".to_string(), 61 | | currency: c.clone(), | | --------- first borrow later used here 62 | | }); | |__________^ second mutable borrow occurs here For more information about this error, try `rustc --explain E0499`. error: could not compile `playground` due to previous error
初始理解修正
你之前的理解存在偏差,报错核心和c是否为Rc引用没有直接关系:
add_currency是接收&mut self的可变方法,当你把它的返回值绑定到变量c时,Rust会判定这次对manager的可变借用生命周期,持续到c最后一次被使用的位置。- 上述代码中
c最后一次使用是在add_instrument调用参数里的c.clone()位置,也就是说第一次可变借用的生命周期覆盖到了第二次调用add_instrument的位置,两次可变借用出现重叠,直接违反了Rust「同一时间只能存在一个可变借用」的规则,因此触发编译错误。
修改后可正常编译的写法
manager.add_currency(Currency { name: "EUR".to_string(), }); let c = manager.get_last_currency(); let _i = manager.add_instrument(Instrument { name: "RRR".to_string(), currency: c.clone(), });
编译通过的原因
你觉得这段代码应该报错,是对借用生命周期的结束位置判定有误解,核心逻辑有两点:
- 第一次调用
add_currency时,你没有将返回值绑定到任何变量,这次可变借用在调用结束的分号位置就立刻终止,不会延续到后续代码。 - 调用
get_last_currency拿到的不可变借用c,它的最后一次使用是c.clone()调用位置:clone()会生成一个和原借用无关的独立值,所有权归当前作用域所有,不再和manager存在关联。当执行到add_instrument调用需要可变借用manager时,之前的不可变借用已经结束,不存在可变借用和不可变借用重叠的情况,完全符合借用规则,因此可以正常编译。
注:当前Rust使用非词法生命周期(NLL)规则判定借用范围,不会死板地以变量所在的花括号作用域作为借用结束边界,而是以值最后一次被使用的位置作为生命周期终止点。
内容的提问来源于stack exchange,提问作者Vaillant Etienne
相关产品推荐
相关产品推荐

