为何在闭包中使用可变引用时未发生重借用?
Rust闭包与可变引用的借用冲突解析
先看这段可以正常编译的代码:
fn bar<T>(v: &mut Vec<T>) { bar(v); // 重借用 bar(v); // 重借用 }
这段代码能通过编译,因为每次调用bar(v)都是临时的重借用,调用结束后借用就归还了,全程不会同时存在多个活跃的可变引用。
但修改为闭包版本后,会触发编译错误:
fn foo<T>(v: &mut Vec<T>) { let mut f = ||{ foo(v); }; let mut g = ||{ foo(v); }; f(); g(); }
对应的错误信息如下:
error[E0524]: two closures require unique access to `*v` at the same time --> src/lib.rs:5:17 | 2 | let mut f = ||{ | -- first closure is constructed here 3 | foo(v); | - first borrow occurs due to use of `*v` in closure 4 | }; 5 | let mut g = ||{ | ^^ second closure is constructed here 6 | foo(v); | - second borrow occurs due to use of `*v` in closure 7 | }; 8 | f(); | - first borrow later used here
核心差异解析
第一个例子中,两次bar(v)是顺序执行的:第一次调用时,v被重借用给bar,函数执行完毕后借用立即归还;第二次调用再重新获取借用,全程没有同时存在两个可变引用的情况。
闭包的情况则完全不同:当创建闭包f和g时,两个闭包都会捕获对v的可变借用权限——由于闭包的执行时机不确定,编译器必须保证在闭包存在的整个周期内,v不能被其他任何地方借用。这里f和g从创建到各自调用完成的阶段是重叠的,相当于同时持有了对*v的可变借用请求,直接违反了Rust的"可变引用唯一"规则,因此编译报错。
哪怕你先调用f()再调用g()也无法解决:编译器在创建g的时候,f还未被销毁(直到函数结束才会释放),此时f仍然持有对v的借用权,g无法再获取新的借用。
内容的提问来源于stack exchange,提问作者Some Name
相关产品推荐
相关产品推荐

