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.
The following program currently segfaults:
The core issue: expressions of the form
lazy exprare considered as Static byRec_check, but the optimisations around lazy expressions mean that it could be translated toexpr, 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:
translcore.mlfor lazy expressions inrec_check.ml, rejecting definitions that would be compiled incorrectly (annoying, but doable)translcore.mlin 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.