pub unsafe trait GcSafe<'gc, Id: CollectorId>: Trace + TrustedDrop {
unsafe fn trace_inside_gc<V>(
gc: &mut Gc<'gc, Self, Id>,
visitor: &mut V
) -> Result<(), V::Err>
where
V: GcVisitor;
}
Expand description
A marker trait correlating all garbage collected pointers
corresponding to the specified Id
are valid for the 'gc
lifetime.
If this type is implemented for a specific CollectorId Id
,
it indicates the possibility of containing pointers belonging to that collector.
If a type is NullTrace, it should implement
GcSafefor all possible collectors. However, if a type
NEEDS_TRACE`, it will usually only implement GcSafe for the specific
CollectorIds it happens to contain (although this is not guarenteed).
Mixing with other lifetimes
Note that T: GcSafe<'gc, T>
does not necessarily imply T: 'gc
.
This allows a garbage collected lifetime to contain shorter lifetimes
For example,
#[derive(Trace)]
#[zerogc(ignore_lifetimes("'a"), collector_ids(CollectorId))]
struct TempLifetime<'gc, 'a> {
temp: &'a i32,
gc: Gc<'gc, i32>
}
fn alloc_ref_temp<'gc>(ctx: &'gc GcContext, long_lived: Gc<'gc, i32>) {
let temp = 5; // Lives for 'a (shorter than 'gc)
let temp_ref = ctx.alloc(TempLifetime {
temp: &temp, gc: long_lived
});
assert_eq!(&temp as *const _, temp_ref.temp as *const _)
}
Mixing collectors
The Id
parameter allows mixing and matching pointers from different collectors,
each with their own ’gc lifetime.
For example,
#[derive(Trace)]
struct MixedGc<'gc, 'js> {
internal_ptr: Gc<'gc, i32, OtherGcId>,
js_ptr: Gc<'js, i32, JsGcId>
}
impl<'gc, 'js> MixedGc<'gc, 'js> {
fn verify(&self) {
assert!(<Self as GcSafe<'gc, OtherGcId>>::assert_gc_safe());
assert!(<Self as GcSafe<'js, JsGcId>>::assert_gc_safe());
// NOT implemented: <Self as GcSafe<'gc, ThirdId>>
}
}
Safety
In addition to the guarantees of Trace and TrustedDrop,
implementing this type requires that all Gc pointers of
the specified Id
have the 'gc
lifetime (if there are any at all).
Required methods
Trace this object behind a Gc pointer.
This is required to delegate to one of the following methods on GcVisitor:
- GcVisitor::trace_gc - For regular,
Sized
types - GcVisitor::trace_array - For slices and arrays
- GcVisitor::trace_trait_object - For trait objects
Safety
This must delegate to the appropriate method on GcVisitor, or undefined behavior will result.
The user is required to supply an appropriate Gc pointer.