第二次可变借款错误,只有一次可变借款

时间:2019-06-02 21:45:26

标签: rust

这没有多大意义,因为无论if let为何,它都会返回相同的内容,但这是我遇到的问题的简要示例:

struct Data {
    value: Option<i32>,
}

impl Data {
    fn get(&mut self) -> Option<&mut i32> {
        if let Some(val) = &mut self.value {
            return Some(val);
        }

        return self.value.as_mut();
    }
}

此代码会产生错误:

error[E0499]: cannot borrow `self.value` as mutable more than once at a time
  --> src/lib.rs:11:16
   |
6  |     fn get(&mut self) -> Option<&mut i32> {
   |            - let's call the lifetime of this reference `'1`
7  |         if let Some(val) = &mut self.value {
   |                            --------------- first mutable borrow occurs here
8  |             return Some(val);
   |                    --------- returning this value requires that `self.value` is borrowed for `'1`
...
11 |         return self.value.as_mut();
   |                ^^^^^^^^^^ second mutable borrow occurs here

我不明白为什么当第一个借项超出范围而又没有第二个借项发生时,这又是第二个可变借项。

val变量不在if let的范围内,那么这又是第二次借用吗?第一次借用应该已经释放。

完全可以肯定的是,我甚至将if let用另一个方块包围了:

{
    if let Some(val) = &mut self.value {
        return Some(val);
    }
}

return self.value.as_mut();

这产生了相同的错误。这是怎么回事?

1 个答案:

答案 0 :(得分:7)

'a的生命周期包含整个函数体,因为返回值需要借用self。因此,第一次借用的范围超出了if表达式,并扩展到整个函数体。

非词法生存时间旨在通过将第一次借用的范围减小为仅包括if表达式来解决此issue。您可以通过将借入的值移动到局部变量(playground)中来看到这一点:

fn get(&mut self) -> Option<&mut i32> {
    let value = &mut self.value;
    if let Some(val) = value {
        return Some(val);
    }
    return value.as_mut();
}

但是,对有条件返回值的支持是removed,因为它花费了太多的编译时间。此功能仍在使用中,可以通过-Zpolonius标志启用:
RUSTFLAGS="-Zpolonius" cargo build +nightly

使用它,原始代码可以很好地编译。