Rust double mut borrow in loops - rust

Looking for a way to push in both Vec<Vec<>> and it's inner Vec<>. I do understand why it fails, but still struggle to find some graceful way to solve it.
fn example() {
let mut vec: Vec<Vec<i32>> = vec![];
vec.push(vec![]);
for i in &mut vec {
i.push(1);
if vec.len() < 10 {
vec.push(vec![]); // second mut borrow
}
}
}

The borrow checker won't allow you to iterate over a vector by reference and modify it during iteration. The reason for that is that modifying the vector can reallocate its storage, which would invalidate the references used for iteration. (And there is also the question of what it means to iterate over a changing vector, do you want to visit the elements added during iteration or just the elements that were present originally.)
The easiest fix that allows you to do what you want is to just iterate the vector using an index:
fn example() {
let mut vec: Vec<Vec<i32>> = vec![];
vec.push(vec![]);
let mut ind = 0;
while ind < vec.len() {
let i = &mut vec[ind];
i.push(1);
if vec.len() < 10 {
vec.push(vec![]);
}
ind += 1;
}
}

Related

how to correctly return a reference to a mutated linked list in rust?

I am solving a leetcode problem in Rust, it's a linked list problem.
The part that I am stuck at is that I have a working algorithm, but I wasn't able to return from the function, below is my solution
pub fn remove_nth_from_end(head: Option<Box<ListNode>>, n: i32) -> Option<Box<ListNode>> {
let mut cursor = head.clone().unwrap();
let mut count: i32 = 0;
while cursor.next != None {
count += 1;
cursor = cursor.next.unwrap();
}
let mut n = count - n;
let mut new_cursor = head.unwrap();
while n != 0 {
n -= 1;
new_cursor = new_cursor.next.unwrap();
}
new_cursor.next = new_cursor.next.unwrap().next;
head // <- error: used of moved value
}
I first clone the head so that I can iterate through the linked list to get its total number of nodes.
Then, I will have to remove one node from the list, hence I'm not cloning the head, instead I use it directly, in this case the variable is moved. So after I am done removing the node, I would like to return the head, so that I can return the whole linked list.
However, because of the ownership system in rust, I wasn't able to return a moved value. The problem is I couldn't clone the value as well because if I were to clone, then the head is no longer pointing to the linked list where I removed one node from it.
How would one solve this kind of issue in Rust? I am fairly new to Rust, just picked up the language recently.
One way is to use &mut over the nodes and then use Option::take to take ownership of the nodes while leaving None behind. Use those combinations to mutate the list:
impl Solution {
pub fn remove_nth_from_end(mut head: Option<Box<ListNode>>, mut n: i32) -> Option<Box<ListNode>> {
match n {
0 => head.and_then(|node| node.next),
_ => {
let mut new_head = &mut head;
while n > 0 {
new_head = if let Some(next) = new_head {
&mut next.next
} else {
return head;
};
n -= 1;
}
let to_skip = new_head.as_mut().unwrap().next.take();
new_head.as_mut().map(|node| {
node.next = if let Some(mut other_node) = to_skip {
other_node.next.take()
} else {
None
};
});
head
}
}
}
}
Playground
Disclaimer: This do not implement it working from the end of the list but from the beginning of it. Didn't realize that part, but that should be the problem itself.

Equivalent of split_at_mut for HashMap?

Consider the following code (minimum example):
use std::collections::HashMap;
fn main() {
let mut map: HashMap<usize, i128> = HashMap::new();
map.insert(1, -5);
map.insert(2, 6);
map.insert(3, 7);
for i in map.keys() {
if *i == 3 {
continue;
}
*map.get_mut(&3).unwrap() += map[i];
}
}
The borrow checker will complain that:
cannot borrow `map` as mutable because it is also borrowed as immutable
However, in this case I can be sure that the mutation I am doing is not interfering with the immutable references. For Vec, I would use split_at_mut here - is there an equivalent for that for HashMap in Rust?
Edit:
As a comment pointed out, let me be more specific about the problem I am trying to solve. I want to implement "merging" vertices in a graph into one vertex. For this I created a HashMap:
pub mergedVerticesList: HashMap<usize, HashSet<usize>>
which should map from a vertex to all the vertices that have been merged into that vertex. Since this can be done recursively, when undoing a merge between u and merge_onto I want to remove all vertices that have been merged into merge_onto because of u from merge_onto's HashSet. Thus, the code looks like this:
for i in self.mergedVerticesList[v].iter() {
self.mergedVerticesList.get_mut(&merge_onto).unwrap().remove(i);
}
No, this is not possible as far as the HashMap is concerned. You could have cells as values to regain mutable access but I'd strongly advise against that. Can't you move the change out of the loop (it also saves from a repeated lookup per iteration). Something to the tune of
use std::collections::HashMap;
fn main() {
let mut map: HashMap<usize, i128> = HashMap::new();
map.insert(1, -5);
map.insert(2, 6);
map.insert(3, 7);
let s = map.iter().filter_map(|(k, v)| if *k != 3 { Some(v) } else { None }).sum::<i128>();
*map.get_mut(&3).unwrap() += s;
println!("{:#?}", &map)
}

Can I reset a borrow of a local in a loop?

I have a processing loop that needs a pointer to a large lookup table.
The pointer is unfortunately triply indirected from the source data, so keeping that pointer around for the inner loop is essential for performance.
Is there any way I can tell the borrow checker that I'm "unborrowing" the state variable in the unlikely event I need to modify the state... so I can only re-lookup the slice in the event that the modify_state function triggers?
One solution I thought of was to change data to be a slice reference and do a mem::replace on the struct at the beginning of the function and pull the slice into local scope, then replace it back at the end of the function — but that is very brittle and error prone (as I need to remember to replace the item on every return). Is there another way to accomplish this?
struct DoubleIndirect {
data: [u8; 512 * 512],
lut: [usize; 16384],
lut_index: usize,
}
#[cold]
fn modify_state(s: &mut DoubleIndirect) {
s.lut_index += 63;
s.lut_index %= 16384;
}
fn process(state: &mut DoubleIndirect) -> [u8; 65536] {
let mut ret: [u8; 65536] = [0; 65536];
let mut count = 0;
let mut data_slice = &state.data[state.lut[state.lut_index]..];
for ret_item in ret.iter_mut() {
*ret_item = data_slice[count];
if count % 197 == 196 {
data_slice = &[];
modify_state(state);
data_slice = &state.data[state.lut[state.lut_index]..];
}
count += 1
}
return ret;
}
The simplest way to do this is to ensure the borrows of state are all disjoint:
#[cold]
fn modify_state(lut_index: &mut usize) {
*lut_index += 63;
*lut_index %= 16384;
}
fn process(state: &mut DoubleIndirect) -> [u8; 65536] {
let mut ret: [u8; 65536] = [0; 65536];
let mut count = 0;
let mut lut_index = &mut state.lut_index;
let mut data_slice = &state.data[state.lut[*lut_index]..];
for ret_item in ret.iter_mut() {
*ret_item = data_slice[count];
if count % 197 == 196 {
modify_state(lut_index);
data_slice = &state.data[state.lut[*lut_index]..];
}
count += 1
}
return ret;
}
The problem is basically two things: first, Rust will not look beyond a function's signature to find out what it does. As far as the compiler knows, your call to modify_state could be changing state.data as well, and it can't allow that.
The second problem is that borrows are lexical; the compiler looks at the block of code where the borrow might be used as goes with that. It doesn't (currently) bother to try and reduce the length of borrows to match where they're actually active.
You can also play games with, for example, using std::mem::replace to pull state.data out into a local variable, do your work, then replace it back just before you return.

What is the idiomatic way to pop the last N elements in a mutable Vec?

I am contributing Rust code to RosettaCode to both learn Rust and contribute to the Rust community at the same time. What is the best idiomatic way to pop the last n elements in a mutable Vec?
Here's roughly what I have written but I'm wanting to see if there's a better way:
fn main() {
let mut nums: Vec<u32> = Vec::new();
nums.push(1);
nums.push(2);
nums.push(3);
nums.push(4);
nums.push(5);
let n = 2;
for _ in 0..n {
nums.pop();
}
for e in nums {
println!("{}", e)
}
}
(Playground link)
I'd recommend using Vec::truncate:
fn main() {
let mut nums = vec![1, 2, 3, 4, 5];
let n = 2;
let final_length = nums.len().saturating_sub(n);
nums.truncate(final_length);
println!("{:?}", nums);
}
Additionally, I
used saturating_sub to handle the case where there aren't N elements in the vector
used vec![] to construct the vector of numbers easily
printed out the entire vector in one go
Normally when you "pop" something, you want to have those values. If you want the values in another vector, you can use Vec::split_off:
let tail = nums.split_off(final_length);
If you want access to the elements but do not want to create a whole new vector, you can use Vec::drain:
for i in nums.drain(final_length..) {
println!("{}", i)
}
An alternate approach would be to use Vec::drain instead. This gives you an iterator so you can actually use the elements that are removed.
fn main() {
let mut nums: Vec<u32> = Vec::new();
nums.push(1);
nums.push(2);
nums.push(3);
nums.push(4);
nums.push(5);
let n = 2;
let new_len = nums.len() - n;
for removed_element in nums.drain(new_len..) {
println!("removed: {}", removed_element);
}
for retained_element in nums {
println!("retained: {}", retained_element);
}
}
The drain method accepts a RangeArgument in the form of <start-inclusive>..<end-exclusive>. Both start and end may be omitted to default to the beginning/end of the vector. So above, we're really just saying start at new_len and drain to the end.
You should take a look at the Vec::truncate function from the standard library, that can do this for you.
(playground)
fn main() {
let mut nums: Vec<u32> = Vec::new();
nums.push(1);
nums.push(2);
nums.push(3);
nums.push(4);
nums.push(5);
let n = 2;
let new_len = nums.len() - n;
nums.truncate(new_len);
for e in nums {
println!("{}", e)
}
}

rust: error: lifetime of non-lvalue is too short to guarantee its contents can be safely reborrowed

I can't figure out what does this error in Rust mean:
error: lifetime of non-lvalue is too short to guarantee its contents can be safely reborrowed
What's a non-lvalue? (I suspect is not a right value).
I want to understand what the errror means and to be able to modify "objects" from a vector of mutable references.
This is a minimum test case to produce the error. I insert in a vector a mutable reference to a struct, and then I try to modify the pointed struct.
struct Point {
x: uint,
y: uint
}
fn main() {
let mut p = Point { x: 0, y: 0};
p.x += 1; // OK, p owns the point
let mut v: Vec<&mut Point> = Vec::new();
v.push(&mut p);
// p.x += 1 // FAIL (expected), v has borrowed the point
let p1:&mut Point = *v.get_mut(0); // ERROR, lifetime of non-lvalue...
// never reached this line
// p1.x += 1;
}
Let's go over what you're trying to do here:
let p1:&mut Point = *v.get_mut(0);
*v.get_mut(0) returns a mutable reference to first the mutable reference in the vector, then dereferences it. If this compiled, you would end up with two mutable references to the same object: one in the vector, the other in the p1 variable. Rust is rejecting this because it's not safe.
By far the best solution is to make the vector the owner of your Point objects. ie. use a Vec<Point> instead of a Vec<&mut Point.
If you need something more complicated, you can use a RefCell for dynamically checked borrowing:
use std::cell::RefCell;
struct Point {
x: uint,
y: uint
}
fn main() {
let p = RefCell::new(Point { x: 0, y: 0});
p.borrow_mut().x += 1;
let mut v: Vec<&RefCell<Point>> = Vec::new();
v.push(&p);
let p1 = v.get(0);
p1.borrow_mut().x += 1;
p.borrow_mut().x += 1;
}

Resources