cannot borrow `*self` as mutable more than once at a time - rust

I don't understand this borrow checker error:
pub fn wait_for_device(&mut self) -> RoxResult<hidapi::HidDevice> {
let mut device = self.open_device();
let start = time::Instant::now();
while device.is_err() {
device = self.open_device();
if start.elapsed().as_secs() > 30 {
return Err("Can't reconnect to device".to_owned());
}
}
Ok(device.expect("Out of while so we should have a device"))
}
pub fn open_device(&mut self) -> RoxResult<hidapi::HidDevice> {
let device_info = &self.list[0];
if let Ok(device) = self.api.open(device_info.vendor_id, device_info.product_id) {
self.current_device = Some(device_info.clone());
Ok(device)
} else {
Err(format!(
"Error opening device vip: {:x} pid: {:x}",
device_info.vendor_id, device_info.product_id
))
}
}
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src\usb.rs:64:22
|
61 | let mut device = self.open_device();
| ---- first mutable borrow occurs here
...
64 | device = self.open_device();
| ^^^^ second mutable borrow occurs here
...
70 | }
| - first borrow ends here
I thought my first borrowing will end at the end of open_device but it seems I'm wrong. Why?

Variables are valid until the end of the scope in which they were declared. You created a variable device and assigned borrowed value to it in the scope of the entire function. In other words the borrow ends at the end of the function (as you can see in compiler error message).

Related

Rust borrow checker multiple mutable reference in modifying element in linked list in a loop

I'm trying to build some sort of linked list, each node has a keyword and vectors of the same node. In that for loop, i will traverse the linked list to get the vector, either already exist if keyword is the same, or create a new vector. I find it impossible to *not * violate the double mut reference error since I'll need to do iter_mut(), push() on the same path. Anyone has general idea on how to approach this?
pub struct Knowledge {
pub title: String,
}
pub struct Entry {
pub keyword: String,
pub next: Vec<Box<KnowledgeEntry>>
}
pub enum KnowledgeEntry {
Normal(Knowledge),
Entry(Entry)
}
impl KnowledgeEntry {
pub fn get_entry_mut (&mut self) -> Option<&mut Vec<Box<KnowledgeEntry>>> {
match self {
KnowledgeEntry::Entry(e) => {
Some(&mut e.next)
}
KnowledgeEntry::Normal(k) => {None}
}
}
}
fn main () {
let mut entry = Entry{keyword: "".to_owned(), next: vec![]};
let mut current_container = &mut entry.next;
let new_knowledge = Knowledge{title: "title1".to_owned()};
// new knowledge to be insert in these hierarchy.
let remaining_comp: Vec<_> = vec!["hier1", "hier2", "hier3"];
// each loop will set current_container, either created from new, or found in the vector.
for comp in remaining_comp.iter() {
// true will be replace with body checking with keyword.
let mut _result = current_container.iter_mut().find(|en| {true});
if let Some(mut _res) = _result {
// found the container. Set the current container
if let KnowledgeEntry::Entry(ref mut entry) = &mut **_res {
current_container = &mut entry.next;
} else {
break;
}
} else {
// can't find the resulting container. Create a new vector, and move the container.
let new_container: Vec<Box<KnowledgeEntry>> = vec![];
let mut _temp = KnowledgeEntry::Entry(Entry {
keyword: (*comp).to_string(),
next: new_container
});
current_container.push(Box::new(_temp));
let last_var = current_container.last_mut().unwrap();
// get_entry_mut() to retrieve `_temp` that we have just moved.
current_container = (**last_var).get_entry_mut().unwrap();
}
}
// found the container correspond to "hier1" -> "hier2" -> "hier3", add the entry.
current_container.push(Box::new(KnowledgeEntry::Normal(new_knowledge)));
}
Playground
Produces the following errors:
error[E0499]: cannot borrow `*current_container` as mutable more than once at a time
--> src/main.rs:50:13
|
35 | let mut _result = current_container.iter_mut().find(|en| {true});
| ----------------- first mutable borrow occurs here
...
50 | current_container.push(Box::new(_temp));
| ^^^^^^^^^^^^^^^^^
| |
| second mutable borrow occurs here
| first borrow later used here
error[E0499]: cannot borrow `*current_container` as mutable more than once at a time
--> src/main.rs:51:28
|
35 | let mut _result = current_container.iter_mut().find(|en| {true});
| ----------------- first mutable borrow occurs here
...
51 | let last_var = current_container.last_mut().unwrap();
| ^^^^^^^^^^^^^^^^^
| |
| second mutable borrow occurs here
| first borrow later used here
error[E0499]: cannot borrow `*current_container` as mutable more than once at a time
--> src/main.rs:57:1
|
35 | let mut _result = current_container.iter_mut().find(|en| {true});
| ----------------- first mutable borrow occurs here
...
57 | current_container.push(Box::new(KnowledgeEntry::Normal(new_knowledge)));
| ^^^^^^^^^^^^^^^^^
| |
| second mutable borrow occurs here
| first borrow later used here

How can I iterate on a Bevy Query and keep a reference to the iterated value so that I can use it later?

I have a borrow in the empty variable and I want to extend its life. In the commented code-block, I attempt to address it, but the reference is no longer available. I have to loop through the loop again to find the match in order to act on it.
How can I loop through a query looking for a best-match and then act on it once I know it's the best match, without having to loop through to find it again?
use bevy::prelude::*;
struct Person;
struct Name(String);
fn main() {
App::build()
.add_default_plugins()
.add_startup_system(startup.system())
.add_system(boot.system())
.run();
}
fn boot(mut query: Query<(&Person, &mut Name)>) {
let mut temp_str = String::new();
let mut empty: Option<&mut Name> = None;
for (_p, mut n_val) in &mut query.iter() {
if n_val.0.to_lowercase() > temp_str.to_lowercase() {
temp_str = n_val.0.clone();
empty = Some(&mut n_val);
}
}
println!("{}", temp_str);
if let Some(n) = empty {
// ...
}
// for (_p, mut n_val) in &mut query.iter() {
// if n_val.0 == temp_str {
// n_val.0 = "a".to_string();
// }
// }
}
fn startup(mut commands: Commands) {
commands
.spawn((Person, Name("Gene".to_string())))
.spawn((Person, Name("Candace".to_string())))
.spawn((Person, Name("Zany".to_string())))
.spawn((Person, Name("Sarah".to_string())))
.spawn((Person, Name("Carl".to_string())))
.spawn((Person, Name("Robert".to_string())));
}
Cargo.toml:
[package]
name = "sample"
version = "0.1.0"
authors = [""]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
bevy = "0.1.3"
Specific error:
error[E0716]: temporary value dropped while borrowed
--> src/main.rs:17:33
|
17 | for (_p, mut n_val) in &mut query.iter() {
| ^^^^^^^^^^^-
| | |
| | temporary value is freed at the end of this statement
| creates a temporary which is freed while still in use
...
24 | if let Some(n) = empty {
| ----- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
error[E0597]: `n_val` does not live long enough
--> src/main.rs:20:26
|
20 | empty = Some(&mut n_val);
| ^^^^^^^^^^ borrowed value does not live long enough
21 | }
22 | }
| - `n_val` dropped here while still borrowed
23 | println!("{}", temp_str);
24 | if let Some(n) = empty {
| ----- borrow later used here
You cannot extend the lifetime of a reference, but that is not your issue here, the error says temporary value dropped while borrowed, so you must extend the lifetime of your temporary.
If you wonder what temporary, the compiler also points to that (literally) in the error message: query.iter(). This is a function call, and the returned value is not bound to anything, so the compiler creates a temporary value for that. Then you iterate using a reference to that temporary. When the for loop ends, the temporary is dropped and any reference lifetime to it expires.
The solution is to bind the temporary to a local variable. This way you extend the lifetime of the object to the scope of the variable:
let mut iter = query.iter();
for (_p, n_val) in &mut iter {
if n_val.0.to_lowercase() > temp_str.to_lowercase() {
temp_str = n_val.0.clone();
empty = Some(n_val);
}
}
PS: I find quite bizarre the pattern of iterating over &mut iter. I would expect the return of iter() to implement Iterator or IntoIterator directly, but it looks like this is not the case.

Cannot share Arc variables when spawning threads

I have the following struct to represent the server object:
pub struct Server {
client_managers: Arc<ClientManager>,
listener: Option<TcpListener>,
}
Here is the code that receives a client's connection and handles it in a new thread:
fn serve(&self) {
for stream in self.listener.as_ref().unwrap().incoming() {
match stream {
Ok(stream) => {
let client_manager = &mut self.client_managers.clone();
// let client_manager = Arc.new(self.client_managers);
thread::spawn(move || {
client_manager.do_something();
});
}
Err(e) => {
println!("connection error: {}", e);
}
}
}
}
However, I get the following error when compiling:
error[E0716]: temporary value dropped while borrowed
--> server/src/server.rs:37:47
|
37 | let client_manager = &mut self.client_managers.clone();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
38 | // let client_manager = Arc.new(self.client_managers);
39 | / thread::spawn(move || {
40 | | client_manager.nothing();
41 | | });
| |______________________- argument requires that borrow lasts for `'static`
42 | }
| - temporary value is freed at the end of this statement
I understood why this error happened. My question is:
1) I use Arc by following some tutorials online. (Example) But why do their examples work but not mine?
2) How can I fix this error in my situation? (I still want to share the object client_manager).
thread::spawn takes a closure that is 'static, meaning that it cannot borrow data from outside the thread. However, this line will clone the Arc and borrow it, and passing the borrowed reference into the thread:
let client_manager = &mut self.client_managers.clone();
thread::spawn(move || {
client_manager.do_something();
// ^-- client_manager is a `&mut Arc<_>` borrowed from outside the thread
});
Instead, what you want is to just clone the Arc, not borrow it in any way before its passed into the thread:
let client_manager = self.client_managers.clone();
thread::spawn(move || {
client_manager.do_something();
// ^-- client_manager is a `Arc<_>` owned by the new thread
});
The Arc has shared ownership over the value, so it is only destroyed once all Arc pointers referring to it falls out of scope, even across threads.

Cannot borrow as mutable in a loop when calling a closure that borrows as immutable?

Here is the code:
fn test(){
let mut numbers = vec![2];
let f = || {
for _ in numbers.iter(){
}
false
};
while false {
let res = f();
if res {
numbers.push(10);
}
}
}
The error is:
|
15 | let f = || {
| -- immutable borrow occurs here
16 | for _ in numbers.iter(){
| ------- first borrow occurs due to use of `numbers` in closure
...
22 | let res = f();
| - immutable borrow later used here
23 | if res {
24 | numbers.push(10);
| ^^^^^^^^^^^^^^^^ mutable borrow occurs here
But if I change the while keyword to if, it can be compiled. How to fix this? I want to call the anonymous function in a loop.
We can simplify your example even more by replacing the closure by a simple immutable reference
let mut numbers = vec![2];
let r = &numbers;
while false {
println!("{:?}", r);
numbers.push(10);
}
Here we get this error:
error[E0502]: cannot borrow `numbers` as mutable because it is also borrowed as immutable
--> src/lib.rs:7:5
|
3 | let r = &numbers;
| -------- immutable borrow occurs here
...
6 | println!("{:?}", r); // use reference
| - immutable borrow later used here
7 | numbers.push(10);
| ^^^^^^^^^^^^^^^^ mutable borrow occurs here
And like in your example, replacing the while with if makes the error go away. Why?
You probably know about the important Rust rule: Aliasing nand mutability. It states that, at any given time, a value can either be borrowed immutably arbitrarily many times or mutably exactly once.
The statement numbers.push(10) borrows numbers mutably temporarily (just for the statement). But we also have r which is an immutable reference. In order for numbers.push(10) to work, the compiler has to make sure that no other borrow exists at that time. But there exists the reference r! This reference cannot exist at the same time as numbers.push(10) exists.
Let's see for the if case first:
let mut numbers = vec![2];
let r = &numbers; // <------+ (creation of r)
// |
if false { // |
println!("{:?}", r); // <------+ (last use of r)
numbers.push(10);
}
While the lexical scope means the variable r is only dropped at the end of the function, due to non-lexical lifetimes, the compiler can see that the last use of r is in the println line. Then the compiler can mark r as "dead" after this line. And this in turn means, that there is no other borrow in the line numbers.push(10) and everything works out fine.
And for the loop case? Let's imagine the loop iterating three times:
let mut numbers = vec![2];
let r = &numbers; // <------+ (creation of r)
// |
// First iteration // |
println!("{:?}", r); // |
numbers.push(10); // | <== oh oh!
// |
// Second iteration // |
println!("{:?}", r); // |
numbers.push(10); // |
// |
// Third iteration // |
println!("{:?}", r); // <------+ (last use of r)
numbers.push(10);
As can be seen here, the time in which r is active overlaps numbers.push(10) (except the last one). And as a result, the compiler will produce an error because this code violates the central Rust rule.
And the explanation is the same for your closure case: the closure borrows numbers immutably and f(); uses that closure. In the loop case, the compiler is not able to shrink the "alive time" of the closure enough to make sure it doesn't overlap the mutable borrow for push.
How to fix?
Well, you could pass numbers into the closure each time:
let mut numbers = vec![2];
let f = |numbers: &[i32]| {
for _ in numbers.iter(){
}
false
};
while false {
let res = f(&numbers);
if res {
numbers.push(10);
}
}
This works because now, numbers is borrowed immutably also just temporarily for the f(&numbers); statement.
You can also use a RefCell as the other answer suggested, but that should be a last resort.
It's not exactly sure what you're trying to accomplish, but one way to solve this, without changing your code too drastically, would be to use std::cell::RefCell (described in the std and in the book):
use std::cell::RefCell;
fn test(){
let numbers = RefCell::new(vec![2]);
let f = || {
for _ in numbers.borrow().iter(){
}
false
};
while false {
let res = f();
if res {
numbers.borrow_mut().push(10);
}
}
}
Here's a little bit tweaked demo, which actually does something:
use std::cell::RefCell;
fn main() {
test();
}
fn test() {
let numbers = RefCell::new(vec![0]);
let f = || {
for n in numbers.borrow().iter() {
println!("In closure: {}", n);
}
println!();
true
};
let mut i = 1;
while i <= 3 {
let res = f();
if res {
numbers.borrow_mut().push(i);
}
i += 1;
}
println!("End of test(): {:?}", numbers.borrow());
}
Output:
In closure: 0
In closure: 0
In closure: 1
In closure: 0
In closure: 1
In closure: 2
End of test(): [0, 1, 2, 3]
Rust Playground demo

Cannot borrow variable as mutable more than once at a time [duplicate]

This question already has answers here:
How to update-or-insert on a Vec?
(2 answers)
Returning a reference from a HashMap or Vec causes a borrow to last beyond the scope it's in?
(1 answer)
Closed 5 years ago.
I'm trying to implement a trie but the borrow checker is really giving me a hard time:
struct Node {
// a trie node
value: char,
children: Vec<Node>,
}
impl Node {
fn add_child(&mut self, value: char) -> &mut Node {
// adds a child to given node
let vec: Vec<Node> = Vec::new();
let node = Node {
value,
children: vec,
};
self.children.push(node);
self.children.last_mut().unwrap()
}
fn get_child(&mut self, value: char) -> Option<&mut Node> {
// checks if given node has a child with given value, returns the child if it exists
for child in self.children.iter_mut() {
if child.value == value {
return Some(child);
}
}
None
}
fn has_child(&self, value: char) -> bool {
for child in self.children.iter() {
if child.value == value {
return true;
}
}
false
}
fn add_word(&mut self, word: String) {
let mut cursor = self;
for c in word.chars() {
match cursor.get_child(c) {
Some(node) => cursor = node,
None => cursor = cursor.add_child(c),
}
}
cursor.add_child('~');
}
}
The add_word method gives these 5 errors:
error[E0499]: cannot borrow `*cursor` as mutable more than once at a time
--> src/main.rs:41:19
|
41 | match cursor.get_child(c) {
| ^^^^^^ mutable borrow starts here in previous iteration of loop
...
47 | }
| - mutable borrow ends here
error[E0506]: cannot assign to `cursor` because it is borrowed
--> src/main.rs:42:31
|
41 | match cursor.get_child(c) {
| ------ borrow of `cursor` occurs here
42 | Some(node) => cursor = node,
| ^^^^^^^^^^^^^ assignment to borrowed `cursor` occurs here
error[E0506]: cannot assign to `cursor` because it is borrowed
--> src/main.rs:43:25
|
41 | match cursor.get_child(c) {
| ------ borrow of `cursor` occurs here
42 | Some(node) => cursor = node,
43 | None => cursor = cursor.add_child(c),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `cursor` occurs here
error[E0499]: cannot borrow `*cursor` as mutable more than once at a time
--> src/main.rs:43:34
|
41 | match cursor.get_child(c) {
| ------ first mutable borrow occurs here
42 | Some(node) => cursor = node,
43 | None => cursor = cursor.add_child(c),
| ^^^^^^ second mutable borrow occurs here
...
47 | }
| - first borrow ends here
error[E0499]: cannot borrow `*cursor` as mutable more than once at a time
--> src/main.rs:46:9
|
41 | match cursor.get_child(c) {
| ------ first mutable borrow occurs here
...
46 | cursor.add_child('~');
| ^^^^^^ second mutable borrow occurs here
47 | }
| - first borrow ends here
This is the Go code that I was trying to translate:
func (n *trieNode) AddWord(word string) {
cursor := n
for i := 0; i < len(word); i++ {
if cursor.HasChild(byte(word[i])) == nil {
cursor = cursor.AddChild(byte(word[i]))
} else {
cursor = cursor.HasChild(byte(word[i]))
}
}
// tilde indicates the end of the word
cursor.AddChild(byte('~'))
}

Resources