After a long battle with ownership, lifetime, move, and borrow errors, I'm down to an error in add_turtle_ref. The desired behavior is that add_turtle_ref adds the input tref to self.turtles, a Vec<TurtleRef>, and self.map, a HashMap<&str, Vec<TurtleRef>>.
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
#[derive(Clone)]
pub struct TurtleRef {
t: Rc<RefCell<Turtle>>,
}
impl TurtleRef {
pub fn new(r: Turtle) -> TurtleRef {
TurtleRef {
t: Rc::new(RefCell::new(r)),
}
}
}
pub struct Campus<'a> {
turtles: Vec<TurtleRef>,
map: HashMap<&'a str, Vec<TurtleRef>>,
}
impl Campus<'_> {
pub fn new() -> Campus<'static> {
Campus {
turtles: Vec::new(),
map: HashMap::new(),
}
}
pub fn size(&self) -> usize {
self.turtles.len()
}
pub fn add_turtle(&mut self, turtle: Turtle) {
self.add_turtle_ref(TurtleRef::new(turtle));
}
pub fn add_turtle_ref(&mut self, tref: TurtleRef) {
self.turtles.push(tref.clone());
let n = tref.t.borrow().name();
self.map.entry(n).or_insert(Vec::new()).push(tref.clone());
}
pub fn breed_turtles(&mut self, t1_index: usize, t2_index: usize, child_name: String) {
let n = self.size();
if t1_index > n - 1 || t2_index > n - 1 {
panic!("out of bounds");
}
let tref = Turtle::breed(
&mut self.turtles[t1_index].t.borrow_mut(),
&mut self.turtles[t2_index].t.borrow_mut(),
child_name,
);
self.add_turtle_ref(TurtleRef { t: tref });
}
}
#[derive(Debug)]
pub struct Turtle {
name: String,
children: Vec<Rc<RefCell<Turtle>>>,
}
impl Turtle {
pub fn new(name: String) -> Turtle {
Turtle {
name: name,
children: Vec::new(),
}
}
pub fn name(&self) -> &String {
&self.name
}
pub fn add_child(&mut self, t: Rc<RefCell<Turtle>>) {
self.children.push(t);
}
pub fn breed(t1: &mut Turtle, t2: &mut Turtle, name: String) -> Rc<RefCell<Turtle>> {
let s = Rc::new(RefCell::new(Turtle {
name: name,
children: Vec::new(),
}));
t1.add_child(Rc::clone(&s));
t2.add_child(Rc::clone(&s));
s
}
}
The error:
error[E0597]: `tref.t` does not live long enough
--> src/lib.rs:38:17
|
36 | pub fn add_turtle_ref(&mut self, tref: TurtleRef) {
| --------- has type `&mut Campus<'1>`
37 | self.turtles.push(tref.clone());
38 | let n = tref.t.borrow().name();
| ^^^^^^ borrowed value does not live long enough
39 | self.map.entry(n).or_insert(Vec::new()).push(tref.clone());
| ----------------- argument requires that `tref.t` is borrowed for `'1`
40 | }
| - `tref.t` dropped here while still borrowed
error[E0716]: temporary value dropped while borrowed
--> src/lib.rs:38:17
|
36 | pub fn add_turtle_ref(&mut self, tref: TurtleRef) {
| --------- has type `&mut Campus<'1>`
37 | self.turtles.push(tref.clone());
38 | let n = tref.t.borrow().name();
| ^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
39 | self.map.entry(n).or_insert(Vec::new()).push(tref.clone());
| ----------------- argument requires that borrow lasts for `'1`
I've tried all sorts of clever tricks such as obtaining the name, dereferencing it to a normal string, then turning the String back into a &String, but this just causes the Rust compiler to complain even faster: you can't dereference a string!