I'm trying to implement the 3rd bullet point from chapter 8.3, with a difference that an employee can be added to multiple departments.
#[cfg(test)]
mod company {
use std::collections::HashMap;
struct Company<'a> {
employees: HashMap<String, Employee>,
departments: HashMap<String, Department<'a>>,
}
struct Department<'a> {
name: String,
employees: HashMap<&'a str, &'a Employee>,
}
struct Employee {
name: String,
}
impl<'a> Company<'a> {
pub fn new() -> Company<'a> {
Company {
employees: HashMap::new(),
departments: HashMap::new(),
}
}
pub fn add_employee_to_department(&'a mut self, employee: &str, department: &str) {
let d = self.departments.entry(String::from(department)).or_insert(Department::new(department));
let e = self.employees.entry(String::from(employee)).or_insert(Employee::new(employee));
d.employees.entry(&e.name).or_insert(e);
}
}
impl<'a> Department<'a> {
pub fn new(name: &str) -> Department<'a> {
Department {
name: String::from(name),
employees: HashMap::new(),
}
}
}
impl Employee {
fn new(name: &str) -> Employee {
Employee {
name: String::from(name),
}
}
}
#[test]
fn test_add_employee_to_department() {
let mut c = Company::new();
c.add_employee_to_department("Sally", "Sales");
c.add_employee_to_department("Jim", "Sales");
}
}
When I compile, I get an error:
error[E0499]: cannot borrow `c` as mutable more than once at a time
--> src/company.rs:55:9
|
54 | c.add_employee_to_department("Sally", "Sales");
| ---------------------------------------------- first mutable borrow occurs here
55 | c.add_employee_to_department("Jim", "Sales");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| second mutable borrow occurs here
| first borrow later used here
If I remove lifetime 'a
from add_employee_to_department
pub fn add_employee_to_department(&mut self, employee: &str, department: &str) {
let d = self.departments.entry(String::from(department)).or_insert(Department::new(department));
let e = self.employees.entry(String::from(employee)).or_insert(Employee::new(employee));
d.employees.entry(&e.name).or_insert(e);
}
I get a different error:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/company.rs:29:36
|
29 | let e = self.employees.entry(String::from(employee)).or_insert(Employee::new(employee));
| ^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined here...
--> src/company.rs:27:43
|
27 | pub fn add_employee_to_department(&mut self, employee: &str, department: &str) {
| ^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/company.rs:29:21
|
29 | let e = self.employees.entry(String::from(employee)).or_insert(Employee::new(employee));
| ^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined here...
--> src/company.rs:19:10
|
19 | impl<'a> Company<'a> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/company.rs:30:50
|
30 | d.employees.entry(&e.name).or_insert(e);
| ^
And if I comment the last line in add_employee_to_department
pub fn add_employee_to_department(&mut self, employee: &str, department: &str) {
let d = self.departments.entry(String::from(department)).or_insert(Department::new(department));
let e = self.employees.entry(String::from(employee)).or_insert(Employee::new(employee));
//d.employees.entry(&e.name).or_insert(e);
}
the code compiles and the test runs.
I'm new to Rust and could be wrong here, but it seems the original error (cannot borrow 'c' as mutable more than once at a time
) is a bug in the borrow checker when a lifetime used with the first &'a self
parameter.
A simpler test shows the same problem. The code below compiles as is, but if I add lifetime 'a
to fn update(&'a mut self, value: &'a T)
, I get the same error: Cannot borrow 'w' as mutable more than once at a time
.
Any advise on what I'm doing wrong here would be greatly appreciated!
#[cfg(test)]
mod wrapper {
struct Wrapper<'a, T> {
value: &'a T,
}
impl<'a, T> Wrapper<'a, T> {
fn new(value: &T) -> Wrapper<T> {
Wrapper {
value,
}
}
fn value(&self) -> &T {
self.value
}
fn update(&mut self, value: &'a T) {
self.value = value;
}
}
#[test]
fn test_wrapper() {
let mut w = Wrapper::new(&12);
w.update(&14);
w.update(&16);
assert_eq!(w.value(), &16);
}
}