Context: I want to integrate Rhai scripts to my application and modify host data from Rhai scripts. But there is a problem with happens due to combination of 2 factors:
Rhai runtime accepts only owned values that implement Clone and 'static (so it can store it in Scope context that can live arbitrarily long). It doesn't accept non-static references.
My data is stored in special storage and I don't want to move it from it (because it can be expensive).
I created call_with_ref function using inspiration from std::thread::scope and WeakRef struct that serves as runtime mutable reference that tracks lifetime of borrowed reference in runtime so can implement 'static and be given to Rhai runtime.
No, this is unsound because you can smuggle the WeakRef and a reference obtained from it outside the closure and then accessed after the closure ends, resulting in overlapping borrows. The is_alive mechanism does not prevent this because the borrow from the WeakRef can be obtained before the closure returns, where is_alive is still true. Rust Playground
To fix this you will have to abort the process if the WeakRef has not been dropped after the closure returned. A panic won't be enough since they can be caught and variables are still dropped. As an alternative, you could provide callback based APIs to WeakRef instead of methods that return references.
error[E0521]: borrowed data escapes outside of closure
--> src/main.rs:80:34
|
75 | let mut data_ref = None;
| ------------ `data_ref` declared here, outside of the closure body
...
80 | .visit_mut_alive(|x| data_ref = Some(x));
| - ^^^^^^^^^^^^^^^^^^ `x` escapes the closure body here
| |
| `x` is a reference that is only valid in the closure body
For more information about this error, try `rustc --explain E0521`.