pub trait BoxRaw {
fn clean(self);
}
impl<X> BoxRaw for *mut X {
fn clean(self) {
unsafe {
let _ = Box::from_raw(self);
}
}
}
macro_rules! impl_mut_raws_for_tuple {
($($T:tt),*) => {
paste::paste! {
impl<$($T,)*> BoxRaw for ($($T,)*)
where
$($T: BoxRaw,)*
{
fn clean(self) {
let ($([<$T:lower>],)*) = self;
$(
[<$T:lower>].clean();
)*
}
}
}
}
}
impl_mut_raws_for_tuple!(A);
impl_mut_raws_for_tuple!(A, B);
impl_mut_raws_for_tuple!(A, B, C);
impl_mut_raws_for_tuple!(A, B, C, D);
impl_mut_raws_for_tuple!(A, B, C, D, E);
impl_mut_raws_for_tuple!(A, B, C, D, E, F);
impl_mut_raws_for_tuple!(A, B, C, D, E, F, G);
impl_mut_raws_for_tuple!(A, B, C, D, E, F, G, H);
impl_mut_raws_for_tuple!(A, B, C, D, E, F, G, H, I);
impl_mut_raws_for_tuple!(A, B, C, D, E, F, G, H, I, J);
impl_mut_raws_for_tuple!(A, B, C, D, E, F, G, H, I, J, K);
impl_mut_raws_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
pub struct BoxRaws<X: BoxRaw>(pub X);
impl<X: BoxRaw> BoxRaw for BoxRaws<X> {
fn clean(self) {
self.0.clean();
}
}
impl<X: BoxRaw> BoxRaws<X> {
pub fn new(raws: X) -> Self { Self(raws) }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn pass_miri() {
let x = Box::into_raw(Box::new(2u8));
x.clean();
let x = (
Box::into_raw(Box::new(2u8)),
Box::into_raw(Box::new(2u32))
);
x.clean();
let i = Box::into_raw(Box::new(0));
let x = (
i,
Box::into_raw(Box::new(2u32)),
Box::into_raw(Box::new(String::from("raw")))
);
x.clean();
}
#[test]
#[cfg_attr(miri, ignore)]
fn not_pass_miri() {
let i = Box::into_raw(Box::new(0));
let x = (
i,
Box::into_raw(Box::new(14u32))
);
x.clean();
unsafe {
let y = *i + 10;
assert_eq!(y, 10);
}
}
#[test]
fn box_raws() {
let x: Box<Vec<String>> = Box::new(vec![String::from("Rome")]);
let x = Box::into_raw(x);
let y = Box::into_raw(Box::new(10i32));
(x, y).clean();
let x: Box<Vec<String>> = Box::new(vec![String::from("Rome")]);
let x = Box::into_raw(x);
let y = Box::into_raw(Box::new(10i32));
let raws = BoxRaws::new((x, y));
raws.clean();
}
}