There are cases where the same function compiled twice produces different code for pattern matching. (And compiled more times, produces some unpredictable-looking alternation of the two versions of the code).
This behaviour is not bad per se, as the two versions of the code are equivalent, but surprising and likely not intended.
Noticed here: rescript-lang/rescript#7557
Pattern matching compilation uses a global counter for handler ids. In principle, the value of the counter is irrelevant, however a function reintroduce_fail part of pattern matching compilation iterates on a hash table over handler ids, so the value of the global counter might affect the order in which ids are visited, and does produce different code for the same function below. (The first function changes the global counter, causing the different compilation for the second function).
(* repro.ml *)
type action =
| WithoutPayload1
| WithoutPayload2
| WithPayload2 of { y : int }
| WithPayload3 of { y : int }
| WithPayload5 of { y : int }
| WithPayload6 of { x : int }
| WithPayload7 of { y : int }
| WithPayload8 of { x : int }
let f1 (action : action) =
(match action with
| WithPayload5 _
| WithPayload6 _
| WithPayload7 _
| WithPayload8 _ -> print_endline "hello"
| _ -> ());
42
let f2 (action : action) =
(match action with
| WithPayload5 _
| WithPayload6 _
| WithPayload7 _
| WithPayload8 _ -> print_endline "hello"
| _ -> ());
42
Compilation produces different code for the same function. Here's the lambda output.
This is on 5.2 but the behaviour is a very old one.
% ocamlc -dlambda repro.ml
(setglobal Repro!
(let
(f1/285 =
(function action/287 : int
(seq
(catch
(catch
(switch action/287
case tag 2: (exit 1)
case tag 3: (exit 1)
case tag 4: (exit 1)
case tag 5: (exit 1)
default: (exit 2))
with (2) 0)
with (1) (apply (field_imm 45 (global Stdlib!)) "hello"))
42))
f2/288 =
(function action/290 : int
(seq
(catch
(switch action/290
case int 0: (exit 4)
case int 1: (exit 4)
case tag 0: (exit 4)
case tag 1: (exit 4)
default: (apply (field_imm 45 (global Stdlib!)) "hello"))
with (4) 0)
42)))
(makeblock 0 f1/285 f2/288)))
There are cases where the same function compiled twice produces different code for pattern matching. (And compiled more times, produces some unpredictable-looking alternation of the two versions of the code).
This behaviour is not bad per se, as the two versions of the code are equivalent, but surprising and likely not intended.
Noticed here: rescript-lang/rescript#7557
Pattern matching compilation uses a global counter for handler ids. In principle, the value of the counter is irrelevant, however a function
reintroduce_failpart of pattern matching compilation iterates on a hash table over handler ids, so the value of the global counter might affect the order in which ids are visited, and does produce different code for the same function below. (The first function changes the global counter, causing the different compilation for the second function).Compilation produces different code for the same function. Here's the lambda output.
This is on
5.2but the behaviour is a very old one.