pub unsafe trait Trace { unsafe fn mark(&self); unsafe fn manage(&self); unsafe fn finalize(&mut self); } pub unsafe trait NullTrace: Trace {} unsafe impl Trace for Option { unsafe fn mark(&self) { if let Some(inner) = self { inner.mark() } } unsafe fn manage(&self) { if let Some(inner) = self { inner.manage() } } unsafe fn finalize(&mut self) { if let Some(inner) = self { inner.finalize() } } } unsafe impl NullTrace for Option {} unsafe impl Trace for Result { unsafe fn mark(&self) { match self { Ok(inner) => inner.mark(), Err(error) => error.mark(), } } unsafe fn manage(&self) { match self { Ok(inner) => inner.manage(), Err(error) => error.manage(), } } unsafe fn finalize(&mut self) { match self { Ok(inner) => inner.finalize(), Err(error) => error.finalize(), } } } unsafe impl NullTrace for Result {} unsafe impl Trace for [T] { unsafe fn mark(&self) { for elem in self { elem.mark() } } unsafe fn manage(&self) { for elem in self { elem.manage() } } unsafe fn finalize(&mut self) { for elem in self { elem.finalize() } } } unsafe impl NullTrace for [T] {} macro_rules! trace_simple { ($($t:ty)*) => {$( unsafe impl Trace for $t { unsafe fn mark(&self) { } unsafe fn manage(&self) { } unsafe fn finalize(&mut self) { ptr::drop_in_place(self as *mut Self) } } unsafe impl NullTrace for $t { } )*} } trace_simple!( i8 i16 i32 i64 isize u8 u16 u32 u64 usize f32 f64 char bool str String std::fs::File std::fs::FileType std::fs::Metadata std::fs::OpenOptions dyn std::io::BufRead dyn std::io::Read dyn std::io::Write std::io::Stdin std::io::Stdout std::io::Stderr std::io::Error std::net::TcpStream std::net::TcpListener std::net::UdpSocket std::net::Ipv4Addr std::net::Ipv6Addr std::net::SocketAddrV4 std::net::SocketAddrV6 std::path::Path std::path::PathBuf std::process::Command std::process::Child std::process::ChildStdout std::process::ChildStdin std::process::ChildStderr std::process::Output std::process::ExitStatus std::process::Stdio std::sync::Barrier std::sync::Condvar std::sync::Once ); macro_rules! trace_arrays { ($($N:expr),*) => {$( unsafe impl Trace for [T; $N] { unsafe fn mark(&self) { <_ as AsRef<[T]>>::as_ref(self).mark() } unsafe fn manage(&self) { <_ as AsRef<[T]>>::as_ref(self).manage() } unsafe fn finalize(&mut self) { <_ as AsMut<[T]>>::as_mut(self).finalize() } } unsafe impl NullTrace for [T; $N] { } )*}; } trace_arrays! { 0o00, 0o01, 0o02, 0o03, 0o04, 0o05, 0o06, 0o07, 0o10, 0o11, 0o12, 0o13, 0o14, 0o15, 0o16, 0o17, 0o20, 0o21, 0o22, 0o23, 0o24, 0o25, 0o26, 0o27, 0o30, 0o31, 0o32, 0o33, 0o34, 0o35, 0o36, 0o37 } macro_rules! trace_tuples { ($(($($T:ident : $N:tt),*))*) => {$( unsafe impl<$($T: Trace,)*> Trace for ($($T,)*) { unsafe fn mark(&self) { $(self.$N.mark();)* } unsafe fn manage(&self) { $(self.$N.manage();)* } unsafe fn finalize(&mut self) { $(self.$N.finalize();)* } } unsafe impl<$($T: NullTrace,)*> NullTrace for ($($T,)*) { } )*}; } trace_tuples! { () (A: 0) (A: 0, B: 1) (A: 0, B: 1, C: 2) (A: 0, B: 1, C: 2, D: 3) (A: 0, B: 1, C: 2, D: 3, E: 4) (A: 0, B: 1, C: 2, D: 3, E: 4, F: 5) (A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6) (A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7) (A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8) (A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8, J: 9) (A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8, J: 9, K: 10) (A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8, J: 9, K: 10, L: 11) } use std::collections::*; use std::mem::{self, ManuallyDrop}; use std::ptr; unsafe impl Trace for Vec { unsafe fn mark(&self) { for elem in self { elem.mark(); } } unsafe fn manage(&self) { for elem in self { elem.manage(); } } unsafe fn finalize(&mut self) { for elem in &mut *self { elem.finalize(); } let this = mem::transmute::<&mut Vec, &mut Vec>>(self); ptr::drop_in_place(this as *mut Vec>); } } unsafe impl NullTrace for Vec {} unsafe impl Trace for VecDeque { unsafe fn mark(&self) { for elem in self { elem.mark(); } } unsafe fn manage(&self) { for elem in self { elem.manage(); } } unsafe fn finalize(&mut self) { for elem in &mut *self { elem.finalize(); } let this = mem::transmute::<&mut VecDeque, &mut VecDeque>>(self); ptr::drop_in_place(this as *mut VecDeque>); } } unsafe impl NullTrace for VecDeque {} unsafe impl Trace for LinkedList { unsafe fn mark(&self) { for elem in self { elem.mark(); } } unsafe fn manage(&self) { for elem in self { elem.manage(); } } unsafe fn finalize(&mut self) { for elem in &mut *self { elem.finalize(); } let this = mem::transmute::<&mut LinkedList, &mut LinkedList>>(self); ptr::drop_in_place(this as *mut LinkedList>); } } unsafe impl NullTrace for LinkedList {} unsafe impl Trace for BinaryHeap { unsafe fn mark(&self) { for elem in self { elem.mark(); } } unsafe fn manage(&self) { for elem in self { elem.manage(); } } unsafe fn finalize(&mut self) { let iter = IntoIterator::into_iter(ptr::read(self)); let iter = mem::transmute::, binary_heap::IntoIter>>( iter, ); iter.for_each(|mut elem| elem.finalize()); } } unsafe impl NullTrace for BinaryHeap {} unsafe impl Trace for HashSet where T: Eq + std::hash::Hash + Trace, S: std::hash::BuildHasher, { unsafe fn mark(&self) { for elem in self { elem.mark(); } } unsafe fn manage(&self) { for elem in self { elem.manage(); } } unsafe fn finalize(&mut self) { let iter = IntoIterator::into_iter(ptr::read(self)); let iter = mem::transmute::, hash_set::IntoIter>>(iter); iter.for_each(|mut elem| elem.finalize()); } } unsafe impl NullTrace for HashSet where T: Eq + std::hash::Hash + NullTrace, S: std::hash::BuildHasher, { } unsafe impl Trace for HashMap where K: Eq + std::hash::Hash + Trace, V: Trace, S: std::hash::BuildHasher, { unsafe fn mark(&self) { for (key, value) in self { key.mark(); value.mark(); } } unsafe fn manage(&self) { for (key, value) in self { key.manage(); value.manage(); } } unsafe fn finalize(&mut self) { let iter = IntoIterator::into_iter(ptr::read(self)); let iter = mem::transmute::< hash_map::IntoIter, hash_map::IntoIter, ManuallyDrop>, >(iter); iter.for_each(|(mut key, mut value)| { key.finalize(); value.finalize(); }); } } unsafe impl NullTrace for HashMap where K: Eq + std::hash::Hash + NullTrace, V: NullTrace, S: std::hash::BuildHasher, { } unsafe impl Trace for BTreeSet where T: Eq + Ord + Trace, { unsafe fn mark(&self) { for elem in self { elem.mark(); } } unsafe fn manage(&self) { for elem in self { elem.manage(); } } unsafe fn finalize(&mut self) { let iter = IntoIterator::into_iter(ptr::read(self)); let iter = mem::transmute::, btree_set::IntoIter>>(iter); iter.for_each(|mut elem| elem.finalize()); } } unsafe impl NullTrace for BTreeSet where T: Eq + Ord + NullTrace {} unsafe impl Trace for BTreeMap where K: Eq + Ord + Trace, V: Trace, { unsafe fn mark(&self) { for (key, value) in self { key.mark(); value.mark(); } } unsafe fn manage(&self) { for (key, value) in self { key.manage(); value.manage(); } } unsafe fn finalize(&mut self) { let iter = IntoIterator::into_iter(ptr::read(self)); let iter = mem::transmute::< btree_map::IntoIter, btree_map::IntoIter, ManuallyDrop>, >(iter); iter.for_each(|(mut key, mut value)| { key.finalize(); value.finalize(); }); } } unsafe impl NullTrace for BTreeMap where K: Eq + Ord + NullTrace, V: NullTrace, { } use pin_cell::PinCell; use std::cell::{Cell, RefCell}; unsafe impl Trace for Cell { unsafe fn mark(&self) {} unsafe fn manage(&self) {} unsafe fn finalize(&mut self) { ptr::drop_in_place(self as *mut Self) } } unsafe impl NullTrace for Cell {} unsafe impl Trace for RefCell { unsafe fn mark(&self) {} unsafe fn manage(&self) {} unsafe fn finalize(&mut self) { ptr::drop_in_place(self as *mut Self) } } unsafe impl NullTrace for RefCell {} unsafe impl Trace for PinCell { unsafe fn mark(&self) { self.borrow().mark() } unsafe fn manage(&self) { self.borrow().manage() } unsafe fn finalize(&mut self) { self.get_mut().finalize() } } unsafe impl NullTrace for PinCell {}