#![allow(unsafe_code, reason = "unsafe is needed to use bevy_ptr::MovingPtr")]
use bevy_ptr::MovingPtr;
use core::cell::Cell;
use core::mem::MaybeUninit;
use core::panic::AssertUnwindSafe;
use std::panic::catch_unwind;
#[test]
fn moving_ptr_assign_drop_is_unwind_safe() {
struct IncAndPanicOnDrop<'a>(&'a Cell<u32>);
impl<'a> Drop for IncAndPanicOnDrop<'a> {
fn drop(&mut self) {
self.0.set(self.0.get() + 1);
if !std::thread::panicking() {
panic!();
}
}
}
let drops1 = Cell::new(0);
let drops2 = Cell::new(0);
let mut value1 = MaybeUninit::new(IncAndPanicOnDrop(&drops1));
let mut value2 = IncAndPanicOnDrop(&drops2);
_ = catch_unwind(AssertUnwindSafe(|| {
let moving_ptr = unsafe { MovingPtr::from_value(&mut value1) };
moving_ptr.assign_to(&mut value2);
}));
assert_eq!(drops1.get(), 0);
assert_eq!(drops2.get(), 1);
_ = catch_unwind(AssertUnwindSafe(|| drop(value2)));
assert_eq!(drops1.get(), 1);
assert_eq!(drops2.get(), 1);
}