New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Incorrect interaction between Matching.for_let and Simplif.simplify_exits #7680
Comments
Comment author: @gasche Are you planning to send a github pull request (GPR) to fix this, or should we take care of it? (Is it correct to just use negative numbers in the code produced by this optimization?) |
Comment author: vlaviron I have this fixed as part of my work on exceptions in the backend, but I don't plan to make a specific pull request for this bug. |
Comment author: @alainfrisch I guess dropping the case for Ltrywith in Matching.map_return would fix the problem. Is it worth using a more complex logic to maintain the optimization in presence of try-with as in the reported example? |
Comment author: vlaviron I'm not sure it is sound to drop only one case: if an other branch activates the optimization, you would end up with the trywith branch returning a couple and not triggering the handler, which is just plain wrong. Or alternatively, you could look at what I'm doing on commit da8a7b4 of #1482: it replaces negative numbers in static exceptions with annotations on Lstaticraise, and as a result the fix gets much cleaner. |
Comment author: @alainfrisch
I'm not sure to follow. Removing the case for Ltrywith would have the effect of considering the whole try...with sub-expression to be "opaque" w.r.t. the transformation (as e.g. a function call). The sub expression would not be rewritten, and would simply return a tuple or raise an exception (in the same way a function call could raise an exception). |
Comment author: vlaviron Ah, yes, you're right (I don't know why I supposed that it would mean that Ltrywith would get the Lstaticraise treatment). |
Comment author: @alainfrisch FWIW, the test in testsuite/asmcomp/bind_tuples.ml explicitly relies on the optimization going under try...with. |
Comment author: @alainfrisch Working on a fix in simplif.mf, where we keep track of the try..with nesting to avoid inlining a static handler across a try..with. |
Comment author: @alainfrisch |
Original bug ID: 7680
Reporter: vlaviron
Assigned to: @alainfrisch
Status: resolved (set by @alainfrisch on 2017-12-06T06:57:15Z)
Resolution: fixed
Priority: normal
Severity: minor
Version: 4.06.0
Fixed in version: 4.07.0+dev/beta2/rc1/rc2
Category: middle end (typedtree to clambda)
Monitored by: @alainfrisch
Bug description
Compilation of match ... with exception ... uses Lambda.next_negative_raise_count instead of Lambda.next_raise_count because it generates a Lstaticraise that jumps from inside a Ltrywith block to outside it, and Simplif.simplify_exits is not allowed to move the handler's code inside the trywith block.
The optimisation for compilation of let-bindings of tuples in Matching.for_let can also generate Lstaticraise that jumps outside a Ltrywith block, but it doesn't use a negative raise count so in some cases Simplif.simplify_exits can produce incorrect code.
Steps to reproduce
$ cat bug.ml
let f () =
let (a,b) =
try (1,2)
with _ -> assert false
in
if a + b = 3 then raise Not_found
let _ = try f () with Not_found -> print_endline "Ok"
$ ocamlc -o bug bug.ml
$ ./bug
Fatal error: exception Assert_failure("bug.ml", 4, 14)
Additional information
Found while updating #1482.
The bug is present since 4.03.0, and the corresponding feature is listed in Changes as '#4800: better compilation of tuple assignment'.
The text was updated successfully, but these errors were encountered: