I've run into a specific lifetime issue in Rust that I cannot wrap my head around, after taking a look at this post, this post, and several other similar ones. In particular, I have these structs & associated implementations:
use std::collections::hash_map::HashMap;
use std::mem;
pub struct JsVar {
binding: String,
}
pub struct Scope<'a> {
pub vars: Vec<JsVar>,
locals: HashMap<String, &'a JsVar>,
}
impl<'a> Scope<'a> {
pub fn new() -> Scope<'a> {
Scope {
vars: Vec::new(),
locals: HashMap::new(),
}
}
pub fn rebind_var(&'a mut self, var: JsVar) {
self.vars.push(var);
let var_ref: &'a JsVar = match self.vars.last() {
Some(var) => var,
None => unreachable!(),
};
self.locals.insert(var_ref.binding.clone(), var_ref);
}
}
pub struct ScopeManager<'a> {
scopes: Vec<Scope<'a>>,
}
impl<'a> ScopeManager<'a> {
pub fn pop_scope(&'a mut self, gc_yield: bool) -> Result<(), String> {
if let Some(mut scope) = self.scopes.pop() {
// Actual code snipped for brevity; this is the relevant operation.
let mut vars = mem::replace(&mut scope.vars, Vec::new());
let mut parent: &mut Scope<'a> = self.scopes.last_mut().unwrap();
while let Some(var) = vars.pop() {
parent.rebind_var(var);
}
Ok(())
} else {
Err(String::from("Bad Scope"))
}
}
}
The compiler complains
cannot borrow *parent as mutable more than once at a time
on the line that reads parent.rebind_var(var)
, which I think is due to the 'a
lifetime annotation on self
in the method definition, which causes parent
to be borrowed for the length of the entire method. However, if I remove the 'a
, then the compiler is unable to infer an appropriate lifetime for self.scopes
on the line where parent
is bound. Based on this information, I don't understand
- how to make
parent
not bound to the lifetime ofself
and - still be able to bind
parent
such that its lifetime is correct.