Trait gc_arena::Collect

source ·
pub unsafe trait Collect {
    // Provided methods
    fn needs_trace() -> bool
       where Self: Sized { ... }
    fn trace(&self, _cc: &Collection) { ... }
}
Expand description

A trait for garbage collected objects that can be placed into Gc pointers. This trait is unsafe, because Gc pointers inside an Arena are assumed never to be dangling, and in order to ensure this certain rules must be followed:

  1. Collect::trace must trace over every Gc pointer held inside this type, and cannot fail.
  2. Held Gc pointers must not be accessed inside Drop::drop since during drop any such pointer may be dangling.
  3. Internal mutability must not be used to adopt new Gc pointers without calling Gc::write during the same arena mutation.

It is, however, possible to implement this trait safely by procedurally deriving it (see gc_arena_derive::Collect), which requires that every field in the structure also implement Collect, and ensures that Drop cannot safely be implemented. Internally mutable types like Cell and RefCell do not implement Collect in such a way that it is possible to store Gc pointers inside them, so the write barrier requirement cannot be broken when procedurally deriving Collect. A safe way of providing internal mutability in this case is to use crate::lock::Lock<T> and crate::lock::RefLock<T>, which provides internal mutability while ensuring that the write barrier is always executed.

Provided Methods§

source

fn needs_trace() -> bool
where Self: Sized,

As an optimization, if this type can never hold a Gc pointer and trace is unnecessary to call, you may implement this method and return false. The default implementation returns true, signaling that Collect::trace must be called.

source

fn trace(&self, _cc: &Collection)

Must call Collect::trace on all held Gc pointers. If this type holds inner types that implement Collect, a valid implementation would simply call Collect::trace on all the held values to ensure this.

Implementations on Foreign Types§

source§

impl Collect for bool
where bool: 'static,

source§

impl Collect for char
where char: 'static,

source§

impl Collect for f32
where f32: 'static,

source§

impl Collect for f64
where f64: 'static,

source§

impl Collect for i8
where i8: 'static,

source§

impl Collect for i16
where i16: 'static,

source§

impl Collect for i32
where i32: 'static,

source§

impl Collect for i64
where i64: 'static,

source§

impl Collect for isize
where isize: 'static,

source§

impl Collect for str
where str: 'static,

source§

impl Collect for u8
where u8: 'static,

source§

impl Collect for u16
where u16: 'static,

source§

impl Collect for u32
where u32: 'static,

source§

impl Collect for u64
where u64: 'static,

source§

impl Collect for ()

source§

impl Collect for usize
where usize: 'static,

source§

impl Collect for CString
where CString: 'static,

source§

impl Collect for String
where String: 'static,

source§

impl Collect for TypeId
where TypeId: 'static,

source§

impl Collect for CStr
where CStr: 'static,

source§

impl Collect for OsStr
where OsStr: 'static,

source§

impl Collect for OsString
where OsString: 'static,

source§

impl Collect for Path
where Path: 'static,

source§

impl Collect for PathBuf
where PathBuf: 'static,

source§

impl<A> Collect for (A,)
where A: Collect,

source§

impl<A, B> Collect for (A, B)
where A: Collect, B: Collect,

source§

impl<A, B, C> Collect for (A, B, C)
where A: Collect, B: Collect, C: Collect,

source§

impl<A, B, C, D> Collect for (A, B, C, D)
where A: Collect, B: Collect, C: Collect, D: Collect,

source§

impl<A, B, C, D, E> Collect for (A, B, C, D, E)
where A: Collect, B: Collect, C: Collect, D: Collect, E: Collect,

source§

impl<A, B, C, D, E, F> Collect for (A, B, C, D, E, F)
where A: Collect, B: Collect, C: Collect, D: Collect, E: Collect, F: Collect,

source§

impl<A, B, C, D, E, F, G> Collect for (A, B, C, D, E, F, G)
where A: Collect, B: Collect, C: Collect, D: Collect, E: Collect, F: Collect, G: Collect,

source§

impl<A, B, C, D, E, F, G, H> Collect for (A, B, C, D, E, F, G, H)
where A: Collect, B: Collect, C: Collect, D: Collect, E: Collect, F: Collect, G: Collect, H: Collect,

source§

impl<A, B, C, D, E, F, G, H, I> Collect for (A, B, C, D, E, F, G, H, I)
where A: Collect, B: Collect, C: Collect, D: Collect, E: Collect, F: Collect, G: Collect, H: Collect, I: Collect,

source§

impl<A, B, C, D, E, F, G, H, I, J> Collect for (A, B, C, D, E, F, G, H, I, J)
where A: Collect, B: Collect, C: Collect, D: Collect, E: Collect, F: Collect, G: Collect, H: Collect, I: Collect, J: Collect,

source§

impl<A, B, C, D, E, F, G, H, I, J, K> Collect for (A, B, C, D, E, F, G, H, I, J, K)
where A: Collect, B: Collect, C: Collect, D: Collect, E: Collect, F: Collect, G: Collect, H: Collect, I: Collect, J: Collect, K: Collect,

source§

impl<A, B, C, D, E, F, G, H, I, J, K, L> Collect for (A, B, C, D, E, F, G, H, I, J, K, L)
where A: Collect, B: Collect, C: Collect, D: Collect, E: Collect, F: Collect, G: Collect, H: Collect, I: Collect, J: Collect, K: Collect, L: Collect,

source§

impl<A, B, C, D, E, F, G, H, I, J, K, L, M> Collect for (A, B, C, D, E, F, G, H, I, J, K, L, M)
where A: Collect, B: Collect, C: Collect, D: Collect, E: Collect, F: Collect, G: Collect, H: Collect, I: Collect, J: Collect, K: Collect, L: Collect, M: Collect,

source§

impl<A, B, C, D, E, F, G, H, I, J, K, L, M, N> Collect for (A, B, C, D, E, F, G, H, I, J, K, L, M, N)
where A: Collect, B: Collect, C: Collect, D: Collect, E: Collect, F: Collect, G: Collect, H: Collect, I: Collect, J: Collect, K: Collect, L: Collect, M: Collect, N: Collect,

source§

impl<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O> Collect for (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O)
where A: Collect, B: Collect, C: Collect, D: Collect, E: Collect, F: Collect, G: Collect, H: Collect, I: Collect, J: Collect, K: Collect, L: Collect, M: Collect, N: Collect, O: Collect,

source§

impl<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P> Collect for (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P)
where A: Collect, B: Collect, C: Collect, D: Collect, E: Collect, F: Collect, G: Collect, H: Collect, I: Collect, J: Collect, K: Collect, L: Collect, M: Collect, N: Collect, O: Collect, P: Collect,

source§

impl<K, V> Collect for BTreeMap<K, V>
where K: Collect, V: Collect,

source§

impl<K, V, S> Collect for HashMap<K, V, S>
where K: Collect, V: Collect, S: 'static,

source§

impl<T> Collect for BTreeSet<T>
where T: Collect,

source§

impl<T> Collect for Rc<T>
where T: ?Sized + Collect,

source§

fn trace(&self, cc: &Collection)

source§

impl<T> Collect for Arc<T>
where T: ?Sized + Collect,

source§

fn trace(&self, cc: &Collection)

source§

impl<T> Collect for Cell<T>
where T: 'static,

source§

impl<T> Collect for RefCell<T>
where T: 'static,

source§

impl<T> Collect for PhantomData<T>

source§

impl<T, S> Collect for HashSet<T, S>
where T: Collect, S: 'static,

source§

impl<T: Collect> Collect for Option<T>

source§

impl<T: Collect> Collect for [T]

source§

impl<T: Collect> Collect for LinkedList<T>

source§

impl<T: Collect> Collect for VecDeque<T>

source§

impl<T: Collect> Collect for Vec<T>

source§

impl<T: Collect, E: Collect> Collect for Result<T, E>

source§

impl<T: Collect, const N: usize> Collect for [T; N]

source§

impl<T: ?Sized + 'static> Collect for &'static T

SAFETY: We know that a &'static reference cannot possibly point to 'gc data, so it is safe to keep in a rooted objet and we do not have to trace through it.

HOWEVER, There is an extra bound here that seems superfluous. If we have a &'static T, why do we require T: 'static, shouldn’t this be implied, otherwise a &'static T would not be well- formed? WELL, there are currently some neat compiler bugs, observe…

let arena = Arena::<Rootable![&'static Gc<'gc, i32>]>::new(Default::default(), |mc| {
    Box::leak(Box::new(Gc::new(mc, 4)))
});

At the time of this writing, without the extra T: static bound, the above code compiles and produces an arena with a reachable but un-traceable Gc<'gc, i32>, and this is unsound. This is ofc the stored type of the root, since the Arena is actually constructing a &'static Gc<'static, i32> as the root object, but this should still not rightfully compile due to the signature of the constructor callback passed to Arena::new. In fact, the ’static lifetime is a red herring, it is possible to change the internals of Arena such that the ’gc lifetime given to the callback is not ’static, and the problem persists.

It should not be required to have this extra lifetime bound, and yet! It fixes the above issue perfectly and the given example of unsoundness no longer compiles. So, until this rustc bug is fixed…

DO NOT REMOVE THIS EXTRA T: 'static BOUND

source§

impl<T: ?Sized + Collect> Collect for Box<T>

source§

fn trace(&self, cc: &Collection)

Implementors§

source§

impl<'gc> Collect for DynamicRootSet<'gc>

source§

impl<'gc, T: Collect + 'gc> Collect for RefLock<T>

source§

impl<'gc, T: Collect + Copy + 'gc> Collect for Lock<T>

source§

impl<'gc, T: ?Sized + 'gc> Collect for Gc<'gc, T>

source§

impl<'gc, T: ?Sized + 'gc> Collect for GcWeak<'gc, T>

source§

impl<T: 'static> Collect for StaticCollect<T>