pub struct EffectRow {
pub reads: BTreeSet<DefinitionId>,
pub writes: BTreeSet<DefinitionId>,
pub calls: BTreeSet<String>,
pub opaque: bool,
pub emits: bool,
pub tags: bool,
pub faults: bool,
pub faults_refined: bool,
pub holes: BTreeSet<u32>,
}Expand description
A static summary of the atomic effects a definition (and everything it
transitively calls) may perform — the spec §2 “row”. Unordered sets over a
finite per-project lattice, so join is a monotone
least-upper-bound and the per-SCC fixpoint terminates without widening.
opaque is the top element of that lattice: when set, the row is treated
as touching every cell and calling every kind regardless of the listed
members — the conservative-total floor (spec §3) for a call whose effects
inference cannot see (a call through a function value, an unresolved
callee). covers reads it as “⊒ everything”.
Fields§
§reads: BTreeSet<DefinitionId>Cells (VAR/CONST global DefinitionIds) this row may read. Seeded
from FG-2.1’s referenced_globals per-def read-set (spec §4).
writes: BTreeSet<DefinitionId>Cells this row may write (assignment targets resolving to a VAR/CONST).
calls: BTreeSet<String>EXTERNAL binding names (the call-kinds, spec §2) this row may
transitively call.
opaque: boolThe pessimal top element (spec §3): this row performs a call whose effects inference cannot summarize — a call through a function value with no visible row, or an unresolved callee. An opaque row is sound against any concrete row it might stand in for.
emits: boolNS-A2 (issue #1108, from #1087): the definition may produce content
— narration/dialogue fragments a host renders (text, interpolations,
glue-only output counts; ruled 2026-07-18). Tag-only lines do NOT set
this — tags are the metadata channel, tracked by Self::tags
(maintainer ruling refinement on #1087). Bool granularity v1.
NS-A2 (issue #1108, from #1087’s second ruling): the definition may
touch the tag channel — line tags, tag-only lines, choice tags.
Independent of Self::emits: a flow can be silent-but-annotating,
narrating-but-untagged, both, or neither. Bool granularity v1.
faults: boolNS-A2 (issue #1108, from #1097): the definition may raise a
turn-terminating fault — the designed domain-fault inventory
(E078-lineage conversions, OOB indexing, missing-key reads,
division by zero, the A1 StdlibWrongType/NotOrderable stdlib
faults, projection invalidation, value-call dispatch faults). Bool
granularity v1; per-fault-kind is the reserved refinement.
faults_refined: boolNS-A4 / F29(a) (ruled by delegation 2026-07-19, stdlib-spec
§4b): the refined faults bit — like faults but
with charge sites discharged by local type evidence where the
walk can prove the construct total (a wrong-type-only intrinsic
over a provably-right-typed argument, float division, for over a
provable collection, an int-bounded range literal). Invariant:
faults_refined → faults (the refinement only ever removes
charges). Consumed by the protocol-impl contract gate (E114): a
display/compare impl whose row is provably total does NOT
inherit the conservative bit; the conservative union applies only
when the impl’s own row is opaque or genuinely fault-bearing.
Deliberately NOT part of covers/
is_empty semantics (those stay anchored to the
conservative bit — the ground-truth harness and assertion checks
must keep the no-under-report property), and never serialized into
the .inkb EffectRows section.
holes: BTreeSet<u32>§6.1 row variables — the “row with a hole” (docs/effects-spec.md
§6 mechanism 1 and §6.1b; Fork C of issue #1680, ruled 2026-07-28).
Each member is the declaration index of one of this definition’s own
fn-typed params that the body calls through. The row is
therefore parametric: its true effects are this row’s listed atoms
⊔ the row of whatever fn value the caller passes in that position.
A hole is not a second opacity bit. opaque stays
the intrinsic floor (a call inference genuinely cannot see);
is_pessimal is the effective floor every
consumer must read, and it is true for any row with an unfilled
hole. That keeps the conservative-total direction (spec §3) exactly as
it was: a higher-order definition read on its own is still pessimal.
The precision arrives one hop up, in solve_scc_effects, which
instantiates the hole from the caller’s structurally-traced
argument origins (EffectAtoms::call_fn_args) and so no longer
inherits the callee’s floor.
Shallow by construction (§6.1: “every value’s row is fixed at its creation site”): a hole is filled with ground rows, never with another hole — an argument that is itself a fn-typed param, or a target whose own row still holes, falls back to the floor rather than chaining.
Implementations§
Source§impl EffectRow
impl EffectRow
Sourcepub fn pessimal() -> EffectRow
pub fn pessimal() -> EffectRow
The pessimal touches-everything row (spec §3) — always sound, the
answer for an Unknown/opaque callee.
Sourcepub fn is_pessimal(&self) -> bool
pub fn is_pessimal(&self) -> bool
The effective pessimal floor — the bit every consumer of a row
must read in place of opaque.
opaque records only intrinsic opacity (a call whose effects
inference genuinely cannot see). A row that carries §6.1
holes is equally unusable on its own: its true
effects depend on an argument the definition has not been given yet.
Reading such a row as non-pessimal would under-report — the one thing
spec §3 forbids — so an unfilled hole tops the lattice exactly like
opaque does. Only solve_scc_effects, which can fill the hole
from the call site, is entitled to look past it.
Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Whether this row lists (or subsumes) nothing at all — an empty, non-opaque row (a genuinely pure·silent·untagged·total definition).
Sourcepub fn join(&mut self, other: &EffectRow)
pub fn join(&mut self, other: &EffectRow)
Fold other into self — the lattice join (set union per component,
opaque/emits/tags/faults are sticky). Monotone: self only
ever grows, which is what makes the solve_scc_effects fixpoint
converge over the finite cells + kinds universe.
Sourcepub fn join_atoms(&mut self, other: &EffectRow)
pub fn join_atoms(&mut self, other: &EffectRow)
join minus the holes component — the
join used when folding a callee’s row into a caller.
A hole is an index into the callee’s own param list; carrying it up
into the caller’s row would silently reinterpret it against the
caller’s params, which is neither sound nor meaningful. The caller
instead discharges each of the callee’s holes explicitly (fill it from
the call site’s traced argument, or take the pessimal floor) — see
solve_scc_effects.
Sourcepub fn covers(&self, other: &EffectRow) -> bool
pub fn covers(&self, other: &EffectRow) -> bool
Whether self conservatively covers (⊒) other: every atom other
admits, self also admits. An opaque self covers anything; a
non-opaque self can never cover an opaque other. This is the
no-under-report relation the conservative-total property tests assert
(spec §3): a def’s inferred row must cover its own body atoms and every
callee’s row.
Trait Implementations§
impl Eq for EffectRow
impl StructuralPartialEq for EffectRow
Auto Trait Implementations§
impl Freeze for EffectRow
impl RefUnwindSafe for EffectRow
impl Send for EffectRow
impl Sync for EffectRow
impl Unpin for EffectRow
impl UnsafeUnpin for EffectRow
impl UnwindSafe for EffectRow
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,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.