New Rust programmer here,
I'm writing an algorithm in Rust to pull a mutable reference to a particular node of an AST. I'm using the syn
crate for AST processing. The algorithm is looking for a function defined within a series of nested modules, whose order and names are specified by the keys
parameter. I'm currently implementing it recursively. However, because I need the returned reference to be mutable, Rust's rules allow only one mutable reference to an object at a time, so the algorithm won't compile.
code:
/// walk the syntax tree of the contracts specified vector of items
/// side-effect: `keys` contains the remaining tokens of the contract's summary key that
/// need definition
fn find_next_module<'a>(items: &'a mut Vec<Item>, keys: &mut Vec<&str>) -> Option<&'a mut Vec<Item>>
{
let key = keys.pop().expect("should not be called on an empty keys");
println!("processing key {}", key);
println!("keys: {:?}", keys);
for item in items.iter_mut()
{
println!("processing item {:?}", item);
if keys.is_empty() &&
is_contract_definition(item.clone(), key)
{
//we found the last level of the key, and it is present.
// so we don't need to do anything
return None;
}
else if let Item::Mod(modl) = item.borrow_mut()
{
if format!("{}", modl.ident) == key
{
if let Some((_, cont))= modl.content.borrow_mut()
{
return find_next_module(cont, keys);
}
}
}
}
//we didn't find the next key. return this set of items to insert the contract into
keys.push(key);
return Some(items);
}
compile error:
error[E0499]: cannot borrow `*items` as mutable more than once at a time
--> src/main.rs:91:17
|
62 | fn find_next_module<'a>(items: &'a mut Vec<Item>, keys: &mut Vec<&str>) -> Option<&'a mut Vec<Item>>
| -- lifetime `'a` defined here
...
67 | for item in items.iter_mut()
| ----- first mutable borrow occurs here
...
83 | return find_next_module(cont, keys);
| ---------------------------- returning this value requires that `*items` is borrowed for `'a`
...
91 | return Some(items);
| ^^^^^ second mutable borrow occurs here
For more information about this error, try `rustc --explain E0499`.
error: could not compile `gen_contracts` (bin "gen_contracts") due to 1 previous error
I'm pretty sure that the problem is that the recursive call pushes a new mutable reference to the same object to the call stack, without deleting the existing mutable reference, causing the Rust borrow rules to be violated. I've tried using RefCell
s, but didn't have success there. I'm pretty sure there's something I'm not understanding about using RefCell
s.
How would one work around this? Is there a way to make the lifetime more granular so that the mut references in the recursive calls don't overlap?
Thank you!