fe test -O0 appears to miscompile a while loop that stores the result of one struct-returning function call, then performs a second unused struct-returning function call in the same loop body.
The same source passes at -O1 and -O2.
Version
fe 26.1.0
Minimal Reproduction
pub struct Point { pub x: u256, pub y: u256 }
pub fn point_add(_ p: Point, _ q: Point) -> Point {
Point { x: p.x + q.x, y: p.y + q.y }
}
pub fn repro() -> Point {
let mut rx: u256 = 0
let mut ry: u256 = 1
let mut s: u256 = 1
while s > 0 {
let r = point_add(Point { x: rx, y: ry }, Point { x: 5, y: 7 })
rx = r.x
ry = r.y
let _unused = point_add(Point { x: 5, y: 7 }, Point { x: 5, y: 7 })
s = 0
}
Point { x: rx, y: ry }
}
#[test]
fn returns_saved_result_not_unused_result() {
let result = repro()
assert(result.x == 5)
assert(result.y == 8)
}
Commands
fe check repro.fe
fe test -O0 repro.fe --call-trace
fe test -O1 repro.fe
fe test -O2 repro.fe
Observed
fe check passes.
-O0 fails:
FAIL [0.0004s] returns_saved_result_not_unused_result
Test reverted: 0x4e487b710000000000000000000000000000000000000000000000000000000000000001
--- call trace ---
CALL $0 data= -> revert ret=4e487b710000000000000000000000000000000000000000000000000000000000000001
--- end trace ---
test result: FAILED. 0 passed; 1 failed
-O1 and -O2 both pass:
PASS [0.0002s] returns_saved_result_not_unused_result
test result: ok. 1 passed; 0 failed
Expected
-O0, -O1, and -O2 should all return Point { x: 5, y: 8 } and pass the test.
Extra Note
If the test is changed to assert the unused call’s result, Point { x: 10, y: 14 }, it passes at -O0. That suggests the second unused struct-returning call may be overwriting, aliasing, or being read in place of the saved result.
fe test -O0appears to miscompile awhileloop that stores the result of one struct-returning function call, then performs a second unused struct-returning function call in the same loop body.The same source passes at
-O1and-O2.Version
fe 26.1.0
Minimal Reproduction
Commands
Observed
fe checkpasses.-O0 fails:
-O1 and -O2 both pass:
Expected
-O0, -O1, and -O2 should all return Point { x: 5, y: 8 } and pass the test.
Extra Note
If the test is changed to assert the unused call’s result,
Point { x: 10, y: 14 }, it passes at -O0. That suggests the second unused struct-returning call may be overwriting, aliasing, or being read in place of the saved result.