5

Rust-lang Playground 链接

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   
    }
}

我有一些与上面提供的代码相似但更复杂的代码,这些代码我已经使用了很长时间。借用检查器对 的实现不满意,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

没有办法在 Rust 中使用可变引用来实现回退逻辑似乎是不合理的,所以我无法想象没有办法。

4

1 回答 1

0

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
        } 
    }
}
于 2022-01-20T02:45:51.400 回答