Skip to content

-O0 miscompiles unused struct-returning call inside while loop #1463

Description

@g-r-a-n-t

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions