qui*_*tle 8 rust borrow-checker early-return mutable-reference
struct Foo {
val: i32
}
impl Foo {
pub fn maybe_get(&mut self) -> Option<&mut i32> {
Some(&mut self.val)
}
pub fn definitely_get(&mut self) -> &mut i32 {
{ // Add closure to ensure things have a chance to get dropped
if let Some(val) = self.maybe_get() {
// Explicit return to avoid potential scope sharing with an else block or a match arms.
return val;
}
}
// One would think any mutable references would not longer be at play at this point
&mut self.val
}
}
Run Code Online (Sandbox Code Playgroud)
我有一些与上面提供的代码相似但更复杂的代码,我已经为此奋斗了很长一段时间。借用检查器对 的实现不满意definitely_get并出现以下错误
error[E0499]: cannot borrow `self.val` as mutable more than once at a time
--> src/main.rs:19:9
|
10 | pub fn definitely_get(&mut self) -> &mut i32 {
| - let's call the lifetime of this reference `'1`
11 | {
12 | if let Some(val) = self.maybe_get() {
| ---------------- first mutable borrow occurs here
13 | return val;
| --- returning this value requires that `*self` is borrowed for `'1`
...
19 | &mut self.val
| ^^^^^^^^^^^^^ second mutable borrow occurs here
Run Code Online (Sandbox Code Playgroud)
在 Rust 中没有办法用可变引用实现回退逻辑似乎是不合理的,所以我无法想象没有办法。
maybe_get由于我的非平凡示例中的实现方式,我已设法通过不幸昂贵的替代实现来解决此问题。
impl Foo {
pub fn has_maybe_val(&self) -> bool {
// Non-trivial lookup...
true
}
pub fn maybe_get(&mut self) -> Option<&mut i32> {
// Same non-trivial lookup...
Some(&mut self.val)
}
pub fn definitely_get(&mut self) -> &mut i32 {
if self.has_maybe_val() {
self.maybe_get().unwrap() // Ouch!
} else {
&mut self.val
}
}
}
Run Code Online (Sandbox Code Playgroud)