diff --git a/changes/untagged-bool-payload-match.fix.md b/changes/untagged-bool-payload-match.fix.md new file mode 100644 index 0000000000..1e0eb099a4 --- /dev/null +++ b/changes/untagged-bool-payload-match.fix.md @@ -0,0 +1 @@ +- Fix matching a bool payload of an untagged variant beside a bool literal case in a match that does not name every case. diff --git a/compiler/core/js_exp_make.ml b/compiler/core/js_exp_make.ml index 31b6a1dd78..f65284cb24 100644 --- a/compiler/core/js_exp_make.ml +++ b/compiler/core/js_exp_make.ml @@ -1059,7 +1059,21 @@ let rec simplify_and_ ~n (e1 : t) (e2 : t) : t option = {expression_desc = Typeof {expression_desc = Var ia}}, {expression_desc = Str "boolean"} ) ) when Js_op_util.same_vident ia ib -> - Some {expression_desc = Bool (not b); comment = None; source_loc = None} + (* A boolean other than [b] is [!b] *) + Some + { + expression_desc = + Bin + ( EqEqEq, + {expression_desc = Var ib; comment = None; source_loc = None}, + { + expression_desc = Bool (not b); + comment = None; + source_loc = None; + } ); + comment = None; + source_loc = None; + } | ( Bin ( EqEqEq, {expression_desc = Typeof {expression_desc = Var ia}}, diff --git a/tests/tests/src/untagged_bool_payload_test.mjs b/tests/tests/src/untagged_bool_payload_test.mjs new file mode 100644 index 0000000000..b00d9f2413 --- /dev/null +++ b/tests/tests/src/untagged_bool_payload_test.mjs @@ -0,0 +1,44 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as Mocha from "mocha"; +import * as Test_utils from "./test_utils.mjs"; + +function id(x) { + return x; +} + +function trueKind(v) { + if (v !== false) { + return "other"; + } else { + return "bool"; + } +} + +function falseKind(v) { + if (v !== true) { + return "other"; + } else { + return "bool"; + } +} + +Mocha.describe("Untagged_bool_payload_test", () => { + Mocha.test("beside @as(true)", () => { + Test_utils.eq("File \"untagged_bool_payload_test.res\", line 26, characters 7-14", trueKind(id(false)), "bool"); + Test_utils.eq("File \"untagged_bool_payload_test.res\", line 27, characters 7-14", trueKind(id(true)), "other"); + Test_utils.eq("File \"untagged_bool_payload_test.res\", line 28, characters 7-14", trueKind(id(1)), "other"); + }); + Mocha.test("beside @as(false)", () => { + Test_utils.eq("File \"untagged_bool_payload_test.res\", line 32, characters 7-14", falseKind(id(true)), "bool"); + Test_utils.eq("File \"untagged_bool_payload_test.res\", line 33, characters 7-14", falseKind(id(false)), "other"); + Test_utils.eq("File \"untagged_bool_payload_test.res\", line 34, characters 7-14", falseKind(id(1)), "other"); + }); +}); + +export { + id, + trueKind, + falseKind, +} +/* Not a pure module */ diff --git a/tests/tests/src/untagged_bool_payload_test.res b/tests/tests/src/untagged_bool_payload_test.res new file mode 100644 index 0000000000..88e2ac7064 --- /dev/null +++ b/tests/tests/src/untagged_bool_payload_test.res @@ -0,0 +1,36 @@ +open Mocha +open Test_utils + +// A bool payload receives the booleans that are not literal cases, also in a +// match that does not name every case (#9035) + +@unboxed type withTrue = | @as(true) LitTrue | TrueBool(bool) | TrueInt(int) +@unboxed type withFalse = | @as(false) LitFalse | FalseBool(bool) | FalseInt(int) + +@inline(never) let id = x => x + +let trueKind = (v: withTrue) => + switch v { + | TrueBool(_) => "bool" + | _ => "other" + } + +let falseKind = (v: withFalse) => + switch v { + | FalseBool(_) => "bool" + | _ => "other" + } + +describe(__MODULE__, () => { + test("beside @as(true)", () => { + eq(__LOC__, trueKind(id(TrueBool(false))), "bool") + eq(__LOC__, trueKind(id(LitTrue)), "other") + eq(__LOC__, trueKind(id(TrueInt(1))), "other") + }) + + test("beside @as(false)", () => { + eq(__LOC__, falseKind(id(FalseBool(true))), "bool") + eq(__LOC__, falseKind(id(LitFalse)), "other") + eq(__LOC__, falseKind(id(FalseInt(1))), "other") + }) +})