I’m building a toy interpreter, and I’m trying to fold
over a vector while modifying a mutable reference. I’m not too sure how to do this though, I’m receiving lifetime errors when i call thing.eval
.
use self::EvalResult::*;
struct Env {}
enum EvalResult<'a> {
Something(&'a str),
Nothing,
}
struct Statement {}
impl Statement {
fn eval<'a, 'b>(&self, env: &'b mut Env) -> EvalResult<'b> {
unimplemented!()
}
}
fn eval_statements<'b>(vec: Vec<Statement>, env: &'b mut Env) -> EvalResult<'b> {
let closure = |acc: EvalResult, thing: &Statement| thing.eval(env);
vec.iter().fold(Nothing, closure)
// Using traditional for loops doesn't work as well
//
// let mut result = Nothing;
// for thing in self.vec.iter() {
// result = thing.eval(env);
// }
// result
}
Errors:
Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'b in function call due to conflicting requirements
--> src/lib.rs:19:62
|
19 | let closure = |acc: EvalResult, thing: &Statement| thing.eval(env);
| ^^^^
|
note: first, the lifetime cannot outlive the lifetime as defined on the body at 19:19...
--> src/lib.rs:19:19
|
19 | let closure = |acc: EvalResult, thing: &Statement| thing.eval(env);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:19:67
|
19 | let closure = |acc: EvalResult, thing: &Statement| thing.eval(env);
| ^^^
note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 18:20...
--> src/lib.rs:18:20
|
18 | fn eval_statements<'b>(vec: Vec<Statement>, env: &'b mut Env) -> EvalResult<'b> {
| ^^
= note: ...so that the expression is assignable:
expected EvalResult<'b>
found EvalResult<'_>
error: aborting due to previous error
For more information about this error, try `rustc --explain E0495`.
error: Could not compile `playground`.
To learn more, run the command again with --verbose.
My understanding is that somehow when closure
is passed to fold
, the compiler adds the following lifetime annotations:
fn anonymous<'a>(acc: EvalResult<'a>, thing: &'a Statement) -> EvalResult<'a> {
}
However, because of thing.eval
requiring a different lifetime ('b
of env: &'b mut Env
), the compiler error happens. How can I work around this and “tie” the result of the closure to 'b
instead?