Semantic Diff

#9113 Keep both checks in x !== true && x !== false

1 commit

85f31fbb15ef96bd168d6e99055ad4808810d6e0..pr-9113

f61e918d4 · cknitt + Claude · Oct 28, 2026, 15:27 UTC

Keep both boolean checks in x !== true && x !== false

Why

The JS simplifier rewrote x !== true && x !== false to false (and x === true || x === false to true) as if x were a boolean. In an untagged variant x can be any payload, so matches with both boolean literal cases, or a bool payload beside one, lost their other checks (#9098). The boolean-only rule is removed; the general constant rules below it still fold every case that holds for any x.

modifiedJS untagged match with both boolean literals

@unboxed type t = D(Date.t) | @as(true) Lt | @as(false) Lf | R(RegExp.t)let g = (v: t) => switch v { | D(_) => 2 | _ => 4 }let h = (v: t) => switch v { | Lt | Lf => 1 | _ => 3 }
js
Before
After
function g(v) {function g(v) { return 4; if (v === true || v === false || !(v instanceof Date)) { return 4; } else { return 2; }}} function h(v) {function h(v) { return 1; if (v === true || v === false) { return 1; } else { return 3; }}}

modifiedJS bool payload beside a boolean literal

@unboxed type t = Bo(bool) | S(string) | @as(true) Ltlet f = (v: t) => switch v { | Bo(false) => 2 | _ => 6 }
js
Before
After
if (v === true) {if (v !== false) {