pub struct Payload<T: Copy> { /* private fields */ }Expand description
A descriptor together with the Rust type of the payload it describes.
TypeDescriptor::builtin takes the payload type P, derives size/align
from it, and then erases it. An allocator that took the payload as a bare
generic could therefore only compare widths at runtime —
gc_alloc(ctx, &scalars::INT, 0) passes an i32, because Rust’s default
integer type is not i64, and aborts the process with “payload size mismatch
for descriptor Int” from inside extern "C". That is the non-unwinding panic
across the ABI §10.4 forbids, and it cannot fire until the wrong call runs.
Payload<T> re-attaches the type. The pairing is checked once, where the
handle is declared — Payload::new is a const fn whose assertions run
during const evaluation, so a static/const handle whose T is not its
descriptor’s payload fails to compile. And because the allocators take
the handle and the value together, the value’s type is checked at every call
site by ordinary type inference. Neither mistake reaches a runtime assert.
Implementations§
Source§impl<T: Copy> Payload<T>
impl<T: Copy> Payload<T>
Sourcepub const fn new(descriptor: &'static TypeDescriptor) -> Payload<T>
pub const fn new(descriptor: &'static TypeDescriptor) -> Payload<T>
Pair descriptor with the payload type T.
Declare the result as a const or static — that is what makes the
check a compile-time one. Called in a runtime expression the assertions
are ordinary ones, which is the situation this type exists to remove.
§Panics
During const evaluation, if T’s layout is not the one descriptor
declares.
Sourcepub const fn descriptor(self) -> &'static TypeDescriptor
pub const fn descriptor(self) -> &'static TypeDescriptor
The descriptor this handle carries. Its address is the type’s identity,
and the handle holds the one static, so that identity survives.
Sourcepub unsafe fn read(self, payload: *const u8) -> T
pub unsafe fn read(self, payload: *const u8) -> T
Read the payload at payload as this handle’s T.
The width is the compiler’s: it is size_of::<T>(), and
Payload::new proved during const evaluation that that is exactly the
descriptor’s declared width. A caller therefore cannot pick a width, and
cannot pick the wrong one — a hand-written read of a one-byte Bool
through an i64 consumes seven bytes of arena padding the allocator
never initialized.
This is the read half of what Payload<T> already does for allocation.
It does not check the object’s descriptor — a handle names a type but
a raw payload pointer carries no header — so callers that hold a GcRef
should reach for the wrapper that checks identity first.
§Safety
payload must point at an initialized payload of this handle’s type,
aligned for T.