v0.8.16 — RangeInclusive Fix
The Problem
v0.8.15 introduced for-range loop emission — converting While i is at most n to for i in 1..=n. Benchmarks revealed bubble sort regressed by 41.4% at N=2000.
Root cause: Rust's RangeInclusive (..=) carries per-iteration overhead. The internal ExactSizeIterator implementation needs bookkeeping to handle the edge case where the range includes T::MAX. In an O(n^2) inner loop, this overhead compounds.
The test that caught it (tier1a_simple_counting_loop in phase_optimize.rs):
let rust = compile_to_rust(source).unwrap();
assert!(rust.contains("for i in 1..6"));
The assertion checks that the generated Rust uses an exclusive range (1..6) rather than an inclusive one (1..=5).
The Fix
All inclusive ranges now emit the exclusive form with limit + 1:
| Before (v0.8.15) | After (v0.8.16) |
|---|---|
| for i in 1..=5 | for i in 1..6 |
| for i in 1..=n | for i in 1..(n + 1) |
| for j in 1..=((n - 1) - i) | for j in 1..(((n - 1) - i) + 1) |
For literal limits, the addition is computed at compile time — 1..6 not 1..(5 + 1).
Exclusive < bounds are unchanged: for i in 0..5 was already correct.
Bubble Sort Codegen (After Fix)
The inner loop of the bubble sort benchmark now generates:
for j in 1..(((n - 1) - i) + 1) {
if arr[(j - 1) as usize] > arr[((j + 1) - 1) as usize] {
arr.swap((j - 1) as usize, ((j + 1) - 1) as usize);
}
}
No ..= anywhere in generated code. Range (exclusive) uses a simple counter increment with no bookkeeping.