pub struct MirFn {
pub fn_id: FnId,
pub name: String,
pub params: Vec<MirParam>,
pub return_type: String,
pub effects: Vec<MirEffectAnnotation>,
pub body: Spanned<MirExpr>,
pub local_count: u32,
pub aliased_slots: Arc<Vec<bool>>,
pub repr: MirFnRepr,
}Expand description
One function in Core MIR. Body is a single MirExpr — MIR is
expression-based, so the function’s body is the expression that
produces its return value. Let chains within the body bind
intermediate results; there’s no separate “block” or
“terminator” concept at this phase.
Fields§
§fn_id: FnIdStable identity for this function. Matches the FnId issued
by SymbolTable during the existing pipeline; downstream
consumers can cross-reference ProofIR / ProgramShape by
the same id.
name: StringSource-level name. Carried for dumps + diagnostics; backends
must not key off this string for identity — that’s what
fn_id is for.
params: Vec<MirParam>Parameters in declaration order. Each gets a fresh LocalId
at lowering time so the body can refer to it.
return_type: StringSource-level return type annotation as it appears on the fn
signature. Phase 4 backends consume this for VM stack-slot
layout; later phases may replace it with a richer type
representation when the typechecker’s Type enum becomes
the universal vocabulary.
effects: Vec<MirEffectAnnotation>Declared effects (! [Namespace.method, ...]). Function-
level only — per-call-site effect annotation is deferred to
the Phase 6 optimizer track per the RFC.
body: Spanned<MirExpr>The single expression that, when evaluated, produces the
function’s return value. Wrapped in Spanned so the body’s
own source location stays available to dumps / diagnostics
(the surrounding MirFn has its own identity layer via
fn_id, but the body span is needed for sub-expression
errors that don’t carry a closer one).
local_count: u32Number of frame slots the lowered body needs: the resolver’s
local_count plus any synthetic slots minted for opaque-let
temps during stmt-chain lowering. The VM walker reserves this
many slots; using the resolver’s count alone underruns the
frame when the body stores into a synthetic slot.
aliased_slots: Arc<Vec<bool>>Per-slot alias-proneness, indexed by LocalId/slot: true
when the resolver’s alias analysis flagged the slot as possibly
sharing its backing engine array/struct with another binding.
Backends combine it with a node’s last_use to gate the
owned-mutate fast path (owned = last_use && !aliased) — the
VM’s owned-mask and the wasm-gc clone-on-write skip. Carried on
the MIR fn so MIR consumers read this ownership fact off MIR
instead of reaching back into the AST FnResolution
side-channel. Cloned from the resolver at lowering today; a
later phase recomputes it as a MIR analysis pass. An
out-of-range slot reads false (not aliased → fast path sound),
matching the resolver tables.
repr: MirFnReprInt-representation tags (ETAP-2). Populated ONLY by the
bare_i64::rewrite_for_rust MIR->MIR pass on the per-target clone
the Rust backend codegens from; default-empty everywhere else (so
the VM / wasm-gc / proof MIR keep all-Int representation). When a
slot is in MirFnRepr::bare_slots it is a raw machine i64 for
its whole lifetime (its reads render native i64, arithmetic over
raw slots stays raw); every crossing into an Int context is an
explicit super::expr::MirExpr::Box node the rewrite inserted.
This is the per-value representation tag made explicit ON the IR –
backends read it off the rewritten MirFn instead of re-deriving
from the BareI64Facts side table.