Skip to main content

EffectRow

Struct EffectRow 

Source
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: bool

The 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: bool

NS-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.

§tags: bool

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: bool

NS-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: bool

NS-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

Source

pub fn pessimal() -> EffectRow

The pessimal touches-everything row (spec §3) — always sound, the answer for an Unknown/opaque callee.

Source

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.

Source

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).

Source

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.

Source

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.

Source

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§

Source§

impl Clone for EffectRow

Source§

fn clone(&self) -> EffectRow

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for EffectRow

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Default for EffectRow

Source§

fn default() -> EffectRow

Returns the “default value” for a type. Read more
Source§

impl Eq for EffectRow

Source§

impl PartialEq for EffectRow

Source§

fn eq(&self, other: &EffectRow) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for EffectRow

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Lookup<T> for T

Source§

fn into_owned(self) -> T

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more