pub unsafe trait Trace {
const NEEDS_TRACE: bool;
const NEEDS_DROP: bool;
fn trace<V: GcVisitor>(&mut self, visitor: &mut V) -> Result<(), V::Err>;
}
Expand description
Indicates that a type can be traced by a garbage collector.
This doesn’t necessarily mean that the type is safe to allocate in a garbage collector (GcSafe).
Safety
See the documentation of the trace
method for more info.
Essentially, this object must faithfully trace anything that
could contain garbage collected pointers or other Trace
items.
Associated Constants
const NEEDS_TRACE: bool
const NEEDS_TRACE: bool
Whether this type needs to be traced by the garbage collector.
Some primitive types don’t need to be traced at all, and can be simply ignored by the garbage collector.
Collections should usually delegate this decision to their element type,
claiming the need for tracing only if their elements do.
For example, to decide Vec<u32>::NEEDS_TRACE
you’d check whether u32::NEEDS_TRACE
(false),
and so then Vec<u32>
doesn’t need to be traced.
By the same logic, Vec<Gc<u32>>
does need to be traced,
since it contains a garbage collected pointer.
If there are multiple types involved, you should check if any of them need tracing.
One perfect example of this is structure/tuple types which check
field1::NEEDS_TRACE || field2::NEEDS_TRACE || field3::needs_trace
.
The fields which don’t need tracing will always ignored by GarbageCollector::trace
,
while the fields that do will be properly traced.
False negatives will always result in completely undefined behavior. False positives could result in un-necessary tracing, but are perfectly safe otherwise. Therefore, when in doubt you always assume this is true.
If this is true NullTrace
should (but doesn’t have to) be implemented.
const NEEDS_DROP: bool
const NEEDS_DROP: bool
If this type needs a destructor run.
This is usually equivalent to core::mem::needs_drop.
However, procedurally derived code can sometimes provide
a no-op drop implementation (for safety)
which would lead to a false positive with core::mem::needs_drop()
Required methods
Trace each field in this type.
Structures should trace each of their fields, and collections should trace each of their elements.
Safety
Some types (like Gc
) need special actions taken when they’re traced,
but those are somewhat rare and are usually already provided by the garbage collector.
Behavior is restricted during tracing:
Permitted Behavior
- Reading your own memory (includes iteration)
- Interior mutation is undefined behavior, even if you use
GcCell
- Interior mutation is undefined behavior, even if you use
- Calling
GcVisitor::trace
with the specified collectorGcVisitor::trace
already verifies that the ids match, so you don’t need to do that
- Panicking on unrecoverable errors
- This should be reserved for cases where you are seriously screwed up,
and can’t fulfill your contract to trace your interior properly.
- One example is
Gc<T>
which panics if the garbage collectors are mismatched
- One example is
- Garbage collectors may chose to abort if they encounter a panic, so you should avoid doing it if possible.
- This should be reserved for cases where you are seriously screwed up,
and can’t fulfill your contract to trace your interior properly.
Never Permitted Behavior
- Forgetting a element of a collection, or field of a structure
- If you forget an element undefined behavior will result
- This is why you should always prefer automatically derived implementations where possible.
- With an automatically derived implementation you will never miss a field
- It is undefined behavior to mutate any of your own data.
- The mutable
&mut self
is just so copying collectors can relocate GC pointers
- The mutable
- Calling other operations on the garbage collector (including allocations)