Decide the untagged dispatch's literal cases by routing them
Why
A literal without an arm got a case whenever the variant had a class case, even where no class check runs on it, and arms of different kinds with one body kept the checks telling them apart. The literal arm left to a complete payload dispatch with one body assumed that dispatch runs no check, which held only because matching shares such bodies.
A literal without an arm skips the literal switch when the payload dispatch, evaluated on it with select, takes it to the default without a class check. The plan is simplified: a test whose branches run the same, and a case that runs what its default runs, are left out, and a literal with the body of a payload dispatch that runs one body unchecked gets no case. The property test also checks that no literal or primitive reaches a class check. Variant_runtime.literal_passes is gone.
Generated code changed (a literal without an arm beside a class case):
@unboxed type t = | @as("a") A | S(string) | N(float) | D(Date.t) | O({x: int})let f = (x: t) => switch x { | D(_) => 1 | O(_) => 2 | _ => 3 }
Before (JS):
if (x === "a") { return 3;}switch (typeof x) { case "string" : case "number" : return 3; default: ...}
After (JS):
switch (typeof x) { case "string" : case "number" : return 3; default: ...}
Generated code changed (arms of different kinds with one body):
@unboxed type t = | @as(null) NoPoint | Point({x: int}) | Name(string)switch x {| NoPoint => Console.log("null")| Point(_) => Console.log("payload")| Name(_) => Console.log("payload")}
Before (JS):
if (x === null) { console.log("null"); return;}if (typeof x === "string") { console.log("payload"); return;}console.log("payload");
After (JS):
if (x === null) { console.log("null"); return;}console.log("payload");