How can I use multiple elements in Vec at a time in Rust?

I'm struggling a bit with the loan checker ... the essence of what I want to do:

#[derive(Debug)] struct SomeStruct { value: String, } impl SomeStruct { fn new(value: &str) -> SomeStruct { SomeStruct { value: value.to_string() } } fn change_value(&mut self, new_value: &str) { self.value = new_value.to_string(); } } fn main() { let mut my_vec = vec![ SomeStruct::new("foo"), SomeStruct::new("bar"), ]; my_vec[0].change_value(my_vec[1].value.as_str()); } 

This is a very general version of the problem I am facing. Here's the stderr:

 error[E0502]: cannot borrow `my_vec` as immutable because it is also borrowed as mutable --> src/main.rs:22:30 | 22 | my_vec[0].change_value(my_vec[1].value.as_str()); | ------ ^^^^^^ - mutable borrow ends here | | | | | immutable borrow occurs here | mutable borrow occurs here 

Thus, the loan checker does not allow me to borrow a vector twice (once as volatile, and then again as immutable), which I understand. But it’s unpleasant that I want to change one element in the vector and read only the other. I'm new to Rust (surprise!), And I'm not sure if I thought about all the details and design options. But this is what it seems to be working, but it is not. What am I missing and what can I do to make this (or comparable behavior) work? Any help is much appreciated!

+5
source share
2 answers

I agree, this is a bit confusing. So let's first see why this is not allowed by the Rust compiler.

Why is it not allowed

The index operator [] is something that can be overloaded, which means that language users can specify how it works. Rust tries to minimize the number of types in which the compiler has specialized knowledge. As a result, and despite its popularity, Vec<T> is a common type defined by the library. You can write your own Vec<T> without telling the compiler about it!

Vec<T> also overloads the index operator, allowing you to index the vector. But since overloading could do something, it could always return the first element of a vector! And if you assume that the index operator would do such a strange thing, this code should not be allowed:

 my_vec[0].change_value(my_vec[1].value.as_str()); 

Because my_vec[0] and my_vec[1] refer to the same value.

How to make it work

Of course, the index operator is not implemented in such a stupid way, and we know that. To get two references to different elements of the vector (where at least one is changed), we must use some special functions instead of the index operator. And there are several ways to do this:

I can’t tell you which method to use because I don’t know your specific use case. But to fix your example, you can write:

 let (head, tail) = my_vec.split_first_mut(); head.change_value(tail[0].value.as_str()); 
+6
source

You are right, you cannot borrow an object both invariably and interchangeably at the same time; To get this working, you can do the following:

 let new_value = my_vec[1].value.clone(); my_vec[0].change_value(&new_value); 

When you clone() value from myvec[1] , you no longer borrow myvec and can use new_value in the next line.

+2
source

Source: https://habr.com/ru/post/1261724/


All Articles