pub struct TemplateRegistry { /* private fields */ }Expand description
Task 7’s owned, 'static substitute for dedup::TemplateTable<'d> (see
this module’s top doc comment) — the minimal (TemplateKey, StateLayout)
registry StateEngine actually needs after elaboration, once the
sv_lang::Design-borrowing dedup walk itself is done.
Review fix (Task 7 r1): each StateLayout is individually boxed, and
templates is UnsafeCell-wrapped so register never needs &mut self. allocate_instance hands out a *const StateLayout pointing
directly into this registry’s backing storage (see
InstanceHandle::layout). Two independent hazards, both now fixed:
- With
templates: Vec<(TemplateKey, StateLayout)>(the pre-fix shape), that pointer targeted theVec’s own tuple element storage — a laterregistercall growing thispub(viaStateEngine.templates), and therefore externally reachable,Veccould reallocate it and silently dangle every previously-mintedlayoutpointer, exactly the hazardregister’s old doc comment warned about without preventing it.Vec<(TemplateKey, Box<StateLayout>)>instead gives eachStateLayoutits own, independent heap allocation: growing the outerVecmoves theBoxpointers around, never theStateLayoutvalues those pointers point at. - Separately (see
StateEngine’s doc comment for the full argument): under Rust’s Stacked/Tree Borrows aliasing model, aBox<T>value being moved — including as a field of a larger struct moved by value, e.g. aStateEnginereturned from a constructor — recursively retags (as freshly, exclusively owned) everything reachable through nestedBox/&/&mutfields, which would silently invalidate alayoutpointer minted before the move even thoughBox<StateLayout>itself never reallocates.templatestherefore usesUnsafeCell(mutated only through&self, never&mut self, exactly likeArena) so thatStateEngine.templatesitself can be anRc, not aBox—Rc’s move doesn’t carry that same recursive-retag semantics (it isn’t a uniquely-owning reference-like type), so Miri’s retag walk never descends into (and therefore never invalidates) the boxedStateLayouts nested inside.
Implementations§
Source§impl TemplateRegistry
impl TemplateRegistry
pub fn new() -> Self
Sourcepub unsafe fn register(&self, key: TemplateKey, layout: StateLayout)
pub unsafe fn register(&self, key: TemplateKey, layout: StateLayout)
Registers one template’s layout. Callable at any time, including
after StateEngine::allocate_instance has already minted one or more
InstanceHandles against this registry (see this struct’s doc
comment for why growing templates no longer moves any
already-registered StateLayout, and never needs to invalidate a
previously-minted layout pointer via a StateEngine move either).
§Safety
The caller must ensure no other live &/&mut borrow into this
registry’s backing Vec (in particular, no live &StateLayout
returned by Self::layout_of) is held across this call, and that
at most one logical writer registers templates at a time — the same
single-logical-writer discipline Arena’s mutating accessors
document. &self, not &mut self, so this can be called through a
Rc<TemplateRegistry> (see StateEngine’s doc comment for why
templates is an Rc, not a Box).
Sourcepub fn layout_of(&self, key: &TemplateKey) -> Option<&StateLayout>
pub fn layout_of(&self, key: &TemplateKey) -> Option<&StateLayout>
Template-relative layout lookup (ST-066-style: never a per-instance
storage offset). Safe: any number of live &StateLayout reads
coexist without aliasing; the aliasing obligation is on the unsafe
Self::register instead (see its doc comment).