My code is like below and this is not the entire code.
The problem is about E507.
I tried to fix this problem but I couldn't
let mut map: HashMap<String, HashSet<String>> = HashMap::new();
fn parse_command(command: String) -> Vec<String> {
let mut parsed:Vec<String> = Vec::new();
for word in command.split_whitespace() {
parsed.push(word.to_string());
}
parsed
}
for command in commands {
let mut words = parse_command(command);
let verb = words[0].as_str();
match verb {
"Add" => {
let dept = words.pop().unwrap();
let to = words.pop();
let person = words.pop().unwrap();
let dept_set = map.get(&dept);
match dept_set { // error occurs here
Some(&(mut t)) => {
t.insert(person);
},
None => {
let mut set = HashSet::new();
set.insert(person);
map.insert(dept, set);
},
}
},
and the error message
error[E0507]: cannot move out of `*dept_set.0` which is behind a shared reference
|
260 | match dept_set {
| ^^^^^^^^
261 | Some(&(mut t)) => {
| -----
| |
| data moved here
| move occurs because `t` has type `HashSet<String>`, which does not implement the `Copy` trait
let dept_set = map.get_mut(&dept);
match dept_set {
Some(t) => {
t.insert(person);
}
...
}
It looks like you were trying to get a mutable reference inside the pattern, but that's not what & does in patterns. It actually works like * does in normal code, removing a reference. That was why you were getting an error about moving a variable.
Essentially you were declaring a mutable binding t that moved the hash set out of dept_set, but what you wanted was just to have a mutable reference in the first place.
I really appreciate to your kind reply.
But there occurs another issue.
"Move" => {
let to_dept = words.pop().unwrap();
let to = words.pop();
let from_dept = words.pop().unwrap();
let from = words.pop();
let person = words.pop().unwrap();
let to_dept_set = map.get_mut(&to_dept);
let from_dept_set = map.get_mut(&from_dept); // error occurs here
match (to_dept_set, from_dept_set) {
(Some(t), Some(u)) => {
if u.remove(&person) {
t.insert(person);
}
},
(_, _) => (),
}
},
This is actually the rest of my code, so I tried to fix it just like you let me know.
and complier gave an error like below
let to_dept_set = map.get_mut(&to_dept);
| --------------------- first mutable borrow occurs here
290 | let from_dept_set = map.get_mut(&from_dept);
| ^^^^^^^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
291 | match (to_dept_set, from_dept_set) {
| ----------- first borrow later used here
how can I fix this problem?
I'm so sorry bothering you....
if let Some(u) = map.get_mut(&from_dept) {
let removed = u.remove(&person);
if let Some(t) = map.get_mut(&to_dept) {
if removed {
t.insert(person);
}
}
}
In this case, the first two lines can be rewritten with a combinator:
if let Some(removed) = map.get_mut(&from_dept).map(|u| u.remove(&person)) {
if let Some(t) = map
.get_mut(&from_dept)
.map(|u| u.remove(&person)) // stop using `&mut HashMap` here
.and_then(|removed| if removed { map.get_mut(&to_dept) } else { None })
{
t.insert(person);
}
the lifetimes of map.get_mut's returned value don't overlap.
If .map is integrated into .and_then, you'll run into the same lifetime problem:
error[E0499]: cannot borrow `map` as mutable more than once at a time
--> src/lib.rs:43:15
|
41 | if let Some(t) = map
| __________________-
42 | | .get_mut(&from_dept)
| |________________________- first mutable borrow occurs here
43 | .and_then(|u| if u.remove(&person) { map.get_mut(&to_dept) } else { None })
| -------- ^^^ --- second borrow occurs due to use of `map` in closure
| | |
| | second mutable borrow occurs here
| first borrow later used by call