Trait cell_gc::traits::IntoHeap [] [src]

pub unsafe trait IntoHeap<'h>: Sized {
    type In;
    fn into_heap(self) -> Self::In;
    unsafe fn from_heap(_: &Self::In) -> Self;
    unsafe fn trace<R>(_: &Self::In, tracer: &mut R)
    where
        R: Tracer
; }

Trait for values that can be moved into a GC heap.

Cell-gc does not support GC allocation of arbitrary values: only values of types that implement IntoHeap. This trait is not meant to be implemented by hand: use the gc_heap_type! macro instead. All primitive types and many standard types support IntoHeap.

GC types come in pairs: an in-heap type, which is stored physically inside the heap, and may be packed with pointer fields and unsafe methods; and an IntoHeap type, which is safe, is used in application code, and lives on the stack. Both types have the same layout, bit for bit.

(The word "safe" above means that, as with everything generally in Rust, you can hack without fear. IntoHeap types don't expose raw Rust pointers or references to GC memory, they don't expose the unsafe in-heap types, and they obey Rust's safety and aliasing rules.)

Users never get a direct & reference to any in-heap value. All access is through safe IntoHeap types, like the Ref type that is automatically declared for you when you use gc_heap_type! to declare a struct.

  • For primitive types, like i32, the two types are the same.

  • Macro-generated "Ref" types are IntoHeap types; the corresponding in-heap types are effectively raw pointers.

  • For macro-generated structs and enums, the user specifies the names of both types. Both types have identical fields or variants, but fields of the in-heap type are in-heap, and fields of the IntoHeap type are IntoHeap.

Implementation note: every type with 'static lifetime should be safe to store in the heap, because ref types are never 'static. Unfortunately I can't make rustc understand this. It would be legal to write this:

unsafe impl<'h, T: Clone + 'static> IntoHeap<'h> for T { ...trivial... }

but alas, Rust thinks this impl conflicts with almost all others, making it impossible to get the macro to work. So instead we impl IntoHeap for a lot of individual types by hand.

Liveness. Some IntoHeap types ("Ref" types) are effectively smart pointers to in-heap values. To preserve safety, if an IntoHeap value is (or contains) a smart pointer to an in-heap value, then that value (and everything reachable from it) is protected from GC.

Safety

In-heap objects are full of pointers; if into_heap puts garbage into them, GC will crash.

trace must be implemented with care in order to preserve the invariants of the GC graph-walking algorithm. Bugs there are very likely to lead to dangling pointers and hard-to-debug crashes down the road.

And this maybe goes without saying, but none of these methods may allocate or do anything else that could trigger garbage collection.

Associated Types

The type of the value when it is physically stored in the heap.

Required Methods

Convert the value to the form it should have in the heap. This is for macro-generated code to call.

This method must not be called while any direct Rust references to heap objects exist. (However, user code never runs while such references exist, so the method is not marked unsafe.)

Extract the value from the heap. This turns any raw pointers in the in-heap value into safe references, so while it's an unsafe function, the result of a correct call can be safely handed out to user code.

Unsafe to call: It is impossible for ordinary users to call this safely, because self must be a direct, unwrapped reference to a value stored in the GC heap, which ordinary users cannot obtain.

Safety

It is impossible for ordinary users to call this safely, because self must be a direct, unwrapped reference to a value stored in the GC heap, which ordinary users cannot obtain.

Implementors