Hello,
I've been working on a project that takes input over a socket connection (set up using socketioxide and axum) and evaluates it using an interpreter for a language I'm working on. I've been fighting lifetime issues pretty much all day in the interpreter, but got stuff to work for the most part.
Until now. When i pass my ast
variable into the interpreter, i get the compiler error saying "borrowed value does not live long enough" (borrowed value being the ast). The interp function i use takes in the ast as a reference and if i change that, I'd have to change a lot of my project. I just don't know what to do to make ast live longer.
Please note that nearly all the logic here is done in the closure passed to the socket.on()
method. I was thinking of maybe replacing the closure with an Fn and indicating lifetimes there? But maybe there is another way.
Also, I'm not sure if my use of .leak()
is proper or not, but it got rid of some other lifetime issues. I just want this part to work and in the future I will come back and fix this up to make it better.
async fn on_connect(socket: SocketRef) {
info!("socket connected: {}{}{}", BLUE, socket.id, DFLT);
let env: Arc<Mutex<HashMap<String, LalaType>>> = Arc::new(Mutex::new(HashMap::new()));
let env_clone = Arc::clone(&env);
socket.on("run", move |s: SocketRef, Data::<Cell>(data)| {
let mut env = env_clone.lock().unwrap();
info!("Received message from {}{}{}: {:?}", BLUE, s.id, DFLT, data);
let input = data.cell_text.leak();
let ast: Vec<Box<parser::AstNode>> = parser::parse(input).unwrap();
let response = interp(&ast, Some(&mut *env), true).unwrap();
let output = CellOutput {
output: response
};
info!("Sending message to {}{}{}: {:?}", BLUE, s.id, DFLT, output);
let _ = s.emit("output", output);
});
}
Here's the full error:
error[E0597]: `ast` does not live long enough
--> src/main.rs:57:31
|
55 | let ast: Vec<Box<parser::AstNode>> = parser::parse(input).unwrap();
| --- binding `ast` declared here
56 |
57 | let response = interp(&ast, Some(&mut *env), true).unwrap();
| ^^^^ borrowed value does not live long enough
...
67 | });
| -
| |
| `ast` dropped here while still borrowed
| borrow might be used here, when `env` is dropped and runs the `Drop` code for type `std::sync::MutexGuard`
|
= note: values in a scope are dropped in the opposite order they are defined
I'm really just at a loss now. I'd really appreciate some help because I just want this to work; I dont want to think a poor design choice I made 9 months ago when i first wrote the interpreter and parser is gonna end up messing me up now.
All the code is also on github and can be found here.
Again, any help is appreciated. I've never had as many issues with lifetimes in the past year that i've been learning rust than i have today.