Follow-on consolidation. The static half — const-folding Int.div/Int.mod with a constant divisor to a literal Result, plus the general "fold a consumer over a known constructor" (withDefault/match/? over a literal Result.Ok/Err or Option.Some/None) — ships in 0.24 "Divide". This ticket is the runtime half + the cleanup it enables.
What's left
The static fold only fires when the producer is a literal constructor. The runtime consume-immediately patterns are still handled by classify-time special-case fusions:
Result.withDefault(Int.div(a, b), d) with variable b (src/ir/leaf.rs / src/ir/hir/classify.rs, IntDivOrDefaultLiteral).
match Map.get(m, k) { Some(v) -> … ; None -> … } (no Option allocation).
Option.withDefault(Vector.get(v, i), d).
- … other fused leaf-ops / VM opcodes.
These are runtime fusions living in the wrong layer (classify/codegen special-cases). With the 0.24 static fold in place, the clean end-state is one mechanism in MIR:
- a general MIR rewrite
withDefault(<runtime Result/Option producer>, d) → <producer with the runtime default inlined> (the variable-divisor / Map.get / Vector.get cases), and match <runtime producer> { … } fused likewise,
- then retire the classify-time fused leaf-ops + their per-backend codegen paths and the fused VM opcodes.
Why
Two mechanisms currently do "avoid the Result/Option round-trip": the new 0.24 static MIR fold and the old classify-time fusions. That overlap is a smell — the fusion belongs in MIR, generally. This fits the broader cleanup of moving deforestation + ownership + fusion onto MIR and deleting the pre-MIR/classify special-cases.
Acceptance
- The runtime
withDefault/match fusions are MIR rewrites; the classify-time IntDivOrDefaultLiteral and the Map.get/Vector.get fused leaf-ops + fused VM opcodes are gone.
- No regression in the byte-differential / behavioural suites; the fused-path perf is preserved (or improved) — verified by
aver bench.
Follow-on consolidation. The static half — const-folding
Int.div/Int.modwith a constant divisor to a literalResult, plus the general "fold a consumer over a known constructor" (withDefault/match/?over a literalResult.Ok/ErrorOption.Some/None) — ships in 0.24 "Divide". This ticket is the runtime half + the cleanup it enables.What's left
The static fold only fires when the producer is a literal constructor. The runtime consume-immediately patterns are still handled by classify-time special-case fusions:
Result.withDefault(Int.div(a, b), d)with variableb(src/ir/leaf.rs/src/ir/hir/classify.rs,IntDivOrDefaultLiteral).match Map.get(m, k) { Some(v) -> … ; None -> … }(noOptionallocation).Option.withDefault(Vector.get(v, i), d).These are runtime fusions living in the wrong layer (classify/codegen special-cases). With the 0.24 static fold in place, the clean end-state is one mechanism in MIR:
withDefault(<runtime Result/Option producer>, d) → <producer with the runtime default inlined>(the variable-divisor /Map.get/Vector.getcases), andmatch <runtime producer> { … }fused likewise,Why
Two mechanisms currently do "avoid the Result/Option round-trip": the new 0.24 static MIR fold and the old classify-time fusions. That overlap is a smell — the fusion belongs in MIR, generally. This fits the broader cleanup of moving deforestation + ownership + fusion onto MIR and deleting the pre-MIR/classify special-cases.
Acceptance
withDefault/matchfusions are MIR rewrites; the classify-timeIntDivOrDefaultLiteraland the Map.get/Vector.get fused leaf-ops + fused VM opcodes are gone.aver bench.