pub unsafe trait Trace: Finalize {
// Required method
fn trace(&self, ctx: &mut Context<'_>);
}
Expand description
Trait to trace cycle-collectable objects.
This trait is unsafe to implement, but can be safely derived using the Trace
derive macro, which calls the trace
method on every field:
#[derive(Trace)]
struct Foo<A: Trace + 'static, B: Trace + 'static> {
a_field: Cc<A>,
another_field: Cc<B>,
}
This trait is already implemented for common types from the standard library.
§Safety
The implementations of this trait must uphold the following invariants:
- The
trace
implementation can trace (maximum once) everyCc
instance exclusively owned byself
. No otherCc
instance can be traced. - It’s always safe to panic.
- During the same tracing phase (see below), two different
trace
calls on the same value must behave the same, i.e. they must trace the sameCc
instances.
If a panic happens during the second of suchtrace
calls but not in the first one, then theCc
instances traced during the second call must be a subset of theCc
instances traced in the first one.
Tracing can be detected using thestate::is_tracing
function. If it never returnedfalse
between twotrace
calls on the same value, then they are part of the same tracing phase. - The
trace
implementation must not create, clone, move, dereference or drop anyCc
. - If the implementing type implements
Drop
, then theDrop::drop
implementation must not create, clone, move, dereference, drop or call any method on anyCc
instance.
§Implementation tips
It is almost always preferable to use the derive macro #[derive(Trace)]
, but in case a manual implementation is needed the following suggestions usually apply:
- If a field’s type implements
Trace
, then call itstrace
method. - Try to avoid panicking if not strictly necessary, since it may lead to memory leaks.
- Avoid mixing
Cc
s with other shared-ownership smart pointers likeRc
(aCc
contained inside anRc
cannot be traced, since it’s not owned exclusively). - Never tracing a field is always safe.
- If you need to perform any clean up actions, you should do them in the
Finalize::finalize
implementation (instead of insideDrop::drop
) or using a cleaner.
§Derive macro compatibility
In order to improve the Trace
derive macro usability and error messages, it is suggested to avoid implementing this trait for references or raw pointers
(also considering that no pointed Cc
may be traced, since a reference doesn’t own what it refers to).