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

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.

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
  • Calling GcVisitor::trace with the specified collector
    • GcVisitor::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
    • Garbage collectors may chose to abort if they encounter a panic, so you should avoid doing it if possible.
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
  • Calling other operations on the garbage collector (including allocations)

Implementations on Foreign Types

Implementors