Repository navigation
Fold untagged matches by evaluating the dispatch plan - #9046
Conversation
Changelog💅 Polish
Semantic Diff1 commit · Full page Fold untagged matches by evaluating the dispatch plan3cf4066 · cknitt + Claude · Oct 25, 2026, 20:30 UTC
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"; |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## dispatch-plan #9046 +/- ##
=================================================
+ Coverage 81.36% 81.38% +0.02%
=================================================
Files 458 458
Lines 64366 64452 +86
=================================================
+ Hits 52369 52457 +88
+ Misses 11997 11995 -2
🚀 New features to boost your workflow:
|
rescript
@rescript/belt
@rescript/darwin-arm64
@rescript/linux-arm64
@rescript/linux-x64
@rescript/runtime
@rescript/win32-x64
commit: |
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex Review: Didn't find any major issues. What shall we delve into next? Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
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):
Example:
@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";
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMkrYaktctdKc4M41WF36t
Signed-off-by: Christoph Knittel <ck@cca.io>
7fe417c to
3cf4066
Compare
|
@codex review |
|
Codex Review: Didn't find any major issues. Nice work! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Stacked on #9045.
Constant folding decided which arm an untagged constant takes with its own copy of the dispatch rules (
untagged_action,value_has_block_type). So it could disagree with the generated code, and it left values outside every case unfolded.Untagged_dispatch.selectnow evaluates a plan on the JavaScript value of a constant, with JavaScript's semantics for each test, including the short circuits of&&and||.Lambda.switchfolds with it, andLambda.untagged_planbuilds the one plan that both folding andLam_compileuse. Folding therefore agrees with the generated code by construction.Folding now also covers constants outside every case. For example, a
truecast toI(int) | S(string)folds to the unchecked last arm, as rule 10 says.New tests:
ounit_untagged_dispatch_tests.mlbuilds 3000 random variants and matches (literals, primitive kinds, classes with a subclass, arrays, objects, unknown payloads, random arm subsets with shared bodies). It checks thatselectgives, for one value of every case, the arm rules 7 to 9 give.untagged_variants_spec_test.reschecks rule 10 both folded and at run time.🤖 Generated with Claude Code
https://claude.ai/code/session_01CMkrYaktctdKc4M41WF36t