Skip to content

Segmentation fault with recursive lazy values #12585

@lthls

Description

@lthls

The following program currently segfaults:

let rec x =
  let y () = (Lazy.force x) () in
  let z = if Sys.opaque_identity true then y else fun () -> () in
  lazy z
let () = (Lazy.force x) ()

The core issue: expressions of the form lazy expr are considered as Static by Rec_check, but the optimisations around lazy expressions mean that it could be translated to expr, which has no particular reason to be allowed as a recursive binding. The actual let-rec compilers then get an expression that doesn't have an obvious size, so assumes it must be non-recursive, and generates wrong code.

Among the solutions I can think of:

  • Replicate the logic in translcore.ml for lazy expressions in rec_check.ml, rejecting definitions that would be compiled incorrectly (annoying, but doable)
  • Prevent optimisations of lazy expressions occurring as the definition of a recursive binding (obviously correct, but involves patching translcore.ml in invasive ways)

My work on recursive bindings does not offer a solution to this problem; in fact, it only made it obvious that this case was not handled properly and needs a dedicated fix.

I'm not mentioning the more obviously correct solution of forbidden lazy recursive bindings as it is actually used in camlinternalMod.ml.

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