pub struct MirFunction {
pub name: String,
pub blocks: Vec<BasicBlock>,
pub num_locals: u16,
pub param_slots: Vec<SlotId>,
pub param_reference_kinds: Vec<Option<BorrowKind>>,
pub local_types: Vec<LocalTypeInfo>,
pub span: Span,
pub field_name_table: HashMap<FieldIdx, String>,
pub local_struct_type_names: HashMap<SlotId, String>,
pub local_typed_array_element_types: HashMap<SlotId, ConcreteType>,
pub local_declared_scalar_types: HashMap<SlotId, ConcreteType>,
}Expand description
The MIR representation of a single function.
Fields§
§name: String§blocks: Vec<BasicBlock>The basic blocks forming the CFG.
num_locals: u16Number of local variable slots.
param_slots: Vec<SlotId>Which locals are function parameters.
param_reference_kinds: Vec<Option<BorrowKind>>Per-parameter reference kind, aligned with param_slots.
local_types: Vec<LocalTypeInfo>Type information for locals (for Copy/Clone inference).
span: SpanSource span of the function.
field_name_table: HashMap<FieldIdx, String>Mapping from FieldIdx to field name, for JIT field access resolution.
local_struct_type_names: HashMap<SlotId, String>Per-slot user-struct type name for slots produced by
Expr::StructLiteral { name, .. } lowering.
ADR-006 §2.7.5 producing-site classification — Phase 3 cluster-0
Round 13 T1’ gap 1 closure. The bytecode compiler’s
concrete_type_from_annotation
(crates/shape-vm/src/compiler/v2_map_emission.rs:357) does
NOT resolve user-struct names to a per-struct StructLayoutId
(the _ => None arm at line 378), and the conduit producer at
compiler/helpers.rs:508 stamps Struct(StructLayoutId(0))
for every ObjectStore regardless of struct identity. Neither
path makes user-struct type name observable at conduit-time.
This map is populated at MIR lowering for
Expr::StructLiteral { name, .. } sites (the canonical
user-struct construction shape — let t = X {},
let p = Point { x: 1, y: 2 }). The conduit producer reads
the map at Call-terminator destination-stamp time for
MirConstant::Method(_) terminators to look up the trait method
declared return ConcreteType via the
find_default_trait_impl_for_type_method chain.
None (no entry) for slots that aren’t user-struct constructions
— primitives, collections, plain object literals, function returns,
etc. The downstream classifier surfaces unstamped per §2.7.7 #9 /
forbidden #9 (no fabricated default).
local_typed_array_element_types: HashMap<SlotId, ConcreteType>Per-slot empty-typed-array element ConcreteType for slots produced by
let mut <name>: Array<C> = [] lowering (where C is a
concrete_type_from_annotation-resolvable element type).
ADR-006 §2.7.5 stamp-at-compile-time — V3-S6e-jit-specialized-vec- map-aggregate-classify (Phase 3 cluster-0+1 Wave 3 Stabilize Round 2, 2026-05-16; V3-S6 multi-session chain checkpoint-final).
Closes the W11-jit-new-array gap inside monomorphized Vec.map<U> /
Vec.filter<U> specialization bodies. V3-S6a’s
synthesize_empty_array_result_annotation writes
Array<C> onto the let mut result = [] var-decl AST node for the
specialized function; this map captures that annotation at MIR
lowering so the conduit producer at
crates/shape-vm/src/compiler/helpers.rs::infer_top_level_concrete_ types_from_mir_with_resolvers can stamp concrete_types[result_slot] = Array(elem).
Why MIR-level rather than just bytecode-side: the empty array literal
at MIR lowering goes through lower_array_expr →
emit_container_store_if_needed which short-circuits for
ContainerStoreKind::Array with empty operands (helpers.rs:128-130).
No StatementKind::ArrayStore is emitted, so the
helpers.rs:687 ArrayStore walker never fires on empty literals.
The conduit producer has no other source for the element kind on
an empty Aggregate slot.
Producer: mir/lowering/stmt.rs::lower_var_decl (var-decl with
annotation Array<C> AND value Expr::Array(items) with
items.is_empty()).
Consumer: compiler/helpers.rs::infer_top_level_concrete_types_from_ mir_with_resolvers (new pass before slot-move propagation).
None (no entry) for slots that aren’t empty-typed-array-literal
initializations — non-empty array literals flow through the existing
ArrayStore operand-kind inference path; absent annotation means
no proven element kind and the JIT surfaces-and-stops per §2.7.7 #9
forbidden Bool-default.
local_declared_scalar_types: HashMap<SlotId, ConcreteType>Per-slot declared scalar ConcreteType for let-bindings whose
type annotation resolves to a narrow integer width (i8/i16/
i32/u8/u16/u32).
ADR-006 §2.7.5 stamp-at-compile-time — R5c-2-β-γ (c)
jit-narrow-wrap. The MIR Rvalue::Use(Constant(Int(_))) carrier
is width-blind: a bare integer literal has no width, so
infer_top_level_concrete_types_from_mir classifies every
MirConstant::Int as ConcreteType::I64. Top-level let a: i32 = 100 bindings are module bindings (not bytecode locals — see
compiler/compiler_impl_reference_model.rs:1472), so the
bytecode-compiler’s per-local side-tables never carry the
declared narrow width either. Without a width source the JIT
declares the slot as a Cranelift I64 variable and emits
iadd/isub/imul at 64-bit width — overflow does not wrap to
the declared width, diverging from the bytecode VM’s
AddI32/AddTyped truncating opcodes.
This map is populated at MIR lowering for var-decls whose
type_annotation resolves through concrete_type_from_annotation
to one of the narrow integer scalar ConcreteType variants. The
conduit producer
(compiler/helpers.rs::infer_top_level_concrete_types_from_mir_ with_resolvers) reads it to stamp concrete_types[slot] with the
proven narrow width, which the JIT then projects to
NativeKind::Int32/Int8/etc., declares the slot at the matching
Cranelift width, and lowers arithmetic so overflow wraps.
None (no entry) for slots without a narrow-int annotation —
plain int/number/heap types are unaffected.
Producer: mir/lowering/stmt.rs::lower_var_decl.
Consumer: compiler/helpers.rs::infer_top_level_concrete_types_ from_mir_with_resolvers.
Implementations§
Source§impl MirFunction
impl MirFunction
Sourcepub fn entry_block(&self) -> BasicBlockId
pub fn entry_block(&self) -> BasicBlockId
Get the entry block (always block 0).
Sourcepub fn iter_blocks(&self) -> impl Iterator<Item = &BasicBlock>
pub fn iter_blocks(&self) -> impl Iterator<Item = &BasicBlock>
Iterate over all blocks.
Sourcepub fn block(&self, id: BasicBlockId) -> &BasicBlock
pub fn block(&self, id: BasicBlockId) -> &BasicBlock
Get a block by ID.
Sourcepub fn all_points(&self) -> Vec<(Point, BasicBlockId, usize)>
pub fn all_points(&self) -> Vec<(Point, BasicBlockId, usize)>
Linearize all statements into a flat list of points. Returns (point, block_id, statement_index) triples.
Trait Implementations§
Source§impl Clone for MirFunction
impl Clone for MirFunction
Source§fn clone(&self) -> MirFunction
fn clone(&self) -> MirFunction
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for MirFunction
impl RefUnwindSafe for MirFunction
impl Send for MirFunction
impl Sync for MirFunction
impl Unpin for MirFunction
impl UnsafeUnpin for MirFunction
impl UnwindSafe for MirFunction
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<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more