Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/untagged-bool-literal-checks.fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Fix untagged variant matches involving boolean literals that skipped the checks for the other cases.
12 changes: 0 additions & 12 deletions compiler/core/js_exp_make.ml
Original file line number Diff line number Diff line change
Expand Up @@ -910,18 +910,6 @@ let rec simplify_and_ ~n (e1 : t) (e2 : t) : t option =
| None -> None
| Some e -> simplify_and_force ~n:(n + 1) e e2)
| Some a_, Some b_ -> simplify_or_force ~n:(n + 1) a_ b_)
| ( Bin
( ((EqEqEq | NotEqEq) as op1),
{expression_desc = Var i1},
{expression_desc = Bool b1} ),
Bin
( ((EqEqEq | NotEqEq) as op2),
{expression_desc = Var i2},
{expression_desc = Bool b2} ) )
when Js_op_util.same_vident i1 i2 ->
let op_eq = op1 = op2 in
let consistent = if op_eq then b1 = b2 else b1 <> b2 in
if consistent then Some e1 else Some false_
| ( Bin
( EqEqEq,
{expression_desc = Typeof {expression_desc = Var ia}},
Expand Down
60 changes: 60 additions & 0 deletions tests/tests/src/untagged_bool_literals_test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// 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 bothKind(v) {
if (v === true || v === false || !(v instanceof Date)) {
return "other";
} else {
return "date";
}
}

function literalKind(v) {
if (v === true || v === false) {
return "literal";
} else {
return "other";
}
}

function falseKind(v) {
if (v !== false) {
return "other";
} else {
return "false";
}
}

Mocha.describe("Untagged_bool_literals_test", () => {
Mocha.test("no case names a boolean literal", () => {
Test_utils.eq("File \"untagged_bool_literals_test.res\", line 32, characters 7-14", bothKind(id(new Date())), "date");
Test_utils.eq("File \"untagged_bool_literals_test.res\", line 33, characters 7-14", bothKind(id(/a/)), "other");
Test_utils.eq("File \"untagged_bool_literals_test.res\", line 34, characters 7-14", bothKind(id(true)), "other");
Test_utils.eq("File \"untagged_bool_literals_test.res\", line 35, characters 7-14", bothKind(id(false)), "other");
});
Mocha.test("both boolean literals in one case", () => {
Test_utils.eq("File \"untagged_bool_literals_test.res\", line 39, characters 7-14", literalKind(id(true)), "literal");
Test_utils.eq("File \"untagged_bool_literals_test.res\", line 40, characters 7-14", literalKind(id(false)), "literal");
Test_utils.eq("File \"untagged_bool_literals_test.res\", line 41, characters 7-14", literalKind(id(new Date())), "other");
Test_utils.eq("File \"untagged_bool_literals_test.res\", line 42, characters 7-14", literalKind(id(/a/)), "other");
});
Mocha.test("bool payload beside @as(true)", () => {
Test_utils.eq("File \"untagged_bool_literals_test.res\", line 46, characters 7-14", falseKind(id(false)), "false");
Test_utils.eq("File \"untagged_bool_literals_test.res\", line 47, characters 7-14", falseKind(id("hello")), "other");
Test_utils.eq("File \"untagged_bool_literals_test.res\", line 48, characters 7-14", falseKind(id(true)), "other");
});
});

export {
id,
bothKind,
literalKind,
falseKind,
}
/* Not a pure module */
50 changes: 50 additions & 0 deletions tests/tests/src/untagged_bool_literals_test.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
open Mocha
open Test_utils

// Checks against both boolean literals must not assume that the value is a
// boolean: in an untagged variant it can be any of the payloads (#9098)

@unboxed type withBoth = D(Date.t) | @as(true) Lt | @as(false) Lf | R(RegExp.t)
@unboxed type withTrue = Bo(bool) | S(string) | @as(true) LitTrue

@inline(never) let id = x => x

let bothKind = (v: withBoth) =>
switch v {
| D(_) => "date"
| _ => "other"
}

let literalKind = (v: withBoth) =>
switch v {
| Lt | Lf => "literal"
| _ => "other"
}

let falseKind = (v: withTrue) =>
switch v {
| Bo(false) => "false"
| _ => "other"
}

describe(__MODULE__, () => {
test("no case names a boolean literal", () => {
eq(__LOC__, bothKind(id(D(Date.make()))), "date")
eq(__LOC__, bothKind(id(R(/a/))), "other")
eq(__LOC__, bothKind(id(Lt)), "other")
eq(__LOC__, bothKind(id(Lf)), "other")
})

test("both boolean literals in one case", () => {
eq(__LOC__, literalKind(id(Lt)), "literal")
eq(__LOC__, literalKind(id(Lf)), "literal")
eq(__LOC__, literalKind(id(D(Date.make()))), "other")
eq(__LOC__, literalKind(id(R(/a/))), "other")
})

test("bool payload beside @as(true)", () => {
eq(__LOC__, falseKind(id(Bo(false))), "false")
eq(__LOC__, falseKind(id(S("hello"))), "other")
eq(__LOC__, falseKind(id(LitTrue)), "other")
})
})
Loading