pub struct FnRow(/* private fields */);Expand description
The effect row riding a Ty::Fn — docs/effects-spec.md §5 (“rows ride
the unifier — the heap answer”), issue #1680 step 3.
What a row is, concretely. §7 rules that “the runtime never computes a
row … a live fn value is a token; its row is a table lookup” in the
shipped DefinitionId → row table. So the thing a type has to carry is
not a computed EffectRow but the set of in-project
creation targets whose fn values may inhabit the slot — the keys that
table is looked up by. §6.1a is what makes that the right (and the only
acyclic) choice: “§6.1 fixes every fn value’s row at its creation site and
creation sites are syntactic: #fn(g) names g literally, and bind
copies from an already-known value rather than naming a new target.” A
target set is therefore structural evidence, never an inferred row, so
growing it onto Ty cannot put an inferred row inside the
call_graph → scc_membership → solve_scc fixpoint the way Fork A’s
rejected shape would have.
The lattice. unknown is the top element (the conservative-total floor
of §3): “some fn value from a source this slot’s type cannot name may
reach here”. FnRow::join is set union with unknown absorbing, which
is exactly §5’s “a cell or collection’s element type accumulates the join
of every fn value assigned into it, through copies, parameters, returns,
and nesting”. That absorption is on the unknown row, not on every
untraceable-looking write: a write typed plain Ty::Unknown (an
unresolved reference, or an unregistered EXTERNAL’s return) unifies
through Ty::Unknown’s own identity arm, not through this lattice at
all, and so leaves the other operand’s row untouched rather than
poisoning it to unknown.
Not yet read by the effect walk. def_effect_atoms deliberately runs
the body walk with empty globals and empty signatures (§6.1a’s acyclicity
is load-bearing on that), so a #fn literal types as Unknown there and
this row is invisible to effect inference as currently constructed.
Wiring §6 mechanism 3 — the heap — means deciding which stratum reads
the type-carried row, which the 2026-07-28 sitting did not settle; see
docs/effects-spec.md §6.1c.
Represented as an Option<Box<…>> so the common Ty::Fn stays one
pointer wider rather than three words wider — Ty is copied constantly
through the join.
Implementations§
Source§impl FnRow
impl FnRow
Sourcepub fn unknown() -> Self
pub fn unknown() -> Self
The top element: nothing is known about where the values inhabiting
this slot were created. Also Default, so every Ty::Fn built
without explicit creation evidence is conservative by construction.
Sourcepub fn of_target(target: DefinitionId) -> Self
pub fn of_target(target: DefinitionId) -> Self
The row of a fn value created here, at a #fn(target, …) literal
naming target — the one syntactic creation form (§6.1a).
Sourcepub fn empty() -> Self
pub fn empty() -> Self
The empty row: this slot provably holds no in-project fn value. Only reachable through a join that started here; never minted directly.
Sourcepub fn is_unknown(&self) -> bool
pub fn is_unknown(&self) -> bool
true when this row is the top element (FnRow::unknown).
Sourcepub fn targets(&self) -> Option<&BTreeSet<DefinitionId>>
pub fn targets(&self) -> Option<&BTreeSet<DefinitionId>>
The creation targets, or None when the row is the top element.
A caller that wants the conservative reading must treat None as
“every target”, never as “no targets”.
Trait Implementations§
impl Eq for FnRow
Source§impl Ord for FnRow
impl Ord for FnRow
1.21.0 (const: unstable) · Source§fn max(self, other: Self) -> Selfwhere
Self: Sized,
fn max(self, other: Self) -> Selfwhere
Self: Sized,
1.21.0 (const: unstable) · Source§fn min(self, other: Self) -> Selfwhere
Self: Sized,
fn min(self, other: Self) -> Selfwhere
Self: Sized,
Source§impl PartialOrd for FnRow
impl PartialOrd for FnRow
impl StructuralPartialEq for FnRow
Auto Trait Implementations§
impl Freeze for FnRow
impl RefUnwindSafe for FnRow
impl Send for FnRow
impl Sync for FnRow
impl Unpin for FnRow
impl UnsafeUnpin for FnRow
impl UnwindSafe for FnRow
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> Comparable<K> for Q
impl<Q, K> Comparable<K> for Q
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§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.