I am trying to make my own programming language in rust, and most features are done, so I thought I could add to the UnknownIdentifier error the ability to find the closest match to whatever the user wanted
However before I even got to finding the closest match I found out that cloning HashMap<String, Object> moves it into the closure
ErrorGenerator::error function:
#[allow(non_snake_case)]
mod ErrorGenerator {
pub fn error(name: &str, explanation: &str, line: usize, col: usize, file: String, after_f: Box<dyn Fn() -> ()>) -> ! {
eprintln!("\n[ERROR] {}, Line {:?}, Column {:?}", file, line, col);
eprintln!(" {}: {}", name, explanation);
after_f();
exit(1);
}
}
ErrorGenerator::error(
"UnknownIdentifier",
&format!("unknown identifier: `{}`, this identifier could not be found", tokenc.repr()),
tokenc.line,
tokenc.col,
tokenc.file,
Box::new(||{
let mut hashc: Vec<String> = hashs.clone().into_keys().collect();
hashc.sort();
}),
);
This is the error it gives:
error[E0597]: `hashs` does not live long enough
--> src/runtime/runtime.rs:960:70
|
959 | Box::new(||{
| - -- value captured here
| _____________________________________|
| |
960 | | let mut hashc: Vec<String> = hashs.clone().into_keys().collect();
| | ^^^^^ borrowed value does not live long enough
961 | | hashc.sort();
962 | | }),
| |______________________________________- cast requires that `hashs` is borrowed for `'static`
...
1203 | }
| - `hashs` dropped here while still borrowed
The problem's solution is probably either:
You can find the full code in https://github.com/kaiserthe13th/tr-lang/tree/unknown-id-err-impl
What happens is that the compiler doesn't clone hashs
then passes the clone to your callback; instead, it passes a reference to hashs
to your callback and clones it inside the callback.
However, the callback is required to be 'static
, and if it holds a reference to the containing function it is not! So the compiler is complaining.
What you want is to clone the hashmap before, then pass the clone to the callback. Like:
ErrorGenerator::error(
"UnknownIdentifier",
&format!("unknown identifier: `{}`, this identifier could not be found", tokenc.repr()),
tokenc.line,
tokenc.col,
tokenc.file,
{
let hashc = hashs.clone();
Box::new(|| {
let mut hashc: Vec<String> = hashc.into_keys().collect();
hashc.sort();
})
},
);
If you'll do that, you'll also recognize that the closure needs to be FnOnce()
since you're moving out of hashc
(.into_keys()
). So after_f: Box<dyn FnOnce()>
.