use super::tracer::Tracer;
use crate::gc::{Gc, GcOpt};
use crate::pointee::{GcPointee, Thin};
use crate::tagged::{Tag, Tagged};
use core::cell::*;
use core::ptr::NonNull;
use core::sync::atomic::*;
pub unsafe trait TraceLeaf: Trace {
#[doc(hidden)]
fn __assert_trace_leaf() {}
}
#[doc(hidden)]
pub trait __MustNotDrop {}
#[doc(hidden)]
#[allow(drop_bounds)]
impl<T: Drop> __MustNotDrop for T {}
pub unsafe trait Trace: GcPointee {
#[doc(hidden)]
const IS_LEAF: bool;
#[doc(hidden)]
fn trace(&self, _tracer: &mut Tracer);
#[doc(hidden)]
fn dyn_trace(ptr: NonNull<Thin<()>>, tracer: &mut Tracer) {
<Self as GcPointee>::deref(ptr.cast()).trace(tracer)
}
}
unsafe impl<'gc, T: Trace + ?Sized> Trace for Gc<'gc, T> {
const IS_LEAF: bool = false;
fn trace(&self, tracer: &mut Tracer) {
tracer.mark_and_trace(self.clone());
}
}
unsafe impl<'gc, T: Trace + ?Sized> Trace for GcOpt<'gc, T> {
const IS_LEAF: bool = false;
fn trace(&self, tracer: &mut Tracer) {
if let Some(gc_mut) = self.as_option() {
gc_mut.trace(tracer)
}
}
}
unsafe impl<'gc, T: Tag> Trace for Tagged<'gc, T> {
const IS_LEAF: bool = false;
fn trace(&self, tracer: &mut crate::Tracer) {
T::trace_tagged(self, tracer);
}
}
macro_rules! impl_trace_leaf {
($($t:ty),*) => {
$(unsafe impl Trace for $t {
const IS_LEAF: bool = true;
fn trace(&self, _: &mut Tracer) {}
})*
$(unsafe impl TraceLeaf for $t {})*
};
}
impl_trace_leaf!(
(),
bool,
char,
u8,
u16,
u32,
u64,
u128,
usize,
i8,
i16,
i32,
i64,
i128,
isize,
f32,
f64,
str,
AtomicBool,
AtomicI8,
AtomicI16,
AtomicI32,
AtomicI64,
AtomicIsize,
AtomicU8,
AtomicU16,
AtomicU32,
AtomicU64,
AtomicUsize
);
unsafe impl<T: TraceLeaf> TraceLeaf for UnsafeCell<T> {}
unsafe impl<T: TraceLeaf> Trace for UnsafeCell<T> {
const IS_LEAF: bool = true;
fn trace(&self, _: &mut Tracer) {}
}
unsafe impl<T: TraceLeaf> TraceLeaf for Cell<T> {}
unsafe impl<T: TraceLeaf> Trace for Cell<T> {
const IS_LEAF: bool = true;
fn trace(&self, _: &mut Tracer) {}
}
unsafe impl<T: TraceLeaf> TraceLeaf for RefCell<T> {}
unsafe impl<T: TraceLeaf> Trace for RefCell<T> {
const IS_LEAF: bool = true;
fn trace(&self, _: &mut Tracer) {}
}
unsafe impl<T: TraceLeaf> TraceLeaf for OnceCell<T> {}
unsafe impl<T: TraceLeaf> Trace for OnceCell<T> {
const IS_LEAF: bool = true;
fn trace(&self, _: &mut Tracer) {}
}
unsafe impl<const N: usize, T: TraceLeaf> TraceLeaf for [T; N] {}
unsafe impl<const N: usize, T: Trace> Trace for [T; N] {
const IS_LEAF: bool = T::IS_LEAF;
fn trace(&self, tracer: &mut Tracer) {
for item in self.iter() {
item.trace(tracer)
}
}
}
unsafe impl<T: TraceLeaf> TraceLeaf for [T] {}
unsafe impl<T: Trace> Trace for [T] {
const IS_LEAF: bool = T::IS_LEAF;
fn trace(&self, tracer: &mut Tracer) {
for item in self.iter() {
item.trace(tracer)
}
}
}
unsafe impl<T: TraceLeaf> TraceLeaf for Option<T> {}
unsafe impl<T: Trace> Trace for Option<T> {
const IS_LEAF: bool = T::IS_LEAF;
fn trace(&self, tracer: &mut Tracer) {
if let Some(value) = self.as_ref() {
value.trace(tracer)
}
}
}
unsafe impl<A: TraceLeaf, B: TraceLeaf> TraceLeaf for Result<A, B> {}
unsafe impl<A: Trace, B: Trace> Trace for Result<A, B> {
const IS_LEAF: bool = A::IS_LEAF && B::IS_LEAF;
fn trace(&self, tracer: &mut Tracer) {
match self {
Ok(res) => res.trace(tracer),
Err(e) => e.trace(tracer),
}
}
}
unsafe impl<A: TraceLeaf, B: TraceLeaf> TraceLeaf for (A, B) {}
unsafe impl<A: Trace, B: Trace> Trace for (A, B) {
const IS_LEAF: bool = A::IS_LEAF && B::IS_LEAF;
fn trace(&self, tracer: &mut Tracer) {
self.0.trace(tracer);
self.1.trace(tracer);
}
}
unsafe impl<A: TraceLeaf, B: TraceLeaf, C: TraceLeaf> TraceLeaf for (A, B, C) {}
unsafe impl<A: Trace, B: Trace, C: Trace> Trace for (A, B, C) {
const IS_LEAF: bool = A::IS_LEAF && B::IS_LEAF && C::IS_LEAF;
fn trace(&self, tracer: &mut Tracer) {
self.0.trace(tracer);
self.1.trace(tracer);
self.2.trace(tracer);
}
}