3

I am implementing an in-place recursive parser in rust and I am getting some borrow errors. The code snippet reproduces the problem although it is not very useful

 use std::vec::Vec; struct MyBorrows<'a> { val : &'a mut i32 } impl <'a> MyBorrows<'a> { fn new(v : &'a mut i32) -> MyBorrows<'a> { MyBorrows { val : v } } } fn main() { let mut my_val = 23; let mut my_vec : Vec<Box<MyBorrows>> = Vec::new(); my_vec.push(Box::new(MyBorrows::new(&mut my_val))); for i in [1..4].iter() { let mut last : &mut Box<MyBorrows> = my_vec.last_mut().unwrap(); let mut new_borrow = Box::new(MyBorrows::new(last.val)); my_vec.push(new_borrow); } } 

This gives me the following error:

 error[E0499]: cannot borrow `my_vec` as mutable more than once at a time --> test.rs:20:9 | 18 | let mut last : &mut Box = my_vec.last_mut().unwrap(); | ------ first mutable borrow occurs here 19 | let mut new_borrow = Box::new(MyBorrows::new(last.val)); 20 | my_vec.push(new_borrow); | ^^^^^^ second mutable borrow occurs here 21 | } 22 | } | - first borrow ends here error: aborting due to 3 previous errors 

In my real case, the vector is used as a stack to reference deeper and deeper components of the struct I am parsing into. This is common pattern I use for general purpose parsing in C++ which I am trying to replicate in Rust but I am having problems. Any help will be appreciated.

1 Answer 1

4

What you are trying to do is unsound. It looks like you are attempting to create multiple MyBorrows which all mutably borrow the same value, and have them all alive at once (in the vector). Such setups are exactly what Rust is designed to prevent, as that's how data races occur.

What you might instead want to do is immutably borrow the value a bunch, which is legal. So after cleaning up the unnecessary mutable borrows, I've reduced the problem to:

struct MyBorrows<'a> { val : &'a i32 } impl <'a> MyBorrows<'a> { fn new(v : &'a i32) -> MyBorrows<'a> { MyBorrows { val : v } } } fn main() { let my_val = 23; let mut my_vec = vec![]; my_vec.push(Box::new(MyBorrows::new(&my_val))); for _ in 1..4 { let last = my_vec.last().unwrap(); let new_borrow = Box::new(MyBorrows::new(last.val)); my_vec.push(new_borrow); } } 

This works in modern Rust with non-lexical lifetimes!

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.