use std::{cell::Cell, marker::PhantomData, rc::Rc};
use destruct_drop::DestructDrop;
#[derive(DestructDrop)]
struct DontDropThis {
a: DropThis,
b: u32,
c: DropThis,
}
impl Drop for DontDropThis {
fn drop(&mut self) {
panic!("Dropped DontDropThis");
}
}
#[derive(Default)]
struct DropThis(Rc<Cell<bool>>);
impl Drop for DropThis {
fn drop(&mut self) {
if self.0.get() {
panic!("Tried to drop DropThis twice!");
}
self.0.set(true);
}
}
#[test]
fn basic_struct() {
let dropped_a = Rc::new(Cell::new(false));
let dropped_c = Rc::new(Cell::new(false));
let dont_drop_this = DontDropThis {
a: DropThis(dropped_a.clone()),
b: 0,
c: DropThis(dropped_c.clone()),
};
assert!(!dropped_a.get());
assert!(!dropped_c.get());
dont_drop_this.destruct_drop();
assert!(dropped_a.get());
assert!(dropped_c.get());
}
#[derive(DestructDrop)]
struct DontDropThisTuple(DropThis, u32, DropThis);
impl Drop for DontDropThisTuple {
fn drop(&mut self) {
panic!("Dropped DontDropThisTuple");
}
}
#[test]
fn basic_tuple_struct() {
let dropped_0 = Rc::new(Cell::new(false));
let dropped_2 = Rc::new(Cell::new(false));
let dont_drop_this =
DontDropThisTuple(DropThis(dropped_0.clone()), 0, DropThis(dropped_2.clone()));
assert!(!dropped_0.get());
assert!(!dropped_2.get());
dont_drop_this.destruct_drop();
assert!(dropped_0.get());
assert!(dropped_2.get());
}
#[derive(DestructDrop)]
struct DontDropThisUnit;
impl Drop for DontDropThisUnit {
fn drop(&mut self) {
panic!("Dropped DontDropThisUnit");
}
}
#[test]
fn basic_unit_struct() {
let dont_drop_this = DontDropThisUnit;
dont_drop_this.destruct_drop();
}
#[derive(DestructDrop)]
enum DontDropThisEnum {
A,
B { v: DropThis },
C(DropThis),
}
impl Drop for DontDropThisEnum {
fn drop(&mut self) {
panic!("Dropped DontDropThisEnum");
}
}
#[test]
fn basic_unit_enum() {
let dont_drop_this_a = DontDropThisEnum::A;
dont_drop_this_a.destruct_drop();
let dropped_b = Rc::new(Cell::new(false));
let dont_drop_this_b = DontDropThisEnum::B {
v: DropThis(dropped_b.clone()),
};
assert!(!dropped_b.get());
dont_drop_this_b.destruct_drop();
assert!(dropped_b.get());
let dropped_c = Rc::new(Cell::new(false));
let dont_drop_this_c = DontDropThisEnum::C(DropThis(dropped_c.clone()));
assert!(!dropped_c.get());
dont_drop_this_c.destruct_drop();
assert!(dropped_c.get());
}
#[derive(DestructDrop)]
struct DontDropThisGeneric<'a, T>(T, PhantomData<&'a T>);
impl <'a, T> Drop for DontDropThisGeneric<'a, T> {
fn drop(&mut self) {
panic!("Dropped DontDropThisGeneric");
}
}
#[test]
fn basic_struct_generic() {
let dropped_inner = Rc::new(Cell::new(false));
let dont_drop_this = DontDropThisGeneric(DropThis(dropped_inner.clone()), PhantomData);
assert!(!dropped_inner.get());
DestructDrop::destruct_drop(dont_drop_this);
assert!(dropped_inner.get());
}