dreck 0.1.1

A safe tracing garbage collection library with minimal safety bookkeeping
Documentation
use super::{Bound, Gc, Trace, Tracer};
macro_rules! impl_trace_primitive{
($($ty:ident,)*) => {
    $(
        unsafe impl<'own> Trace<'own> for $ty{
            fn needs_trace() -> bool{
                false
            }

            fn trace(&self, _t: Tracer){}
        }

        unsafe impl<'to> Bound<'to> for $ty {
            type Rebound = $ty;
        }
    )*
};
}

impl_trace_primitive!(
    bool, char, u8, u16, u32, u64, usize, i8, i16, i32, i64, f32, f64, isize, String,
);

macro_rules! impl_trace_tuple{
    ($($ty:ident),*) => {
            #[allow(non_snake_case)]
            #[allow(unused_variables)]
            unsafe impl<'own,$($ty:Trace<'own>,)*> Trace<'own> for ($($ty,)*){
                fn needs_trace() -> bool{
                    false $(|| $ty::needs_trace())*
                }

                fn trace<'a>(&self, t: Tracer<'a,'own>){
                    let ($(ref $ty,)*) = self;
                    $($ty.trace(t);)*
                }
            }

            unsafe impl<'to,$($ty: Bound<'to>,)*> Bound<'to> for ($($ty,)*){
                type Rebound = ($($ty::Rebound,)*);
            }
    };
}

impl_trace_tuple!();
impl_trace_tuple!(A);
impl_trace_tuple!(A, B);
impl_trace_tuple!(A, B, C);
impl_trace_tuple!(A, B, C, D);
impl_trace_tuple!(A, B, C, D, E);
impl_trace_tuple!(A, B, C, D, E, F);
impl_trace_tuple!(A, B, C, D, E, F, G);
impl_trace_tuple!(A, B, C, D, E, F, G, H);

unsafe impl<'gc, 'own, T: Trace<'own>> Trace<'own> for Gc<'gc, 'own, T> {
    fn needs_trace() -> bool
    where
        Self: Sized,
    {
        true
    }

    fn trace<'a>(&self, t: Tracer<'a, 'own>) {
        t.mark(*self)
    }
}

unsafe impl<'to, 'from, 'own, T> Bound<'to> for Gc<'from, 'own, T>
where
    T: Trace<'own> + Bound<'to>,
    T::Rebound: Trace<'own> + 'to,
{
    type Rebound = Gc<'to, 'own, T::Rebound>;
}

unsafe impl<'own, T: Trace<'own>> Trace<'own> for Vec<T> {
    fn needs_trace() -> bool
    where
        Self: Sized,
    {
        T::needs_trace()
    }

    fn trace<'a>(&self, t: Tracer<'a, 'own>) {
        for v in self {
            v.trace(t);
        }
    }
}

unsafe impl<'to, T: Bound<'to>> Bound<'to> for Vec<T> {
    type Rebound = Vec<T::Rebound>;
}

unsafe impl<'own, T: Trace<'own>> Trace<'own> for Option<T> {
    fn needs_trace() -> bool
    where
        Self: Sized,
    {
        T::needs_trace()
    }

    fn trace(&self, t: Tracer<'_, 'own>) {
        if let Some(v) = self.as_ref() {
            v.trace(t);
        }
    }
}

unsafe impl<'to, T: Bound<'to>> Bound<'to> for Option<T> {
    type Rebound = Option<T::Rebound>;
}

unsafe impl<'a, 'to, T, R> Bound<'to> for &'a mut T
where
    T: Bound<'to, Rebound = R>,
    R: 'a,
{
    type Rebound = &'a mut R;
}