Keep cases handled by a default arm out of the arms a switch names
Why
A switch on an untagged variant with a _ arm let the cases it does not name reach the arms it names: a Date matched the object arm, since only arrays were guarded, and an @as("lit") literal matched the string arm, since the literal test was skipped when the switch names no literal (#8995).
The switch (typeof x) is preceded by a guard sending every instance case without an arm to the default, as it already did for arrays. The literal test is skipped only when no literal of the variant would pass the check of a payload arm. Rules 7 and 9 of the spec state both.
modifiedJS an instance handled by the default
@unboxed type t = D(Date.t) | R(RegExp.t) | O({x: int}) | S(string) | I(int) | F(int => int)let f = v => switch v { | O(_) => "O" | S(_) => "S" | _ => "other" }
js
Before
After
if (v instanceof RegExp || v instanceof Date) { return "other";}switch (typeof v) {switch (typeof v) { case "object" : case "object" : return "O"; return "O";
modifiedJS a literal handled by the default
@unboxed type t = | @as("lit") Lit | S(string) | I(int) | B(bool) | O({x: int}) | F(int => int)let f = v => switch v { | S(_) => "S" | O(_) => "O" | _ => "other" }
js
Before
After
if (v === "lit") { return "other";}switch (typeof v) {switch (typeof v) { case "string" : case "string" : return "S"; return "S";