How can I partition a mutably borrowed vector? - rust

If I have a local, mutable vector, I can partition it as follows, copied from the documentation of partition.
let mut a = vec![1, 2, 3, 4];
let (even, odd): (Vec<i32>, Vec<i32>) = a.into_iter().partition(|&n| n % 2 == 0);
The a vector is consumed (moved) in this process. However, the same call to partition doesn't work if I have a borrowed mutable reference. If I try to use the same code in that case, I get the error:
error[E0277]: the trait bound `std::vec::Vec<i32>: std::iter::Extend<&mut i32>` is not satisfied
--> src/main.rs:2:59
|
2 | let (even, odd): (Vec<i32>, Vec<i32>) = a.into_iter().partition(|n| **n % 2 == 0);
| ^^^^^^^^^ the trait `std::iter::Extend<&mut i32>` is not implemented for `std::vec::Vec<i32>`
|
= help: the following implementations were found:
<std::vec::Vec<T> as std::iter::Extend<&'a T>>
<std::vec::Vec<T> as std::iter::Extend<T>>
Based on How to make a Rust mutable reference immutable?, I wrote the following, which compiles and puts the right values into even and odd.
fn doit(a: &mut Vec<i32>) {
let (even, odd): (Vec<i32>, Vec<i32>) = (&*a).into_iter().partition(|&n| n % 2 == 0);
println!("even {:?}, odd {:?}, a {:?}", even, odd, a);
}
However, this does not consume the original vector, even though I'm using into_iter(). There's something about mutability, borrowing, or iterators that I'm just not getting here.

As others have implied, you can't move the original vector since you don't own it. However you can move all the values out of the vector, leaving it empty. This can be accomplished with the drain method:
fn doit(a: &mut Vec<i32>) {
let (even, odd): (Vec<i32>, Vec<i32>) = a.drain(..).partition(|&n| n % 2 == 0);
println!("even {:?}, odd {:?}, a {:?}", even, odd, a);
}
playground

The reason is that the IntoIterator trait is implemented differently for &'a mut Vec<T> and &'a Vec<T> then it is for Vec<T>. The First two create an iterator by value where as the Vec<T> version creates a consuming iterator, that is, one that moves each value out of the vector (from start to end). The vector cannot be used after calling into_iter(). So you can think of the first two &'a mut Vec<T> and &'a Vec<T> as using the values inside the reference to the Vector to create an iterator. Where as the Vec<T> you can think of it removing the values out of the Vec<T> and putting them into the iterator. Shepmaster's comment of not being able to consume something that you don't own is the reason why they are implemented differently.
Also be aware that there is different ways to get an iterator.
From the Rust documentation:
iter(), which iterates over &T.
iter_mut(), which iterates over &mut T.
into_iter(), which iterates over T.
So you could also keep the function the same without doing (&*a) by using iter() instead of into_iter().
fn doit(a: &mut Vec<i32>) {
let (even, odd): (Vec<i32>, Vec<i32>) = a.iter().partition(|&n| n % 2 == 0);
println!("even {:?}, odd {:?}, a {:?}", even, odd, a);
}

Related

Why does this Rust code not compile (mutably borrow two individual vector elements)? [duplicate]

This question already has an answer here:
What is lifetime elision in very simple terms?
(1 answer)
Closed 3 months ago.
I have this function that borrows two individual elements from a vector. It works as expected:
fn borrow_mut_two<T>(v: &mut [T], i: usize, j: usize) -> (&mut T, &mut T) {
assert!(i < j);
let (left, right) = v.split_at_mut(j);
(&mut left[i], &mut right[0])
}
fn test() {
let mut v = vec![0, 1, 2, 3, 4, 5, 6, 7, 8];
let i = 2;
let j = 5;
let (ref_a, ref_b) = borrow_mut_two(&mut v, i, j);
*ref_a += 1;
*ref_b += 5;
assert_eq!(*ref_a, i + 1);
assert_eq!(*ref_b, j + 5);
}
What I'm trying to understand is why the following code doesn't compile:
fn test() {
let mut v = vec![0, 1, 2, 3, 4, 5, 6, 7, 8];
let i = 2;
let j = 5;
let (ref_a, ref_b) = borrow_mut_two(&mut v, i, j);
// Added this line:
let (other_ref_a, other_ref_b) = borrow_mut_two(&mut v, i, j);
*ref_a += 1;
*ref_b += 5;
assert_eq!(*ref_a, i + 1);
assert_eq!(*ref_b, j + 5);
}
It seems it works in a safe manner, because it doesn't allow me to mutably borrow the same elements twice (or potentially other elements).
My question is how does the compiler know that this is unsafe (and therefore reject compiling it)?
The compiler errors are:
229 | let (ref_a, ref_b) = borrow_mut_two(&mut v, i, j);
| ------ first mutable borrow occurs here
230 | let (other_ref_a, other_ref_b) = borrow_mut_two(&mut v, i, j);
| ^^^^^^ second mutable borrow occurs here
As far as I know the return value of borrow_mut_two is the tuple (&mut T, &mut T), which may or may not be a borrow to self, but it seems the compiler does know it's borrowing self. My assumptions may be wrong though 🙂.
The only thing that comes to mind is that Rust automatically adds the lifetime:
fn borrow_mut_two<'a, T>(v: &'a mut [T], i: usize, j: usize) -> (&'a mut T, &'a mut T)
Which would mean that in my test function, 'a is still alive (i.e. self mutably borrowed) due to the first call to borrow_mut_two while the second call happens, and that's how it detects a second mutable borrow.
But I'd like to confirm if this is correct.
Extra
It could be related to this part of the book. The only difference I see is that my function returns a tuple. So the question can be reduced to: Does Rust's second lifetime elision rule also add 'a to each element of a tuple? If so, then my doubt is solved:
The first rule is that the compiler assigns a lifetime parameter to
each parameter that’s a reference. In other words, a function with one
parameter gets one lifetime parameter: fn foo<'a>(x: &'a i32); a
function with two parameters gets two separate lifetime parameters: fn
foo<'a, 'b>(x: &'a i32, y: &'b i32); and so on.
The second rule is that, if there is exactly one input lifetime
parameter, that lifetime is assigned to all output lifetime
parameters: fn foo<'a>(x: &'a i32) -> &'a i32.
Yes, your understanding is correct - due to lifetime elision, the following two function signatures are equivalent:
fn borrow_mut_two<T>(v: &mut [T], i: usize, j: usize) -> (&mut T, &mut T)
fn borrow_mut_two<'a, T>(v: &'a mut [T], i: usize, j: usize) -> (&'a mut T, &'a mut T)
Because the lifetimes of the output are tied to the lifetime of v, the compiler knows that v is still mutably borrowed until those derived references stop being used.
The issue in your second code is that you are trying to borrow mutably v while an other mutable borrow is still alive, just as the compiler indicates to you. To be more precise, the compiler sees the following constraints:
fn test() {
// ...
let (ref_a, ref_b) = borrow_mut_two(&'3 mut v, i, j); // ------+
// ^^^^^ ^^^^^ ^^^^^^^ Let's call // |
// +---+ this lifetime '3 // |
// | // |
// Let's call the lifetime of these mutable borrows '1 // |
// Added this line: // +- '1
let (other_ref_a, other_ref_b) = borrow_mut_two(&'4 mut v, i, j); // -+ '2 |
// ^^^^^^^^^^^ ^^^^^^^^^^^ // | |
// +------+ Let's call the lifetimes of these borrows '2 // -+ |
*ref_a += 1; // |
*ref_b += 5; // ------+
}
First of all, '3 and '4 cannot outlive the lifetime of v, but this isn't very important in this case so we can forget about it. Then, due to the signature of borrow_mut_two, '1='3 and '2='4. Furthermore, since we are talking about mutable borrows, there can be at most one at a time. Finally, I have indicated the minimum span of '1 and '2.
When the compiler tries to enforce all these constraints, it will fail, because clearly '1 and '2 cannot be disjoint while living at least for as much time as they are useful.
In fact, it is sometimes possible to make this kind of layout work, because '1 is never used when '2 is used, and '2's span is included in '1's. In these cases, the compiler says the borrows are stacked, and it could accept them if '2 was a reborrow of '1. It is logically the case, but split_at_mut prevents the compiler from understanding this because internally it uses unsafe code on which the compiler can't reason as easily as it would otherwise.

Swap two elements in a vector in rust

I want to swap two elements in a vector.
I wrote this function to swap elements, but it gives it gives an error.
fn swap<T>(arr: &mut Vec<T>, i: usize, j: usize) {
let temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
error[E0507]: cannot move out of index of `Vec<T>`
--> src/quick_sort.rs:2:16
|
2 | let temp = arr[i];
| ^^^^^^
| |
| move occurs because value has type `T`, which does not implement the `Copy` trait
| help: consider borrowing here: `&arr[i]`
You are in luck, the implementers thought that people may want an easy way of swapping elements and added Vec::swap. This method is also implemented with slices. If you want to swap the values for two mutable references you can use std::mem::swap.
fn swap<T>(arr: &mut Vec<T>, i: usize, j: usize) {
arr.swap(i, j);
}
Alternatively while it is a bit of a pain to do, you can split a slice or array into two or more non-overlapping mutable slices of the original. This allows you to take multiple multiple references into an slice at once.
pub fn swap(arr: &mut [Foo], i: usize, j: usize) {
let (low, high) = match i.cmp(&j) {
Ordering::Less => (i, j),
Ordering::Greater => (j, i),
Ordering::Equal => return,
};
let (a, b) = arr.split_at_mut(high);
std::mem::swap(&mut a[low], &mut b[0]);
}
Because you haven't added any constraints to T, your generic swap<T>() function needs to be able to work for any type T. Importantly, it needs to be able to work for types even if they don't implement the Copy trait, therefore the assignment operator (=) performs a move. You can't move the value out of the vector like this, or this would invalidate the vector. Of course, you plan to fix up the vector so that it is valid again, but the compiler doesn't see the big picture here, it only sees the initial move as invalidating the vector, and therefore is illegal.
To implement swap here, you would need to use unsafe code. However, swap is a common problem, so the Rust standard library exposes functions to do this so you don't have to (std::mem::swap() or Vec::swap() as #Locke mentioned).
Alternatively, you could specify that your swap function only works for types which implement the Copy trait, like so:
fn swap<T: Copy>(arr: &mut Vec<T>, i: usize, j: usize) {
let temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
However, there is no advantage to writing your own swap over std::mem::swap().

How do I get a slice containing all but the Nth element? [duplicate]

I have a function that needs to operate on two parts of a single array.
The purpose is to be able to build an #[nostd] allocator that can return a variable slice of a bigger array to the caller and hang on to the remainder of the array for future allocations.
Here's example code that fails:
fn split<'a>(mut item: &'a mut [i32], place: usize) -> (&'a mut [i32], &'a mut [i32]) {
(&mut item[0..place], &mut item[place..])
}
fn main() {
let mut mem: [i32; 2048] = [1; 2048];
let (mut array0, mut array1) = split(&mut mem[..], 768);
array0[0] = 4;
println!("{:?} {:?}", array0[0], array1[0]);
}
the error is as follows:
error[E0499]: cannot borrow `*item` as mutable more than once at a time
--> src/main.rs:2:32
|
2 | (&mut item[0..place], &mut item[place..])
| ---- ^^^^ second mutable borrow occurs here
| |
| first mutable borrow occurs here
3 | }
| - first borrow ends here
This pattern also can be helpful for in-place quicksort, etc.
Is there anything unsafe about having two mutable references to nonoverlapping slices of the same array? If there's no way in pure Rust, is there a "safe" unsafe incantation that will allow it to proceed?
Is there anything unsafe about having two mutable references to nonoverlapping slices of the same array?
There isn't, but Rust's type system cannot currently detect that you're taking mutable references to two non-overlapping parts of a slice. As this is a common use case, Rust provides a safe function to do exactly what you want: std::slice::split_at_mut.
fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T])
Divides one &mut into two at an index.
The first will contain all indices from [0, mid) (excluding the index
mid itself) and the second will contain all indices from [mid, len)
(excluding the index len itself).
The final code is:
fn main() {
let mut mem : [i32; 2048] = [1; 2048];
let (mut array0, mut array1) = mem[..].split_at_mut(768);
array0[0] = 4;
println!("{:?} {:?}", array0[0], array1[0]);
}
Wow that was such a perfect match. Thanks for finding this!

How does Rust determine type in for-in loop? Does Rust auto reference/dereference on variable assignment? [duplicate]

I'm confused by how Rust for loops work. Consider the following:
#![feature(core_intrinsics)]
fn print_type_of<T>(_: T) {
println!("{}", unsafe { std::intrinsics::type_name::<T>() });
}
fn main() {
let nums = vec![1, 2, 3];
for num in &nums { print_type_of(num); }
for num in nums { print_type_of(num); }
}
It outputs the following:
&i32
&i32
&i32
i32
i32
i32
What does it mean to pass in a vector into for versus a reference to a vector? Why, when you pass in a reference, do you get a reference to the items and when you pass in an actual vector, you get the actual items?
The argument to a for loop must implement IntoIterator. If you check out the docs for Vec, you will see these two implementations of IntoIterator:
impl<T> IntoIterator for Vec<T> {
type Item = T;
type IntoIter = IntoIter<T>
}
impl<'a, T> IntoIterator for &'a Vec<T> {
type Item = &'a T;
type IntoIter = Iter<'a, T>
}
You get references for &vec and values for vec because that's how the iterators are defined.
Sometimes, you'll see these as the more explicit forms: iter or into_iter. The same logic applies; see What is the difference between iter and into_iter?
There's another form that you will encounter: &mut vec and iter_mut. These return mutable references to the elements in the vector.
As to why the differences at all...
Using a reference to the vector allows you to access the vector after the loop is done. This compiles:
let v = vec![1, 2, 3];
for i in &v {}
for i in &v {}
This does not:
let v = vec![1, 2, 3];
for i in v {}
for i in v {}
error[E0382]: use of moved value: `v`
--> src/main.rs:4:14
|
3 | for i in v {}
| - value moved here
4 | for i in v {}
| ^ value used here after move
|
= note: move occurs because `v` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
Ownership-wise, you can't get a value from a reference unless you clone the value (assuming the type can even be cloned!). This means &vec is unable to yield values that aren't references.
The implementer of Vec's iterator could have chosen to only yield references, but transferring ownership of the elements to the iterator allows the iterator's consumer to do more things; from a capability perspective it's preferred.
See also:
What is the difference between iter and into_iter?
Why can I iterate over a slice twice, but not a vector?

How to operate on 2 mutable slices of a Rust array?

I have a function that needs to operate on two parts of a single array.
The purpose is to be able to build an #[nostd] allocator that can return a variable slice of a bigger array to the caller and hang on to the remainder of the array for future allocations.
Here's example code that fails:
fn split<'a>(mut item: &'a mut [i32], place: usize) -> (&'a mut [i32], &'a mut [i32]) {
(&mut item[0..place], &mut item[place..])
}
fn main() {
let mut mem: [i32; 2048] = [1; 2048];
let (mut array0, mut array1) = split(&mut mem[..], 768);
array0[0] = 4;
println!("{:?} {:?}", array0[0], array1[0]);
}
the error is as follows:
error[E0499]: cannot borrow `*item` as mutable more than once at a time
--> src/main.rs:2:32
|
2 | (&mut item[0..place], &mut item[place..])
| ---- ^^^^ second mutable borrow occurs here
| |
| first mutable borrow occurs here
3 | }
| - first borrow ends here
This pattern also can be helpful for in-place quicksort, etc.
Is there anything unsafe about having two mutable references to nonoverlapping slices of the same array? If there's no way in pure Rust, is there a "safe" unsafe incantation that will allow it to proceed?
Is there anything unsafe about having two mutable references to nonoverlapping slices of the same array?
There isn't, but Rust's type system cannot currently detect that you're taking mutable references to two non-overlapping parts of a slice. As this is a common use case, Rust provides a safe function to do exactly what you want: std::slice::split_at_mut.
fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T])
Divides one &mut into two at an index.
The first will contain all indices from [0, mid) (excluding the index
mid itself) and the second will contain all indices from [mid, len)
(excluding the index len itself).
The final code is:
fn main() {
let mut mem : [i32; 2048] = [1; 2048];
let (mut array0, mut array1) = mem[..].split_at_mut(768);
array0[0] = 4;
println!("{:?} {:?}", array0[0], array1[0]);
}
Wow that was such a perfect match. Thanks for finding this!

Resources