I want to be able to pass an mutable reference to function, but catch unwinds that may come from that function. The purpose is for use in writing some test wrappers (setup, teardown), not general error handling.
If I were using typical sync code, I can get this to compile and work...
struct MyStruct {
n: u32
}
fn my_func(s: &mut MyStruct) {
s.n += 1;
panic!("Oh no!");
}
fn main() {
let mut ctx = MyStruct { n: 1 };
let mut wrapper = std::panic::AssertUnwindSafe(&mut ctx);
let result = std::panic::catch_unwind(move || {
my_func(*wrapper);
});
// Do some cleanup of `ctx` here.
if let Err(err) = result {
std::panic::resume_unwind(err);
}
}
However, I haven't been able to figure out how to do this using futures and async/await. In that case, I would be trying to call a function that has been declared as async. I have tried various things like the code below:
async fn run_async(s: &mut MyStruct) {
s.n += 1;
panic!("Oh no!");
}
#[tokio::main]
async fn main() {
let mut ctx = MyStruct { n : 1 };
let wrapper = std::panic::AssertUnwindSafe(&mut ctx);
let result = async move {
run_async(*wrapper).catch_unwind().await
}.await;
println!("{:?}", result);
}
However, I typically will end up with an error such as:
the type
&mut MyStructmay not be safely transferred across an unwind boundary`.
I was under the belief that AssertUnwindSafe was supposed to help with these problems, as they did with the sync code. But there is obviously something I'm not understanding at the intersection of AssertUnwindSafe and the async/await.