Borrows do not "go out of scope"; they persist until they are no longer used.
I'm not sure why exactly your code won't compile but I noticed some weird things about it that might mean it's not doing what you expect. Here's a lightly edited version of activate
that has the same problem:
pub fn activate(&mut self, input: &ContextType) {
// I'm just going to put this in a variable so I can more easily talk about the following line
let key = (
&self.dat,
match self.stack.len() {
0 => None,
_ => Some(&self.stack[self.stack.len() - 1]),
},
input,
);
let (stack_action, val_action) = (&self.table.get(&key)).unwrap();
match stack_action {
StackAction::Pop => {
self.stack.pop();
}
StackAction::Push(x) => self.stack.push(x.clone()),
_ => {}
};
self.dat = val_action.clone();
}
The weirdness is concentrated in this line:
let (stack_action, val_action) = (&self.table.get(&key)).unwrap();
First, HashMap::get
returns an Option<&V>
. Then you take a &
reference to it, so you have &Option<&V>
-- this in itself is weird because there's not really a good reason for it. The next thing you do is call .unwrap()
, which dereferences the &
to make a copy of the Option
which it then unwraps to &V
. This is a little more weird because you generally can't call .unwrap()
on a &Option<_>
. The only reason it works is because Option<&V>
is Copy
, but that doesn't seem relevant to what you're doing -- you could have just written self.table.get(&key).unwrap()
. Maybe you were trying to express something that got a little lost in translation.
Then, &V
is actually &(StackAction<T>, Option<T>)
. You assign this to (stack_action, val_action)
. This compiles because of "pattern ergonomics" which is non-obvious but what it does is make stack_action
a &StackAction<T>
and val_action
an &Option<T>
, i.e. they reference the values that are still owned by self.table
, instead of being moved out. Is this what you meant to do or did you expect stack_action
and val_action
to be owned values?