2

Suppose that you have multiple stacks represented as vectors and you want to move data from one of the stacks to another. A convenient and "Rustic" way to do that is to use extend_from_slice to extend one vector with a slice from the other vector without copying it, like this:

fn main() {
    let mut s1 = vec![1, 2, 3];
    let mut s2 = vec![];

    println!("before #{}: {:?}", 1, s1);
    println!("before #{}: {:?}", 2, s2);

    s2.extend_from_slice(&s1[1..]);
    s1.truncate(1);

    println!("after  #{}: {:?}", 1, s1);
    println!("after  #{}: {:?}", 2, s2);
}

This compiles fine and implements the move.

Now, if you want to support multiple vectors, even a variable number of them, you can store them as a vector of vectors, like this:

fn main() {
    let mut stacks = vec![vec![1, 2, 3], vec![2, 3, 4], vec![]];

    for (n, stack) in stacks.iter().enumerate() {
        println!("before #{}: {:?}", n, stack);
    }

    stacks[2].extend_from_slice(&stacks[1][1..]);
    stacks[1].truncate(1);

    for (n, stack) in stacks.iter().enumerate() {
        println!("after  #{}: {:?}", n, stack);
    }
}

However, if you try this trick to append a slice from one of the vectors to another, the borrow-checker will complain:

error[E0502]: cannot borrow `stacks` as immutable because it is also borrowed as mutable
  --> examples/vector_vector_move.rs:10:34
   |
10 |     stacks[2].extend_from_slice(&stacks[1][1..]);
   |     ------    -----------------  ^^^^^^ immutable borrow occurs here
   |     |         |
   |     |         mutable borrow later used by call
   |     mutable borrow occurs here

Since the slice to move is from a different vector than the slice to extend, there should be no safety issues with performing the move. Rationale is that the "top-level" vector does not need to change size, it is only the inner vectors that need to change size.

Trying to split out the slice into a separate variable give the same error as before, and storing references to vectors instead of vectors directly gives a whole bunch of other errors saying similar things as above.

Is there a way to move a slice of a vector to another vector in a vector of vectors without creating a copy of the slice first?

Mats Kindahl
  • 1,863
  • 14
  • 25
  • AoC, right? Can you use nightly? – Chayim Friedman Dec 06 '22 at 15:09
  • 1
    You can apply this [How to get mutable references to two array elements at the same time?](https://stackoverflow.com/questions/30073684/how-to-get-mutable-references-to-two-array-elements-at-the-same-time) to your problem because you can simply cast one of the borrows to a shared one (if rust doesn't do it automatically for you). – cafce25 Dec 06 '22 at 15:21
  • @ChayimFriedman Yes, it is AoC. I solved it by copying the slice, but this raised the bigger question on how to do it the "Rustic" way. – Mats Kindahl Dec 06 '22 at 15:23
  • Just posted the nightly answer on the duplicate. – Chayim Friedman Dec 06 '22 at 15:25
  • Note that to remove the data from one and extend other at the same time you can use `drain()`: `dest.extend(src.drain(1..));`. – Chayim Friedman Dec 06 '22 at 15:31
  • @ChayimFriedman I missed that one. Thanks! – Mats Kindahl Dec 06 '22 at 15:46
  • @cafce25 I do not think that the questions are actually the same. This one is about having a immutable (shared) reference to one part of the vector and a mutable reference to another part of the vector, so casting here does not really help. At least I cannot see how this can help. – Mats Kindahl Dec 06 '22 at 15:50
  • @cafce25 Well... there are many questions that are different that have the same answer, and since SO seeks to find answer to questions, I think that the key point is if the questions are duplicates, not if the answers are duplicates. – Mats Kindahl Dec 06 '22 at 15:55
  • It's a duplicate because the exact same answer applies to your problem. Not because the questions are phrased the exact same. What good would it do if we copy pasted the answers of the duplicate target here? Better have this as a sign post to lead to the correct answer than duplicate the effort no? Also did you not get your answer by us linking the duplicate? This doesn't mean your question is bad or should not have been posted. Just that we don't want to post a literal copy paste of the other answer below this. – cafce25 Dec 06 '22 at 15:56

0 Answers0