【问题标题】:Mutable borrow goes out of scope but can't re-borrow可变借用超出范围但不能重新借用
【发布时间】:2018-11-13 18:29:12
【问题描述】:

当第一个可变借用似乎超出范围时,我无法理解为什么我不能第二次使用 v

fn get_or_insert(v: &mut Vec<Option<i32>>, index: usize, default: i32) -> &mut i32 {
    if let Some(entry) = v.get_mut(index) { // <-- first borrow here
        if let Some(value) = entry.as_mut() {
            return value;
        }
    }

    // error[E0502]: cannot borrow `*v` as immutable because it is also borrowed as mutable    
    while v.len() <= index {                // <-- compiler error here
        v.push(None);
    }

    // error[E0499]: cannot borrow `*v` as mutable more than once at a time
    let entry = v.get_mut(index).unwrap();  // <-- compiler error here
    *entry = Some(default);
    entry.as_mut().unwrap()
}

playground link

是我的变量范围有误,还是借用检查器保护了我免受我看不到的东西的影响?

编辑:启用 NLL 的错误消息非常好:

error[E0502]: cannot borrow `*v` as immutable because it is also borrowed as mutable
  --> src/main.rs:10:11
   |
3  | fn get_or_insert(v: &mut Vec<Option<i32>>, index: usize, default: i32) -> &mut i32 {
   |                     - let's call the lifetime of this reference `'1`
4  |     if let Some(entry) = v.get_mut(index) {
   |                          - mutable borrow occurs here
5  |         if let Some(value) = entry.as_mut() {
6  |             return value;
   |                    ----- returning this value requires that `*v` is borrowed for `'1`
...
10 |     while v.len() <= index {
   |           ^ immutable borrow occurs here

【问题讨论】:

标签: rust


【解决方案1】:

关键是,即使使用 NLL,返回值的生命周期也会跨越整个函数。在确定v 引用是否可在下方代码中访问时,并未考虑函数在第 4 行提前返回的事实。

@Stargateur 建议的解决方法是在访问元素之前根据需要增大向量:

fn get_or_insert(v: &mut Vec<Option<i32>>, index: usize, value: i32) -> &mut i32 {
    if v.len() < index {
        v.resize(index + 1, None);
    }
    v[index].get_or_insert(value)
}

playground link

Here's where I used the technique in the final code.

【讨论】:

    猜你喜欢
    • 2021-05-20
    • 1970-01-01
    • 2016-05-02
    • 1970-01-01
    • 1970-01-01
    • 2015-10-16
    • 2018-04-15
    • 1970-01-01
    • 2018-05-17
    相关资源
    最近更新 更多