[][src]Macro zerogc::unsafe_trace_deref

macro_rules! unsafe_trace_deref {
    ($target:ident, target = $target_type:ident) => { ... };
    ($target:ident, target = $target_type:ident; $($param:ident),*) => { ... };
    ($target:ident, target = { $target_type:ty }; $($param:ident),*) => { ... };
    ($target:ident, $($param:ident),*; immut = required; |$value:ident| $extract:expr) => { ... };
    ($target:ident, $($param:ident),*; immut = false; |$value:ident| $extract:expr) => { ... };
}

Unsafely implement GarbageCollected for the specified type, by converting the specified wrapper type in order to trace the underlying objects.

In addition to smart pointers, it can be used for newtype structs like Wrapping or NonZero, as long as the types can properly traced by just reading their underlying value. However, it's slightly easier to invoke if you implement Deref, since the expression is inferred based on the target type. However, you will always need to explicitly indicate the dereferencing output type, in order to be eplicit about the intended operation.

This macro is usually only useful for unsafe wrappers like NonZero and smart pointers like Rc and Box who use raw pointers internally, since raw pointers can't be automatically traced without additional type information. Otherwise, it's best to use an automatically derived implementation since that's always safe. However, using this macro is always better than a manual implementation, since it makes your intent clearer.

Usage

// Easy to use for wrappers that `Deref` to their type parameter
unsafe_trace_deref!(Box, target = T);
unsafe_trace_deref!(Rc, target = T);
unsafe_trace_deref!(Arc, target = T);
// The `Deref::Output` type can be declared separately from the type paremters
unsafe_trace_deref!(Vec, target = { [T] }, T);
/*
 * You can use an arbitrary expression to acquire the underlying value,
 * and the type doesn't need to implement `Deref` at all
 */
unsafe_trace_deref!(Cell, T; |cell| cell.get());
unsafe_trace_deref!(Wrapping, T; |wrapping| &wrapping.0);
unsafe_trace_deref!(NonZero, T; |nonzero| &nonzero.get());

Safety

Always prefer automatically derived implementations where possible, since they're just as fast and can never cause undefined behavior. This is basically an unsafe automatically derived implementation, to be used only when a safe automatically derived implementation isn't possible (like with Vec).

Undefined behavior if there could be garbage collected objects that are not reachable via iteration, since the macro only traces objects it can iterate over, and the garbage collector will free objects that haven't been traced. This usually isn't the case with collections and would be somewhat rare, but it's still a possibility that causes the macro to be unsafe.

This delegates to unsafe_gc_brand to provide the GcBrand implementation, so that could also trigger undefined behavior.