pub struct ClosureLayout {
pub capture_types: Vec<ConcreteType>,
pub captures: Vec<FieldInfo>,
pub capture_kinds: Vec<CaptureKind>,
pub capture_native_kinds: Vec<NativeKind>,
pub heap_capture_mask: u64,
pub owned_mutable_capture_mask: u64,
pub shared_capture_mask: u64,
pub captures_size: usize,
pub captures_align: usize,
}Expand description
Computed layout for a closure’s captures.
Offsets in captures are relative to the captures area start (i.e.
offset 0 = first byte after the header). Use ClosureLayout::heap_capture_offset
or ClosureLayout::stack_capture_offset for absolute offsets from the
corresponding closure base pointer.
§ADR-006 §2.7.8 / Q10 — per-capture NativeKind companion
capture_native_kinds extends the §2.7.7 stack-side parallel-Vec<NativeKind>
invariant to closure cell storage. Each entry is the NativeKind interpretation
of capture slot i’s 8-byte raw payload — set at construction (lockstep with
capture_types[i] and capture_kinds[i]), read at access/teardown so that
drop dispatch routes through drop_with_kind(bits, kind) (the canonical
KindedSlot::drop table) instead of the deleted ValueWord-shape
vw_drop(bits) (forbidden #8 per §2.7.7) or the also-deleted
Arc<HeapValue> blanket decrement.
Index invariant: capture_types.len() == capture_native_kinds.len() == capture_kinds.len() == captures.len() at every observable boundary.
Storage location. Per ADR-006 §2.7.8 / Q10, the kinds live in the layout
descriptor (constant per ClosureTypeId), NOT in the per-instance raw
closure block. The block’s fixed-offset C-shaped byte buffer is unchanged —
JIT FFI offsets (SHARED_CELL_VALUE_OFFSET, HEAP_CLOSURE_HEADER_SIZE,
per-capture heap_capture_offset(i)) are preserved. The kind track is a
pure side-table on the layout, identical in shape to the §2.7.8 ADR
example for ClosureCell { bits, kinds } but specialised to the
existing OwnedClosureBlock raw-byte form: bits live in the block at
layout.heap_capture_offset(i), kinds live in layout.capture_native_kinds[i].
Fields§
§capture_types: Vec<ConcreteType>The ConcreteType of each capture, in declaration order. Also the
registry key for this layout.
captures: Vec<FieldInfo>Per-capture field info. offset is relative to the captures area start.
capture_kinds: Vec<CaptureKind>Per-capture storage discipline. capture_kinds[i] corresponds to
captures[i] and determines which of the three mutually-exclusive
masks below (if any) has bit i set.
capture_native_kinds: Vec<NativeKind>Per-capture NativeKind companion (ADR-006 §2.7.8 / Q10). Entry i
is the kind interpretation of capture slot i’s raw 8-byte payload
in the closure block. Lockstep with capture_types / capture_kinds
at every observable boundary. Read at access/teardown by drop glue
— the cell-store drop_with_kind(bits, kind) dispatch reads this
per-capture entry to route to the matching Arc<T>::decrement arm.
The default constructor ClosureLayout::from_capture_types derives
this list from capture_types via native_kind_from_concrete_type.
The explicit constructor
ClosureLayout::from_capture_types_with_native_kinds accepts a
caller-supplied list when the kind is finer-grained than what
ConcreteType can express (e.g. NativeKind::Ptr(HeapKind::TypedArray)
vs the generic Ptr field kind).
heap_capture_mask: u64Bitmap: bit N = capture N is a heap-refcounted pointer (Ptr) held
directly in the slot (i.e. CaptureKind::Immutable over a Ptr
field kind). Used by Drop glue to call release_raw_value_bits on
the slot contents.
owned_mutable_capture_mask: u64Bitmap: bit N = capture N is CaptureKind::OwnedMutable. The slot
holds *mut ValueWord (from Box::into_raw); Drop reclaims via
Box::from_raw, which also releases any heap refcount share held
inside the boxed ValueWord.
Bitmap: bit N = capture N is CaptureKind::Shared. The slot holds
*const SharedCell (from Arc::into_raw); Drop reclaims via
Arc::from_raw, which decrements the strong count by one.
captures_size: usizeSize in bytes of the captures area (rounded up to 8-byte alignment). Does NOT include the header.
captures_align: usizeAlignment of the captures area (always 8 in practice).
Implementations§
Source§impl ClosureLayout
impl ClosureLayout
Sourcepub fn from_capture_types(
capture_types: &[ConcreteType],
kinds: &[CaptureKind],
) -> Self
pub fn from_capture_types( capture_types: &[ConcreteType], kinds: &[CaptureKind], ) -> Self
Build a layout from parallel lists of capture types and storage kinds.
Captures are laid out in declaration order with natural alignment padding, starting from offset 0 of the captures area. The total size is rounded up to 8 bytes so the whole closure object is 8-aligned.
For CaptureKind::OwnedMutable / CaptureKind::Shared the slot is
always emitted as a FieldKind::Ptr (8-byte pointer), regardless of
the underlying ConcreteType — the slot holds the raw
*mut ValueWord (Box) or *const SharedCell (Arc), not the value
directly. Only CaptureKind::Immutable honours the natural width of
capture_types[i].
§Invariants on the emitted masks
The three per-index masks are mutually exclusive: for any index
i, at most one of heap_capture_mask, owned_mutable_capture_mask,
shared_capture_mask has bit i set. release_typed_closure
relies on this to avoid double-releases.
§Panics
- If
capture_types.len() != kinds.len(). - If
capture_types.len() > 64(mask-width limit). - If any capture type is
ConcreteType::Void(not a well-formed capture per §2.7.8 / Q10 — seenative_kind_from_concrete_type).
capture_native_kinds is derived from capture_types via
native_kind_from_concrete_type. Use
ClosureLayout::from_capture_types_with_native_kinds when the
caller has a finer-grained kind in hand (e.g. distinguishing
Ptr(HeapKind::TypedArray) vs Ptr(HeapKind::TypedObject) for two
ConcreteType::Pointer(_) captures).
Sourcepub fn from_capture_types_with_native_kinds(
capture_types: &[ConcreteType],
kinds: &[CaptureKind],
native_kinds: &[NativeKind],
) -> Self
pub fn from_capture_types_with_native_kinds( capture_types: &[ConcreteType], kinds: &[CaptureKind], native_kinds: &[NativeKind], ) -> Self
Build a layout from parallel lists of capture types, storage kinds,
and explicit per-capture NativeKinds (ADR-006 §2.7.8 / Q10).
This is the explicit-kinds entry point. The default
ClosureLayout::from_capture_types derives the kinds via
native_kind_from_concrete_type; use this when the caller knows a
finer-grained kind (e.g. specific HeapKind discriminator for a
ConcreteType::Pointer(_) capture) or wants to pin the kind track
to an authoritative source (e.g. FrameDescriptor.slots[binding_idx]
per §2.7.8’s debug cross-check).
§Panics
- If
capture_types.len() != kinds.len()orcapture_types.len() != native_kinds.len(). - If
capture_types.len() > 64(mask-width limit).
Sourcepub fn capture_count(&self) -> usize
pub fn capture_count(&self) -> usize
Number of captures.
Sourcepub fn capture_offset(&self, i: usize) -> usize
pub fn capture_offset(&self, i: usize) -> usize
Offset of capture i from the captures area start (not from the
heap / stack base pointer).
Sourcepub fn capture_kind(&self, i: usize) -> FieldKind
pub fn capture_kind(&self, i: usize) -> FieldKind
FieldKind of capture i.
Sourcepub fn capture_inner_kind(&self, i: usize) -> FieldKind
pub fn capture_inner_kind(&self, i: usize) -> FieldKind
Interior FieldKind of capture i — the type stored inside the
box/cell, not the slot kind.
For Immutable captures this returns the same value as
capture_kind: the slot directly holds a value
of the declared type.
For OwnedMutable and Shared captures the slot kind is always
FieldKind::Ptr (the slot stores *mut T / *const SharedCell),
so capture_kind would lose the underlying type. This method
returns the interior type by consulting capture_types[i] directly.
Drop glue uses this to reconstruct the typed Box<T> for an
OwnedMutable cell.
Sourcepub fn heap_capture_offset(&self, i: usize) -> usize
pub fn heap_capture_offset(&self, i: usize) -> usize
Absolute offset of capture i from the start of a heap-allocated
TypedClosureHeader (i.e. add 16 for the header).
Sourcepub fn stack_capture_offset(&self, i: usize) -> usize
pub fn stack_capture_offset(&self, i: usize) -> usize
Absolute offset of capture i from the start of a StackClosure
(i.e. add 8 for the function_id/type_id pair).
Sourcepub fn total_heap_size(&self) -> usize
pub fn total_heap_size(&self) -> usize
Total size of a heap-allocated closure with this layout:
HeapHeader + function_id + type_id + captures.
Sourcepub fn total_stack_size(&self) -> usize
pub fn total_stack_size(&self) -> usize
Total size of a stack-allocated closure with this layout:
function_id + type_id + captures.
Sourcepub fn is_heap_capture(&self, i: usize) -> bool
pub fn is_heap_capture(&self, i: usize) -> bool
Whether capture i is a heap-refcounted pointer (slot-owned Arc
share on an immutable Ptr capture).
Sourcepub fn is_owned_mutable_capture(&self, i: usize) -> bool
pub fn is_owned_mutable_capture(&self, i: usize) -> bool
Whether capture i is CaptureKind::OwnedMutable — slot holds
*mut ValueWord and must be Box::from_raw’d on drop.
Whether capture i is CaptureKind::Shared — slot holds
*const SharedCell and must be Arc::from_raw’d on drop.
Sourcepub fn capture_storage_kind(&self, i: usize) -> CaptureKind
pub fn capture_storage_kind(&self, i: usize) -> CaptureKind
Storage discipline for capture i.
Sourcepub fn capture_native_kind(&self, i: usize) -> NativeKind
pub fn capture_native_kind(&self, i: usize) -> NativeKind
NativeKind of capture i’s raw 8-byte payload (ADR-006 §2.7.8 /
Q10). Used by drop glue to dispatch through drop_with_kind(bits, kind)
— the canonical KindedSlot::Drop table — rather than the deleted
vw_drop / Arc<HeapValue> blanket-decrement shapes.
For Immutable captures the kind classifies the slot’s payload
directly (e.g. Float64 for an f64 capture, String for an
Arc<String> capture, Ptr(HeapKind::TypedArray) for an
Arc<TypedArrayData> capture).
For OwnedMutable and Shared captures the slot stores a raw
*mut T (Box) or *const SharedCell (Arc) cell pointer — the
kind classifies the interior payload of that cell (the same
shape capture_inner_kind returns at the FieldKind level, but
resolved to NativeKind for kind-aware drop dispatch). The
per-Arc / per-Box drop helper (drop_owned_mutable_capture /
drop_shared_capture) consumes this to release the inner share
before reclaiming the cell allocation itself.
Trait Implementations§
Source§impl Clone for ClosureLayout
impl Clone for ClosureLayout
Source§fn clone(&self) -> ClosureLayout
fn clone(&self) -> ClosureLayout
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more