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

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('~'))
}

Related

use an object inside a closure which is passed to a method of that object

i have a struct Screen with its implementation
pub struct Screen {
stdin: Stdin,
// types are irrelevant
stdout: MouseStdout,
}
impl Screen {
// ...
pub fn handle_keys_loop<F: FnMut(&Event) -> ()>(
&self,
mut handler: F,
) {
let stdin = stdin();
for e in stdin.events() {
let e = e.unwrap();
match e {
Event::Key(Key::Ctrl('c')) => break,
_ => {
handler(&e);
},
}
}
}
}
and usage (which is wrong and know it)
let mut screen = Screen::new();
screen.init_screen();
screen.handle_keys_loop(|event| {
match event {
Event::Key(Key::Char('a')) => {
screen.println("hello there",15, 1, true);
},
_ => {}
}
});
screen.end_screen();
the error is
error[E0502]: cannot borrow `screen` as mutable because it is also borrowed as immutable
--> src/bin/terminal.rs:74:29
|
74 | screen.handle_keys_loop(|event| {
| - ---------------- ^^^^^^^ mutable borrow occurs here
| | |
| _____| immutable borrow later used by call
| |
75 | | match event {
76 | | Event::Key(Key::Char('a')) => {
77 | | println!("{} {} {} {}", "do something with a", 15, 1, true);
78 | | // tried to borrow as mutable
79 | | screen.println("hello there",15, 1, true);
| | ------ second borrow occurs due to use of `screen` in closure
... |
82 | | }
83 | | });
| |______- immutable borrow occurs here
and if i make self mut inside handle_keys_loop to get rid of cannot borrow screen as mutable because it is also borrowed as immutable
pub fn handle_keys_loop<F: FnMut(&Event) -> ()>(
+ &mut self,
- &self
....
i get this error
error[E0499]: cannot borrow `screen` as mutable more than once at a time
--> src/bin/terminal.rs:74:29
|
74 | screen.handle_keys_loop(|event| {
| - ---------------- ^^^^^^^ second mutable borrow occurs here
| | |
| _____| first borrow later used by call
| |
75 | | match event {
76 | | Event::Key(Key::Char('a')) => {
77 | | screen.println("hello there",15, 1, true);
| | ------ second borrow occurs due to use of `screen` in closure
... |
80 | | }
81 | | });
| |______- first mutable borrow occurs here
what im trying to do: use the method handle_keys_loop of screen and pass screen inside the closure, which is passed to handle_keys_loop. basically, to use screen inside of screen.
how do i achieve that ?
some people told me to use RefCell, but that didnt work out very well, i got BorrowError.
i will use any workaround to just use screen inside the closure which is passed to screen's method.
thanks in advance.
One pattern I use to handle such a situation is to pass self: &mut Self back into the closure from handle and use that inside the closure. A simplified version of your code:
struct Screen {}
struct Event {}
impl Screen {
fn handle<F: FnMut(&mut Screen, Event)>(&mut self, mut handler: F) {
handler(self, Event {})
}
fn print(&mut self) {}
}
fn main() {
let mut screen = Screen {};
screen.handle(|screen, _event| screen.print());
screen.handle(|screen, _event| screen.print());
}
You can't do what you're trying to do because it violates Rust's rule that you can't mutate a value while something else has access to it.
However, your handle_keys_loop method doesn't even use self which means the &self parameter is redundant. There's no reason to give a function an argument it's not going to use (except when implementing a trait that requires it).
Just remove the argument:
pub fn handle_keys_loop<F: FnMut(&Event) -> ()>(
mut handler: F,
) {
And call it as Screen::handle_keys_loop(|event| { ... }).
Alternatively, make it a free function, external to Screen entirely, since it doesn't depend on Screen in any way.

How can I let one struct contains another struct and a value produced by that struct in Rust?

Actually the lexer's get_next_token will return a Token which has no relation to the lexer.
But the get_next_token method would borrow "mut self", so the compiler kept yelling "cannot return value referencing function parameter lexer".
How can I deal with it???????
// in impl lexer
fn get_next_token(&mut self) -> Token {
let mut result = None;
while self.current_char != None {
match self.current_char {
// editing result
}
}
if let Some(token) = result {
token
} else {
Token::new(EOF, Nil)
}
}
struct Intepreter<'a> {
lexer: Lexer<'a>,
current_token: Token<'a>
}
impl<'a> Intepreter<'a> {
fn new(mut lexer: Lexer<'a>) -> Intepreter {
let current_token = lexer.get_next_token();
Intepreter {
lexer: lexer,
current_token // error!
}
}
}
error[E0515]: cannot return value referencing function parameter `lexer`
--> src\main.rs:134:9
|
133 | let current_token = lexer.get_next_token();
| ---------------------- `lexer` is borrowed here
134 | / Intepreter {
135 | | lexer: lexer,
136 | | current_token
137 | | }
| |_________^ returns a value referencing data owned by the current function
error[E0505]: cannot move out of `lexer` because it is borrowed
--> src\main.rs:135:20
|
131 | impl<'a> Intepreter<'a> {
| -- lifetime `'a` defined here
132 | fn new(mut lexer: Lexer<'a>) -> Intepreter {
133 | let current_token = lexer.get_next_token();
| ---------------------- borrow of `lexer` occurs here
134 | / Intepreter {
135 | | lexer: lexer,
| | ^^^^^ move out of `lexer` occurs here
136 | | current_token
137 | | }
| |_________- returning this value requires that `lexer` is borrowed for `'a`

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 do we return a reference to a HashMap value from a method in a struct that owns the HashMap? [duplicate]

This question already has answers here:
HashMap borrow issue when trying to implement find or insert
(2 answers)
How to lookup from and insert into a HashMap efficiently?
(2 answers)
Closed 4 years ago.
Consider the following attempt to make a function memoizer (playground link):
use std::collections::HashMap;
pub struct Cacher<F, IN, OUT> {
function: F,
cache: HashMap<IN, OUT>,
}
impl<F, IN, OUT> Cacher<F, IN, OUT>
where
F: Fn(IN) -> OUT,
IN: std::cmp::Eq + std::hash::Hash + std::marker::Copy,
OUT: std::marker::Copy,
{
fn new(function: F) -> Cacher<F, IN, OUT> {
Cacher {
function: function,
cache: HashMap::new(),
}
}
fn at(&mut self, arg: IN) -> &OUT {
match self.cache.get(&arg) {
None => {
let val = (self.function)(arg);
self.cache.insert(arg, val);
&val // FAIL!
}
Some(val) => val,
}
}
}
The at method fails to compile:
error[E0597]: `val` does not live long enough
--> src/lib.rs:26:18
|
26 | &val // FAIL!
| ^^^ borrowed value does not live long enough
27 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 21:5...
--> src/lib.rs:21:5
|
21 | / fn at(&mut self, arg: IN) -> &OUT {
22 | | match self.cache.get(&arg) {
23 | | None => {
24 | | let val = (self.function)(arg);
... |
29 | | }
30 | | }
| |_____^
error[E0502]: cannot borrow `self.cache` as mutable because it is also borrowed as immutable
--> src/lib.rs:25:17
|
22 | match self.cache.get(&arg) {
| ---------- immutable borrow occurs here
...
25 | self.cache.insert(arg, val);
| ^^^^^^^^^^ mutable borrow occurs here
...
30 | }
| - immutable borrow ends here
My understanding is that in the case that the value must be computed, the returned &val isn't known to live long enough.
I tried a few things to explain to the compiler that the returned &val should be expected to live as long as the Cacher that contains it, but so far I have not succeeded.
How do we give the compiler the required information about &val's lifetime?

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

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).

Resources