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
traceimplementation can trace (maximum once) everyCcinstance exclusively owned byself. No otherCcinstance can be traced. - It’s always safe to panic.
- During the same tracing phase (see below), two different
tracecalls on the same value must behave the same, i.e. they must trace the sameCcinstances.
If a panic happens during the second of suchtracecalls but not in the first one, then theCcinstances traced during the second call must be a subset of theCcinstances traced in the first one.
Tracing can be detected using thestate::is_tracingfunction. If it never returnedfalsebetween twotracecalls on the same value, then they are part of the same tracing phase. - The
traceimplementation must not create, clone, move, dereference or drop anyCc. - If the implementing type implements
Drop, then theDrop::dropimplementation must not create, clone, move, dereference, drop or call any method on anyCcinstance.
§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 itstracemethod. - Try to avoid panicking if not strictly necessary, since it may lead to memory leaks.
- Avoid mixing
Ccs with other shared-ownership smart pointers likeRc(aCccontained inside anRccannot 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::finalizeimplementation (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).