ho questo frammento che non passa il controllo prestito:non possono prendere in prestito come mutabile più di una volta in un momento in un codice -, ma può in un altro molto simile
use std::collections::HashMap;
enum Error {
FunctionNotFound
}
#[derive(Copy, Clone)]
struct Function<'a> {
name: &'a str,
code: &'a [u32]
}
struct Context<'a> {
program: HashMap<&'a str, Function<'a>>,
call_stack: Vec<Function<'a>>,
}
impl<'a> Context<'a> {
fn get_function(&'a mut self, fun_name: &'a str) -> Result<Function<'a>, Error> {
self.program.get(fun_name).map(|f| *f).ok_or(Error::FunctionNotFound)
}
fn call(&'a mut self, fun_name: &'a str) -> Result<(), Error> {
let fun = try!(self.get_function(fun_name));
self.call_stack.push(fun);
Ok(())
}
}
fn main() {
}
La mia sensazione è che il il problema è legato al fatto che HashMap
restituisce None
o un riferimento del valore all'interno della struttura dati. Ma non voglio questo: la mia intenzione è che self.get_function
restituisca una copia in byte del valore memorizzato o un errore (ecco perché inserisco .map(|f| *f)
e).
La modifica di &'a mut self
in altro non aiuta.
Tuttavia, il seguente frammento, in qualche modo simile nello spirito, è accettato:
#[derive(Debug)]
enum Error {
StackUnderflow
}
struct Context {
stack: Vec<u32>
}
impl Context {
fn pop(&mut self) -> Result<u32, Error> {
self.stack.pop().ok_or(Error::StackUnderflow)
}
fn add(&mut self) -> Result<(), Error> {
let a = try!(self.pop());
let b = try!(self.pop());
self.stack.push(a + b);
Ok(())
}
}
fn main() {
let mut a = Context { stack: vec![1, 2] };
a.add().unwrap();
println!("{:?}", a.stack);
}
Così ora sono confuso. Qual è il problema con il primo snippet? (e perché non succede nel secondo?)
I frammenti fanno parte di un codice più grande. Per fornire più contesto, this su Rust Playground mostra un esempio più completo con il codice errato e this mostra una versione precedente senza HashMap, che supera il controllo del prestito e viene eseguito normalmente.
Non credo che 'fun_name' debba avere una vita intera. – o11c
il tuo secondo snippet non ha alcuna durata, quindi non si qualifica per "simile" –