use std::collections::{BinaryHeap, BTreeMap, BTreeSet, HashMap, HashSet, LinkedList, VecDeque};
use std::hash::Hash;
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize};
pub trait Finalize {
fn finalize(&self) {}
}
#[cfg(feature = "nightly")]
impl<T: ?Sized> Finalize for T {
#[inline]
default fn finalize(&self) {}
}
pub unsafe trait Trace: Finalize {
unsafe fn trace(&self);
unsafe fn root(&self);
unsafe fn unroot(&self);
fn finalize_glue(&self);
}
#[macro_export]
macro_rules! unsafe_empty_trace {
() => {
#[inline]
unsafe fn trace(&self) {}
#[inline]
unsafe fn root(&self) {}
#[inline]
unsafe fn unroot(&self) {}
#[inline]
fn finalize_glue(&self) {
$crate::Finalize::finalize(self)
}
}
}
#[macro_export]
macro_rules! custom_trace {
($this:ident, $body:expr) => {
#[inline]
unsafe fn trace(&self) {
#[inline]
unsafe fn mark<T: $crate::Trace + ?Sized>(it: &T) {
$crate::Trace::trace(it);
}
let $this = self;
$body
}
#[inline]
unsafe fn root(&self) {
#[inline]
unsafe fn mark<T: $crate::Trace + ?Sized>(it: &T) {
$crate::Trace::root(it);
}
let $this = self;
$body
}
#[inline]
unsafe fn unroot(&self) {
#[inline]
unsafe fn mark<T: $crate::Trace + ?Sized>(it: &T) {
$crate::Trace::unroot(it);
}
let $this = self;
$body
}
#[inline]
fn finalize_glue(&self) {
$crate::Finalize::finalize(self);
#[inline]
fn mark<T: $crate::Trace + ?Sized>(it: &T) {
$crate::Trace::finalize_glue(it);
}
let $this = self;
$body
}
}
}
impl<T: ?Sized> Finalize for &'static T {}
unsafe impl<T: ?Sized> Trace for &'static T {
unsafe_empty_trace!();
}
macro_rules! simple_empty_finalize_trace {
($($T:ty),*) => {
$(
impl Finalize for $T {}
unsafe impl Trace for $T { unsafe_empty_trace!(); }
)*
}
}
simple_empty_finalize_trace![(), isize, usize, bool, i8, u8, i16, u16, i32,
u32, i64, u64, f32, f64, char, String, Path, PathBuf, AtomicBool,
AtomicIsize, AtomicUsize];
#[cfg(feature = "nightly")]
simple_empty_finalize_trace![i128, u128];
macro_rules! array_finalize_trace {
($n:expr) => {
impl<T: Trace> Finalize for [T; $n] {}
unsafe impl<T: Trace> Trace for [T; $n] {
custom_trace!(this, {
for v in this {
mark(v);
}
});
}
}
}
macro_rules! fn_finalize_trace_one {
($ty:ty $(,$args:ident)*) => {
impl<Ret $(,$args)*> Finalize for $ty {}
unsafe impl<Ret $(,$args)*> Trace for $ty { unsafe_empty_trace!(); }
}
}
macro_rules! fn_finalize_trace_group {
() => {
fn_finalize_trace_one!(extern "Rust" fn () -> Ret);
fn_finalize_trace_one!(extern "C" fn () -> Ret);
fn_finalize_trace_one!(unsafe extern "Rust" fn () -> Ret);
fn_finalize_trace_one!(unsafe extern "C" fn () -> Ret);
};
($($args:ident),*) => {
fn_finalize_trace_one!(extern "Rust" fn ($($args),*) -> Ret, $($args),*);
fn_finalize_trace_one!(extern "C" fn ($($args),*) -> Ret, $($args),*);
fn_finalize_trace_one!(extern "C" fn ($($args),*, ...) -> Ret, $($args),*);
fn_finalize_trace_one!(unsafe extern "Rust" fn ($($args),*) -> Ret, $($args),*);
fn_finalize_trace_one!(unsafe extern "C" fn ($($args),*) -> Ret, $($args),*);
fn_finalize_trace_one!(unsafe extern "C" fn ($($args),*, ...) -> Ret, $($args),*);
}
}
macro_rules! tuple_finalize_trace {
() => {};
($($args:ident),*) => {
impl<$($args),*> Finalize for ($($args,)*) {}
unsafe impl<$($args: $crate::Trace),*> Trace for ($($args,)*) {
custom_trace!(this, {
#[allow(non_snake_case, unused_unsafe)]
fn avoid_lints<$($args: $crate::Trace),*>(&($(ref $args,)*): &($($args,)*)) {
unsafe { $(mark($args);)* }
}
avoid_lints(this)
});
}
}
}
macro_rules! array_finalize_trace_impls {
($($n:expr),*) => {
$(
array_finalize_trace!($n);
)*
}
}
macro_rules! type_arg_tuple_based_finalized_trace_impls {
($(($($args:ident),*);)*) => {
$(
fn_finalize_trace_group!($($args),*);
tuple_finalize_trace!($($args),*);
)*
}
}
array_finalize_trace_impls![
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31
];
type_arg_tuple_based_finalized_trace_impls![
();
(A);
(A, B);
(A, B, C);
(A, B, C, D);
(A, B, C, D, E);
(A, B, C, D, E, F);
(A, B, C, D, E, F, G);
(A, B, C, D, E, F, G, H);
(A, B, C, D, E, F, G, H, I);
(A, B, C, D, E, F, G, H, I, J);
(A, B, C, D, E, F, G, H, I, J, K);
(A, B, C, D, E, F, G, H, I, J, K, L);
];
impl<T: Trace + ?Sized> Finalize for Box<T> {}
unsafe impl<T: Trace + ?Sized> Trace for Box<T> {
custom_trace!(this, {
mark(&**this);
});
}
impl<T: Trace> Finalize for Vec<T> {}
unsafe impl<T: Trace> Trace for Vec<T> {
custom_trace!(this, {
for e in this {
mark(e);
}
});
}
impl<T: Trace> Finalize for Option<T> {}
unsafe impl<T: Trace> Trace for Option<T> {
custom_trace!(this, {
if let Some(ref v) = *this {
mark(v);
}
});
}
impl<T: Trace, E: Trace> Finalize for Result<T, E> {}
unsafe impl<T: Trace, E: Trace> Trace for Result<T, E> {
custom_trace!(this, {
match *this {
Ok(ref v) => mark(v),
Err(ref v) => mark(v),
}
});
}
impl<T: Ord + Trace> Finalize for BinaryHeap<T> {}
unsafe impl<T: Ord + Trace> Trace for BinaryHeap<T> {
custom_trace!(this, {
for v in this.into_iter() {
mark(v);
}
});
}
impl<K: Trace, V: Trace> Finalize for BTreeMap<K, V> {}
unsafe impl<K: Trace, V: Trace> Trace for BTreeMap<K, V> {
custom_trace!(this, {
for (k, v) in this {
mark(k);
mark(v);
}
});
}
impl<T: Trace> Finalize for BTreeSet<T> {}
unsafe impl<T: Trace> Trace for BTreeSet<T> {
custom_trace!(this, {
for v in this {
mark(v);
}
});
}
impl<K: Eq + Hash + Trace, V: Trace> Finalize for HashMap<K, V> {}
unsafe impl<K: Eq + Hash + Trace, V: Trace> Trace for HashMap<K, V> {
custom_trace!(this, {
for (k, v) in this.iter() {
mark(k);
mark(v);
}
});
}
impl<T: Eq + Hash + Trace> Finalize for HashSet<T> {}
unsafe impl<T: Eq + Hash + Trace> Trace for HashSet<T> {
custom_trace!(this, {
for v in this.iter() {
mark(v);
}
});
}
impl<T: Eq + Hash + Trace> Finalize for LinkedList<T> {}
unsafe impl<T: Eq + Hash + Trace> Trace for LinkedList<T> {
custom_trace!(this, {
for v in this.iter() {
mark(v);
}
});
}
impl<T: Trace> Finalize for VecDeque<T> {}
unsafe impl<T: Trace> Trace for VecDeque<T> {
custom_trace!(this, {
for v in this.iter() {
mark(v);
}
});
}