pub struct Layout {
pub name: Arc<str>,
pub shape: Shape,
pub words: Vec<Repr>,
}Expand description
The description of one family of values.
Fields§
§name: Arc<str>What a boundary calls a value of this family.
Qualified for a declared type — m.geometry.Point — because a layout
is an identity and two modules may each declare a Point. A rendering
shortens it, which is what the public Display does with the same
string.
shape: Shape§words: Vec<Repr>The words a value of this family occupies in a frame, or inline in a heap object’s payload.
Cached rather than computed, because computing it means walking the layout table and every reader of it is on a path where that would be the expensive part: a frame’s reference map, a copy’s width, a collection’s walk.
One Repr::Ref for every family that lives in the heap, which is
what “a value has a static width or it lives in the heap” means when
written down.
Implementations§
Source§impl Layout
impl Layout
Sourcepub fn object(name: impl Into<Arc<str>>, shape: Shape) -> Layout
pub fn object(name: impl Into<Arc<str>>, shape: Shape) -> Layout
A family that lives in the heap, so a value of it is one reference.
Sourcepub fn inline(
name: impl Into<Arc<str>>,
shape: Shape,
words: Vec<Repr>,
) -> Layout
pub fn inline( name: impl Into<Arc<str>>, shape: Shape, words: Vec<Repr>, ) -> Layout
An inline family, whose words the caller has already flattened.
Sourcepub fn is_one_address(&self) -> bool
pub fn is_one_address(&self) -> bool
Whether a value of this family is the address of an object rather than inline words.
The question is asked of the shape, because the width cannot answer
it and the earlier version of this — “one word wide, and that word is a
Repr::Ref” — got it wrong in a way nothing caught.
struct Error { message: String } is one Repr::Ref word wide and is
an inline struct, not a reference to an Error somewhere; the one
word it occupies is its field, and reading it as the value’s own
address reads the declaration away. A one-field struct is not a rare
shape, and the language ships one.
So: a struct and an enum are inline at every width, a scalar is one
address exactly when its Repr is Repr::Ref, and every remaining
family lives in the heap and is one. Shape::Free is not a value and
answers no.
What turns on it is every place a walk has to choose between reading
the words in front of it and following them: the boundary’s erasure
path, the ordering a Set and a Map are sorted by, and equality.
Sourcepub fn payload_words(&self, len: u32, layouts: &[Layout]) -> u32
pub fn payload_words(&self, len: u32, layouts: &[Layout]) -> u32
How many payload words an object of this layout with header length
len occupies.
len means different things to different shapes — a byte count for a
string, an element count for an array, and nothing at all for a
struct — and this is the one place that difference is written down.
A Struct or an Enum answers its own inline words, because a boxed
value’s payload is the value.
Sourcepub fn try_payload_words(&self, len: u32, layouts: &[Layout]) -> Option<u32>
pub fn try_payload_words(&self, len: u32, layouts: &[Layout]) -> Option<u32>
The same computation, checked against a len this compiler did not
choose.
Layout::payload_words does the multiplication in u32, which is
exactly right for the len every internal caller passes it — a
header’s own length field, or a count crate::lower computed and
which crate::verify has already agreed is small enough. This
is for the one caller that cannot make that assumption:
cove_runtime’s Machine::allocate takes a len an Inst::Alloc
operand supplies, and one of its three Len forms is a slot the
running program computed at run time. A len that large is rare, but
u32 * u32 wraps silently rather than answering wrong loudly, and a
wrapped payload size is an under-allocation followed by writes sized
by the caller’s original, larger len — so this does the same match
in u64, wide enough that len and a stride each at most u32::MAX
cannot overflow the multiply, and answers None rather than a
truncated u32 when the true result does not fit one.
Kept beside Layout::payload_words rather than folded into it: the
two are the same rule at two widths on purpose, not a second, weaker
copy of the first. Widening the arithmetic every internal caller
already trusts to be in range would pay a u64 multiply and a range
check on the collector’s sweep of every live object for a case that
caller cannot hit, on the one path this workspace measures for
allocation cost.
Sourcepub fn fixed_payload_words(&self, layouts: &[Layout]) -> Option<u32>
pub fn fixed_payload_words(&self, layouts: &[Layout]) -> Option<u32>
The same, where the answer is a fact about the layout alone.
None for a shape whose payload the header’s len decides: a
string’s bytes, a run of elements, the value inside a box. The two are
separate questions because a static reader has no header to consult.
crate::verify bounds a field access against the object whose
layout it can prove, and it can only do so where proving the layout is
enough — for a Shape::Str or a Shape::Elements it would still be
guessing at the length.
Sourcepub fn may_hold_refs(&self, layouts: &[Layout]) -> bool
pub fn may_hold_refs(&self, layouts: &[Layout]) -> bool
Whether an object of this layout can hold a reference at all.
The collector uses it to skip an object without looking at any of its
words: a string, an Array<Int> and a boxed scalar are all leaves.
Sourcepub fn field(&self, name: &str) -> Option<&Field>
pub fn field(&self, name: &str) -> Option<&Field>
The field name, if this is a struct-shaped layout.
Trait Implementations§
impl Eq for Layout
impl StructuralPartialEq for Layout
Auto Trait Implementations§
impl Freeze for Layout
impl RefUnwindSafe for Layout
impl Send for Layout
impl Sync for Layout
impl Unpin for Layout
impl UnsafeUnpin for Layout
impl UnwindSafe for Layout
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.