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 areIntoHeap
.
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
type In
The type of the value when it is physically stored in the heap.
Required Methods
fn into_heap(self) -> Self::In
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
.)
unsafe fn from_heap(_: &Self::In) -> Self
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.
unsafe fn trace<R>(_: &Self::In, tracer: &mut R) where
R: Tracer,
R: Tracer,
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
impl<'h> IntoHeap<'h> for bool
impl<'h> IntoHeap<'h> for char
impl<'h> IntoHeap<'h> for i8
impl<'h> IntoHeap<'h> for u8
impl<'h> IntoHeap<'h> for i16
impl<'h> IntoHeap<'h> for u16
impl<'h> IntoHeap<'h> for i32
impl<'h> IntoHeap<'h> for u32
impl<'h> IntoHeap<'h> for i64
impl<'h> IntoHeap<'h> for u64
impl<'h> IntoHeap<'h> for isize
impl<'h> IntoHeap<'h> for usize
impl<'h> IntoHeap<'h> for f32
impl<'h> IntoHeap<'h> for f64
impl<'h> IntoHeap<'h> for String
impl<'h, T: ?Sized> IntoHeap<'h> for &'static T
impl<'h, T: ?Sized> IntoHeap<'h> for PhantomData<T>
impl<'h, T: Clone + 'static> IntoHeap<'h> for GCLeaf<T>
impl<'h, T: Clone + 'static> IntoHeap<'h> for Box<T>
impl<'h, T: Clone + 'static> IntoHeap<'h> for Rc<T>
impl<'h, T: IntoHeap<'h>> IntoHeap<'h> for Option<T>
impl<'h> IntoHeap<'h> for ()
impl<'h, T: IntoHeap<'h>> IntoHeap<'h> for (T,)
impl<'h, T: IntoHeap<'h>, U: IntoHeap<'h>> IntoHeap<'h> for (T, U)
impl<'h, T: IntoHeap<'h>, U: IntoHeap<'h>, V: IntoHeap<'h>> IntoHeap<'h> for (T, U, V)
impl<'h, T: IntoHeap<'h>, U: IntoHeap<'h>, V: IntoHeap<'h>, W: IntoHeap<'h>> IntoHeap<'h> for (T, U, V, W)
impl<'h, T: IntoHeap<'h>, U: IntoHeap<'h>, V: IntoHeap<'h>, W: IntoHeap<'h>, X: IntoHeap<'h>> IntoHeap<'h> for (T, U, V, W, X)
impl<'h, T: IntoHeap<'h>, U: IntoHeap<'h>, V: IntoHeap<'h>, W: IntoHeap<'h>, X: IntoHeap<'h>, Y: IntoHeap<'h>> IntoHeap<'h> for (T, U, V, W, X, Y)
impl<'h, T: IntoHeap<'h>, U: IntoHeap<'h>, V: IntoHeap<'h>, W: IntoHeap<'h>, X: IntoHeap<'h>, Y: IntoHeap<'h>, Z: IntoHeap<'h>> IntoHeap<'h> for (T, U, V, W, X, Y, Z)
impl<'h, T: IntoHeap<'h>> IntoHeap<'h> for Vec<T>
impl<'h, T: IntoHeap<'h>> IntoHeap<'h> for VecRef<'h, T>