That’s exactly what the crate I was about to publish allowed to write:
use ::call_on_drop::*;
let mut x = 0;
let foo = CallOnDrop::new(|| x = 42);
let ret = this_may_panic();
// uncomment the following if you want the closure to only be called in case of panic/unwinding
// foo.drop_silently();
ret
While also providing a macro:
use ::call_on_drop::*;
let mut x = 0;
may_panic!({
this_may_panic()
} finally {
x = 42
})
But, again, that’s what ::scopeguard already does, and on top of that it does it better, since it allows to solve the mut ref problem with an explicit environment capture that allows the guard to DerefMut into it, allowing to write something along these lines:
let mut x: i32 = 0;
let ret = {
/* to work with x, a mutable reference suffices,
so we give an exclusive ref to the Drop struct,
and shadow the unusable x with a mutable reference */
let x: &mut i32 = *with_Drop(&mut x, |slf| *slf = 42);
this_may_panic(&mut *x)
};
assert_eq!(x, 42_i32);
ret