Trait zerogc::Trace [−][src]
pub unsafe trait Trace { const NEEDS_TRACE: bool; fn visit<V: GcVisitor>(&mut self, visitor: &mut V) -> Result<(), V::Err>; }
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
[src]
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.
Required methods
fn visit<V: GcVisitor>(&mut self, visitor: &mut V) -> Result<(), V::Err>
[src]
Visit each field in this type
Users should never invoke this method, and always call the V::visit
instead.
Only the collector itself is premitted to call this method,
and it is undefined behavior for the user to invoke this.
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.
Unless I explicitly document actions as legal I may decide to change i.
I am only bound by the constraints of semantic versioning in the trace function
if I explicitly document it as safe behavior in this method’s documentation.
If you try something that isn’t explicitly documented here as permitted behavior,
the collector may choose to override your memory with 0xDEADBEEF
.
Always Permitted
- 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::visit
with the specified collectorGarbageCollector::trace
already verifies that it owns the data, so you don’t need to do that
- Panicking
- 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
- This rule may change in future versions, depending on how we deal with multi-threading.
- 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 we always prefer automatically derived implementations where possible.
- You will never trigger undefined behavior with an automatic implementation, and it’ll always be completely sufficient for safe code (aside from destructors).
- 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
- Invoking this function directly, without delegating to
GcVisitor
Implementations on Foreign Types
impl<T> Trace for PhantomData<T>
[src]
impl<T> Trace for PhantomData<T>
[src]impl<E, F, G, H, I> Trace for (E, F, G, H, I) where
E: Trace,
F: Trace,
G: Trace,
H: Trace,
I: Trace,
[src]
impl<E, F, G, H, I> Trace for (E, F, G, H, I) where
E: Trace,
F: Trace,
G: Trace,
H: Trace,
I: Trace,
[src]impl<D, E, F, G, H, I> Trace for (D, E, F, G, H, I) where
D: Trace,
E: Trace,
F: Trace,
G: Trace,
H: Trace,
I: Trace,
[src]
impl<D, E, F, G, H, I> Trace for (D, E, F, G, H, I) where
D: Trace,
E: Trace,
F: Trace,
G: Trace,
H: Trace,
I: Trace,
[src]impl<C, D, E, F, G, H, I> Trace for (C, D, E, F, G, H, I) where
C: Trace,
D: Trace,
E: Trace,
F: Trace,
G: Trace,
H: Trace,
I: Trace,
[src]
impl<C, D, E, F, G, H, I> Trace for (C, D, E, F, G, H, I) where
C: Trace,
D: Trace,
E: Trace,
F: Trace,
G: Trace,
H: Trace,
I: Trace,
[src]impl<B, C, D, E, F, G, H, I> Trace for (B, C, D, E, F, G, H, I) where
B: Trace,
C: Trace,
D: Trace,
E: Trace,
F: Trace,
G: Trace,
H: Trace,
I: Trace,
[src]
impl<B, C, D, E, F, G, H, I> Trace for (B, C, D, E, F, G, H, I) where
B: Trace,
C: Trace,
D: Trace,
E: Trace,
F: Trace,
G: Trace,
H: Trace,
I: Trace,
[src]impl<A, B, C, D, E, F, G, H, I> Trace for (A, B, C, D, E, F, G, H, I) where
A: Trace,
B: Trace,
C: Trace,
D: Trace,
E: Trace,
F: Trace,
G: Trace,
H: Trace,
I: Trace,
[src]
impl<A, B, C, D, E, F, G, H, I> Trace for (A, B, C, D, E, F, G, H, I) where
A: Trace,
B: Trace,
C: Trace,
D: Trace,
E: Trace,
F: Trace,
G: Trace,
H: Trace,
I: Trace,
[src]impl<'a, T: 'a> Trace for &'a T where
T: TraceImmutable,
[src]
impl<'a, T: 'a> Trace for &'a T where
T: TraceImmutable,
[src]impl<T: TraceImmutable> Trace for Rc<T> where
T: Trace,
[src]
impl<T: TraceImmutable> Trace for Rc<T> where
T: Trace,
[src]impl<T: TraceImmutable> Trace for Arc<T> where
T: Trace,
[src]
impl<T: TraceImmutable> Trace for Arc<T> where
T: Trace,
[src]impl<T: TraceImmutable> Trace for HashSet<T> where
T: Trace,
[src]
impl<T: TraceImmutable> Trace for HashSet<T> where
T: Trace,
[src]Implementors
impl Trace for DummyCollectorId
[src]
impl Trace for DummyCollectorId
[src]impl<'gc, T: GcSafe + 'gc, Id: CollectorId> Trace for Gc<'gc, T, Id>
[src]
impl<'gc, T: GcSafe + 'gc, Id: CollectorId> Trace for Gc<'gc, T, Id>
[src]impl<T> Trace for AssumeNotTraced<T>
[src]
impl<T> Trace for AssumeNotTraced<T>
[src]impl<T: Trace + Copy> Trace for GcCell<T>
[src]
impl<T: Trace + Copy> Trace for GcCell<T>
[src]GcCell can only support mutating types that are NullTrace
,
because garbage collected types need write barriers.
However, this is already enforced by the bounds of GcCell::set
,
so we don’t need to verify here.
In other words is possible to safely trace a GcCell
with a garbage collected type, as long as it is never mutated.