Errors in overwriting slice reference with sub-slice reference

走远了吗. 提交于 2021-01-29 10:46:12

问题


I'm trying to nail down ownership rules. I want to:

  • start with a mutable reference to a slice
  • make some edits to its contents
  • reduce the slice reference to a reference of a sub-slice and repeat

Below is my attempt:

pub fn example() {
    // Make a mutable slice
    let mut v = [0, 1, 2, 3];

    // Make a mutable reference to said slice
    let mut v_ref = &mut v[..];

    while v_ref.len() > 1 {
        // Involves some edits -> need mut
        v_ref.swap(0, v_ref.len() - 1);

        // Try to reduce slice to sub-slice (some simplification here)
        // Errors!
        let (v_l, v_h) = v.split_at_mut(v.len() / 2);
        v_ref = v_l;
    }
}

However I'm getting the errors:

error[E0502]: cannot borrow `*v_ref` as immutable because it is also borrowed as mutable
  --> src/lib.rs:11:23
   |
11 |         v_ref.swap(0, v_ref.len() - 1);
   |         -----         ^^^^^          - mutable borrow ends here
   |         |             |
   |         |             immutable borrow occurs here
   |         mutable borrow occurs here

error[E0499]: cannot borrow `v` as mutable more than once at a time
  --> src/lib.rs:15:26
   |
7  |     let mut v_ref = &mut v[..];
   |                          - first mutable borrow occurs here
...
15 |         let (v_l, v_h) = v.split_at_mut(v.len() / 2);
   |                          ^ second mutable borrow occurs here
...
18 | }
   | - first borrow ends here

error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
  --> src/lib.rs:15:41
   |
7  |     let mut v_ref = &mut v[..];
   |                          - mutable borrow occurs here
...
15 |         let (v_l, v_h) = v.split_at_mut(v.len() / 2);
   |                                         ^ immutable borrow occurs here
...
18 | }
   | - mutable borrow ends here

I understand that you can't have multiple references to an object in the same scope as a single mutable reference.

There should be a safe way to reduce a slice's range, as you're only reducing the scope of a current mutable reference. What's the best way to do that?


回答1:


Problem 1: Using the same variable mutably and immutably

As Peter Hall points out, the code attempts to reference the variable v while there's a concurrent mutable reference to it, even though you don't care about v_ref anymore. A MCVE:

pub fn example() {
    let mut v = 0;
    let mut v_ref = &mut v;
    println!("{}", v)
}

See also:

  • What are non-lexical lifetimes?

Problem 2: Using the same variable mutably and immutably

Then the code attempts to overlap mutable and mutable borrows in a single function call. A MCVE:

pub fn example() {
    let mut v = [0, 1, 2, 3];
    v.split_at_mut(v.len());
}

See also:

  • Cannot borrow as immutable because it is also borrowed as mutable in function arguments

Problem 3: Using the same variable mutably and mutably

Then the code has overlapping mutable borrows of v in the loop.

See also:

  • Cannot obtain a mutable reference when iterating a recursive structure: cannot borrow as mutable more than once at a time

All together:

pub fn example() {
    let mut v = [0, 1, 2, 3];
    let mut v_ref = &mut v[..];

    while v_ref.len() > 1 {
        let len = v_ref.len();
        v_ref.swap(0, len - 1);
        let (v_l, _) = { v_ref }.split_at_mut(len / 2);
        v_ref = v_l;
    }
}


来源:https://stackoverflow.com/questions/52026575/errors-in-overwriting-slice-reference-with-sub-slice-reference

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!