Fold untagged matches by evaluating the dispatch plan
Why
Constant folding decided which arm an untagged constant takes with its own copy of the dispatch rules, so it could disagree with the generated code, and it left values outside every case unfolded.
Untagged_dispatch.select evaluates a plan on the JavaScript value of a constant, with JavaScript's semantics for each test. Lambda.switch folds with it, and Lambda.untagged_plan builds the plan for both folding and Lam_compile. A property test compares the plans of random variants and matches with rules 7 to 9.
Generated code changed (a constant outside every case):
@unboxed type t = I(int) | S(string)let name = (x: t) => switch x { | I(_) => "int" | S(_) => "string" }let r = name(raw(true))
Before (JS):
let r = name(true);After (JS):
let r = "string";