Skip to content

Simplif.simplify_lets generates incorrect code if fed its own output #9954

@lthls

Description

@lthls

This is not a real bug, and more a lack of documentation and checks, but Simplif.simplify_lets will generate incorrect code on some seemingly correct lambda inputs. In particular, running the function on its own output can result in incorrect code being produced.

I've found two examples so far (sample ml programs and their lambda output after an extra round of simplify_lets).
Example 1:

let f x =
  let r = ref x in
  r := !r + 1;
  !r

compiles to:

(let (f/82 = (function x/84[int] : int (seq (assign r/85 (+ x/84 1)) x/84)))

The cause is this optimisation, which replaces let x = y in expr by expr[x <- y] even for Variable bindings.

Example 2:

let g () =
  let r = ref 0 in
  let x = !r in
  (fun _ -> x)

compiles to:

(let g/86 =
     (function param/91
       (let (r/88 =v[int] 0) (function param/90 : int r/88)))))

which breaks the invariant that variables bound to a Variable let must not occur in nested function bodies (they can't be passed in the function's closure like regular variables, in general).

This was discovered while trying to force a different type for mutable variables in the lambda representation (and dedicated Llet and Lvar variants). I wasn't sure how to patch simplify_lets in these cases, and it turns out the current code is wrong for those cases where there are already some Variable bindings. Fortunately this cannot occur with the current code paths, as the only place where Variable bindings are generated is in simplify_lets itself, and the function doesn't call itself recursively on the result.

I'd still like to know if other maintainers are bothered by this behaviour and want to discuss how to fix it, or if it's just how it works and it's not worth spending too much time on it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions