gc_arena/
collect.rs

1use crate::context::Collection;
2
3/// A trait for garbage collected objects that can be placed into `Gc` pointers. This trait is
4/// unsafe, because `Gc` pointers inside an Arena are assumed never to be dangling, and in order to
5/// ensure this certain rules must be followed:
6///
7///   1. `Collect::trace` *must* trace over *every* `Gc` pointer held inside this type, and cannot
8///      fail.
9///   2. Held `Gc` pointers must not be accessed inside `Drop::drop` since during drop any such
10///      pointer may be dangling.
11///   3. Internal mutability *must* not be used to adopt new `Gc` pointers without calling
12///      `Gc::write` during the same arena mutation.
13///
14/// It is, however, possible to implement this trait safely by procedurally deriving it (see
15/// [`gc_arena_derive::Collect`]), which requires that every field in the structure also implement
16/// `Collect`, and ensures that `Drop` cannot safely be implemented. Internally mutable types like
17/// `Cell` and `RefCell` do not implement `Collect` in such a way that it is possible to store
18/// `Gc` pointers inside them, so the write barrier requirement cannot be broken when procedurally
19/// deriving `Collect`. A safe way of providing internal mutability in this case is to use
20/// [`crate::lock::Lock<T>`] and [`crate::lock::RefLock<T>`], which provides internal mutability
21/// while ensuring that the write barrier is always executed.
22pub unsafe trait Collect {
23    /// As an optimization, if this type can never hold a `Gc` pointer and `trace` is unnecessary
24    /// to call, you may implement this method and return false. The default implementation returns
25    /// true, signaling that `Collect::trace` must be called.
26    #[inline]
27    fn needs_trace() -> bool
28    where
29        Self: Sized,
30    {
31        true
32    }
33
34    /// *Must* call `Collect::trace` on all held `Gc` pointers. If this type holds inner types that
35    /// implement `Collect`, a valid implementation would simply call `Collect::trace` on all the
36    /// held values to ensure this.
37    #[inline]
38    fn trace(&self, _cc: &Collection) {}
39}