#![doc(hidden)]
#[macro_export]
macro_rules! unsafe_trace_lock {
($target:ident, target = $target_type:ident; |$get_mut:ident| $get_mut_expr:expr, |$lock:ident| $acquire_guard:expr) => {
unsafe_gc_brand!($target, $target_type);
unsafe impl<$target_type: Trace> Trace for $target<$target_type> {
const NEEDS_TRACE: bool = T::NEEDS_TRACE;
#[inline]
fn visit<V: GcVisitor>(&mut self, visitor: &mut V) -> Result<(), V::Err> {
let $get_mut = self;
let value: &mut $target_type = $get_mut_expr;
visitor.visit(value)
}
}
unsafe impl<$target_type: Trace> $crate::TraceImmutable for $target<$target_type> {
#[inline]
fn visit_immutable<V: GcVisitor>(&self, visitor: &mut V) -> Result<(), V::Err> {
if !Self::NEEDS_TRACE { return Ok(()) };
let $lock = self;
#[allow(unused_mut)]
let mut guard = $acquire_guard;
let guard_value = &mut *guard;
visitor.visit(guard_value)
}
}
unsafe impl<$target_type: $crate::NullTrace> $crate::NullTrace for $target<$target_type> {}
unsafe impl<$target_type: $crate::GcSafe> $crate::GcSafe for $target<$target_type> {}
};
}
#[macro_export]
macro_rules! unsafe_trace_deref {
($target:ident, target = $target_type:ident) => {
unsafe_trace_deref!($target, target = $target_type; $target_type);
};
($target:ident, target = $target_type:ident; $($param:ident),*) => {
unsafe_trace_deref!($target, target = { $target_type }; $($param),*);
};
($target:ident, target = { $target_type:ty }; $($param:ident),*) => {
unsafe impl<$($param: TraceImmutable),*> $crate::TraceImmutable for $target<$($param),*> {
#[inline]
fn visit_immutable<V: GcVisitor>(&self, visitor: &mut V) -> Result<(), V::Err> {
let extracted: &$target_type = &**self;
visitor.visit_immutable(extracted)
}
}
unsafe_trace_deref!($target, $($param),*; immut = false; |value| {
let dereferenced: &mut $target_type = &mut **value;
dereferenced
});
};
($target:ident, $($param:ident),*; immut = required; |$value:ident| $extract:expr) => {
unsafe_gc_brand!($target, immut = required; $($param),*);
unsafe impl<$($param),*> Trace for $target<$($param),*>
where $($param: TraceImmutable),* {
const NEEDS_TRACE: bool = $($param::NEEDS_TRACE || )* false;
#[inline]
fn visit<V: GcVisitor>(&mut self, visitor: &mut V) -> Result<(), V::Err> {
let extracted = {
let $value = self;
$extract
};
visitor.visit_immutable(extracted)
}
}
unsafe impl<$($param),*> TraceImmutable for $target<$($param),*>
where $($param: TraceImmutable),* {
#[inline]
fn visit_immutable<V: GcVisitor>(&self, visitor: &mut V) -> Result<(), V::Err> {
let extracted = {
let $value = self;
$extract
};
visitor.visit_immutable(extracted)
}
}
unsafe impl<$($param: NullTrace),*> NullTrace for $target<$($param),*> {}
unsafe impl<$($param),*> GcSafe for $target<$($param),*>
where $($param: GcSafe + TraceImmutable),* {
const NEEDS_DROP: bool = core::mem::needs_drop::<Self>();
}
};
($target:ident, $($param:ident),*; immut = false; |$value:ident| $extract:expr) => {
unsafe_gc_brand!($target, $($param),*);
unsafe impl<$($param),*> Trace for $target<$($param),*>
where $($param: Trace),* {
const NEEDS_TRACE: bool = $($param::NEEDS_TRACE || )* false;
#[inline]
fn visit<V: GcVisitor>(&mut self, visitor: &mut V) -> Result<(), V::Err> {
let extracted = {
let $value = self;
$extract
};
visitor.visit(extracted)
}
}
unsafe impl<$($param: NullTrace),*> NullTrace for $target<$($param),*> {}
unsafe impl<$($param),*> GcSafe for $target<$($param),*>
where $($param: GcSafe),* {
const NEEDS_DROP: bool = core::mem::needs_drop::<Self>();
}
};
}
#[macro_export]
macro_rules! unsafe_immutable_trace_iterable {
($target:ident, element = $element_type:ident) => {
unsafe_trace_iterable!($target, element = &$element_type; $element_type);
};
($target:ident<$($param:ident),*>; element = { $element_type:ty }) => {
unsafe impl<$($param),*> TraceImmutable for $target<$($param),*>
where $($param: TraceImmutable),* {
fn visit_immutable<Visit: GcVisitor>(&self, visitor: &mut Visit) -> Result<(), Visit::Err> {
if !Self::NEEDS_TRACE { return Ok(()) };
let iter = IntoIterator::into_iter(self);
for element in iter {
let element: $element_type = element;
visitor.visit_immutable(&element)?;
}
Ok(())
}
}
unsafe impl<$($param: $crate::NullTrace),*> NullTrace for $target<$($param),*> {}
};
}
#[macro_export]
macro_rules! unsafe_trace_primitive {
($target:ty) => {
unsafe_gc_brand!($target);
unsafe impl Trace for $target {
const NEEDS_TRACE: bool = false;
#[inline(always)] fn visit<V: $crate::GcVisitor>(&mut self, _visitor: &mut V) -> Result<(), V::Err> {
Ok(())
}
}
unsafe impl $crate::TraceImmutable for $target {
#[inline(always)]
fn visit_immutable<V: $crate::GcVisitor>(&self, _visitor: &mut V) -> Result<(), V::Err> {
Ok(())
}
}
unsafe impl $crate::NullTrace for $target {}
unsafe impl GcSafe for $target {
const NEEDS_DROP: bool = core::mem::needs_drop::<$target>();
}
unsafe impl<'gc, OwningRef> $crate::GcDirectBarrier<'gc, OwningRef> for $target {
#[inline(always)]
unsafe fn write_barrier(
&self, _owner: &OwningRef, _field_offset: usize,
) {
}
}
};
}
#[macro_export]
macro_rules! unsafe_gc_brand {
($target:tt) => {
unsafe impl<'new_gc, Id: $crate::CollectorId> $crate::GcBrand<'new_gc, Id> for $target {
type Branded = Self;
}
};
($target:ident, $($param:ident),+) => {
unsafe impl<'new_gc, Id, $($param),*> $crate::GcBrand<'new_gc, Id> for $target<$($param),*>
where Id: crate::CollectorId, $($param: $crate::GcBrand<'new_gc, Id>,)*
$(<$param as $crate::GcBrand<'new_gc, Id>>::Branded: Trace,)* {
type Branded = $target<$(<$param as $crate::GcBrand<'new_gc, Id>>::Branded),*>;
}
};
($target:tt, immut = required; $($param:ident),+) => {
unsafe impl<'new_gc, Id, $($param),*> $crate::GcBrand<'new_gc, Id> for $target<$($param),*>
where Id: crate::CollectorId, $($param: $crate::GcBrand<'new_gc, Id> + TraceImmutable,)*
$(<$param as $crate::GcBrand<'new_gc, Id>>::Branded: TraceImmutable,)* {
type Branded = $target<$(<$param as $crate::GcBrand<'new_gc, Id>>::Branded),*>;
}
}
}
mod core;
#[cfg(any(feature = "alloc", feature = "std"))]
mod stdalloc;
#[cfg(feature = "std")]
mod stdlib;
#[cfg(feature = "indexmap")]
mod indexmap;