Skip to main content

lower_store_field_ir

Function lower_store_field_ir 

Source
pub fn lower_store_field_ir(
    f: &StoreField,
    program: &CheckedProgram,
) -> StoreFieldIr
Expand description

P6.7 (#1163): lower an agent store field declaration into a real StoreFieldIr — dispatches on f.kind.head.name into StoreKindIr’s five real variants; Queue cannot reach a certified program (bynk.store.kind_unsupported gates it before certify, R3.10), so this match is total over what one can actually contain, not a gap needing its own extension later.

@ttl/@retain millis and @indexed(by: …) field names are read directly off f.annotations, independently of cache_ttl_millis/ store_log_fields/store_map_indexes (bynk-check/the shipped emitter) — the pattern is the same one those already established ([DECISION B]/[DECISION C], #1163), not a call into shared code: this track’s own P6.0 precedent (design/tracks/the-ir.md §3.4, Q4) chose to extend the checker’s typed output once (Callee) rather than let a lowering pass re-derive from the AST the way the shipped emitter’s own dispatcher does, and this constructor falls short of that bar — a real, accepted duplication (three independent copies of the same DurationLit-extraction shape now exist: context_checks.rs, emitter/emit.rs, and here), not one this slice is positioned to close, since none of the three is pub/shaped for a shared caller today. Within this function the @ttl/@retain cases at least share one call each to duration_millis_annotation, rather than repeating the extraction inline a second time. indexed keeps the annotation’s own declaration order, deduplicated — no sort, unlike the shipped emitter’s own doubly-sorted HashMap intermediate ([DECISION E]’s own structural fix, ir.rs’s own StoreFieldIr::indexed doc comment), but still guarding against a duplicate by: key the checker admits (validate_indexed_keys validates each by: argument independently, so @indexed(by: k, by: k) certifies), mirroring the shipped emitter’s own store_map_indexes dedup guard.

init is constructed only for a Cell field ([DECISION D]) — no checker pass types a non-Cell field’s init expression (a real, pre-existing gap this proposal’s own grounding pass found: context_checks.rs’s init-checking loop skips anything that isn’t Cell, and no other pass fills that gap either), so on a certified program such an expression, if ever written, has no expr_types entry — lowering it here would hit this pass’s own ADR 0334 panic on a value the checker never verified, not a recoverable state.

Deliberately not unified with checker::StoreField (bynk-check/src/checker.rs): that dispatch is ephemeral, per-agent checking-time scratch, rebuilt fresh inside check_agent_decls and discarded once that agent’s handler/invariant checking finishes; this constructor produces persistent IR data with no consumer yet. Collapsing them would mean either the checker producing IR-shaped data (crossing the phase-5/ phase-6 boundary the-ir.md §3.4 already drew deliberately) or this pass consuming the checker’s own discarded scratch state across a value that no longer exists once check_agent_decls returns — a real, named duplication (#1163’s own Risks), not a gap this slice closes.