I get a compilation error related to lifetimes that I'm having trouble undersanding. Perhaps one of you can help? Here's the code (I pared it down as best I could):
use std::collections::HashMap;
pub enum BaseError {
TBD,
}
#[derive(Debug, Clone, PartialEq)]
pub enum RawValue {
TBD,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Value<'a> {
Sequence(&'a Vec<Value<'a>>),
}
#[derive(Debug, Clone, PartialEq)]
pub enum InternalValue<'a> {
Base(Value<'a>),
ToBeDerived(RawValue),
TBD,
}
pub enum ThingError {
InvalidPath,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Thing<'a> {
data: HashMap<String, InternalValue<'a>>,
}
impl<'a> Thing<'a> {
fn derive(&self, _node: &RawValue) -> Result<InternalValue, ThingError> {
todo!("derive");
}
fn use_path(&mut self, _node: &RawValue) -> Result<InternalValue, ThingError> {
todo!("use_path");
}
pub(crate) fn compute_path(&self, _s: &str) -> Result<RawValue, BaseError> {
todo!("compute_path");
}
pub fn get(&mut self, key: &str) -> Result<Value, ThingError> {
let iv = match self.data.get(key) {
None => {
match self.compute_path(key) {
Err(_) => Err(ThingError::InvalidPath),
Ok(node) => self.use_path(&node),
}
}
Some(v) => Ok(v.clone()),
};
match iv {
Err(e) => Err(e),
Ok(v) => match v {
InternalValue::Base(cv) => Ok(cv),
InternalValue::ToBeDerived(av) => {
let _v = self.derive(&av);
todo!("handle v");
}
_ => todo!("other cases"),
},
}
}
}
Errors:
Compiling playground v0.0.1 (/playground)
error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
--> src/lib.rs:62:30
|
46 | pub fn get(&mut self, key: &str) -> Result<Value, ThingError> {
| - let's call the lifetime of this reference `'1`
...
51 | Ok(node) => self.use_path(&node),
| ---- mutable borrow occurs here
...
60 | InternalValue::Base(cv) => Ok(cv),
| ------ returning this value requires that `*self` is borrowed for `'1`
61 | InternalValue::ToBeDerived(av) => {
62 | let _v = self.derive(&av);
| ^^^^ immutable borrow occurs here
error: aborting due to previous error
For more information about this error, try `rustc --explain E0502`.
error: could not compile `playground`.
To learn more, run the command again with --verbose.
I understand that the problem is due to line 60, as the message says, but what isn't clear to me is why, and how to get around it. Commenting out that line allows compilation to complete, but that isn't what I want.
Basically, an internal hash map holds values that are either "base" or "derived", and if they are "derived", some additional computation needs to happen. I've no problem using references, cloning returned values etc. but I'm just not sure where I need to apply those - applying in the obvious places hasn't made a difference, but maybe what's obvious to me isn't obvious enough!