I am considering ways to implement borrowed type / type with lifetime for GitHub - fzyzcjy/flutter_rust_bridge: Flutter/Dart <-> Rust binding generator, feature-rich, but seamless and simple. (Rust <-> Dart/Flutter). Roughly speaking, the scenario is that:
Suppose we have a Rust function
fn f(a: &MyStruct) -> &MySubStruct {
&a.field
}
The current generated code looks like:
let a: Arc<RwLock<MyStruct>> = it_is_gotten_from_dart();
let a_read_guard = a.read();
let output = f(a_read_guard);
give_it_to_dart(output);
If there is no lifetime or reference type, then everything is good. However, since output
is of type &MySubStruct
, if we want to give it to Dart naively, Rust compiler will (correctly) realize it needs to live shorter than the guard, and thus cause troubles.
One simple way is to do something like:
let pack: (ReadGuard, &MySubStruct) = (a_read_guard, output);
give_it_to_dart(Box::leak(Box::new(pack)));
i.e. if we leak the guard together with the reference, and ensure the reference is dropped before the guard is dropped, then we are safe.
However, in safe Rust, it seems we cannot do something like above (cannot move the guard when it is referred). It seems possible to do with some unsafe code (e.g. maybe an Arc<ReadGuard>
, or maybe a self referential type?). But I wonder, is there a best practice / prior art when dealing with things like this?
Thanks for any suggestions!