Skip to content

Remove parser modes by encoding constructor arity explicitly - #8610

Open
cknitt wants to merge 13 commits into
rescript-lang:masterfrom
cknitt:codex/remove-parser-mode
Open

Remove parser modes by encoding constructor arity explicitly#8610
cknitt wants to merge 13 commits into
rescript-lang:masterfrom
cknitt:codex/remove-parser-mode

Conversation

@cknitt

@cknitt cknitt commented Sep 3, 2026

Copy link
Copy Markdown
Member

Motivation

The ReScript parser previously supported two modes:

type mode =
  | ParseForTypeChecker
  | Default

These modes allowed the parser to produce different trees depending on whether its output was intended for the type checker or the printer.

In particular, the type-checker representation collapsed the distinction between multiple constructor arguments and a tuple passed as a single constructor argument. The printer needed a different, source-preserving representation so it could retain the extra parentheses.

The parser mode was also used for differences in string-literal representation. #8606 normalized string literals across the compiler and was the first step toward removing the mode entirely. Constructor arity was the main remaining reason for it.

This change

Constructor arity is now represented explicitly in the parsetree:

Pexp_construct of Longident.t loc * expression list
Ppat_construct of Longident.t loc * pattern list

The same approach is used for polymorphic variant expressions, patterns, and type payload groups.

For example:

type binary = Binary(int, int)
type unaryTuple = UnaryTuple((int, int))

Their applications have unambiguous parsetree representations:

Binary(x, y)
→ Pexp_construct("Binary", [x; y])

UnaryTuple((x, y))
→ Pexp_construct("UnaryTuple", [Pexp_tuple [x; y]])

The type checker can therefore compare the number of syntactic arguments directly with the constructor's declared arity.

This also means that a constructor with one tuple payload must use the corresponding nested parentheses:

Some((x, y))

Writing Some(x, y) now correctly reports an arity mismatch.

Alignment with subsequent compiler layers

The new representation is more closely aligned with subsequent compiler layers. Nominal constructors are already represented as argument lists in the typedtree, so the type checker no longer needs to infer their arity by inspecting tuple nodes.

Polymorphic variants continue to be normalized to their semantic single-payload representation when entering the type checker. Their source-level arity remains explicit in the parsetree for printing and tooling.

There is therefore no need to change the typedtree or later compiler representations.

Cleanup enabled by the new representation

With both source shape and constructor arity available in one parsetree, this PR removes:

  • ParseForTypeChecker and Default from the parser
  • the for_printer argument throughout parser APIs and their callers
  • the developer-only -typechecker parser flag
  • parser branches that produced different trees for printing and type checking
  • type-checker logic that inferred constructor arity by inspecting tuple nodes
  • redundant tuple unpacking in analysis and compiler traversals

It also:

  • consolidates constructor argument parsing and printing
  • centralizes AST0 constructor argument encoding and decoding
  • confines legacy ocaml.explicit_arity handling to the AST0 compatibility boundary
  • makes constructor argument naming consistently reflect that the parsetree contains a list

PPX compatibility

The frozen parsetree0 representation remains unchanged.

When converting multiple constructor arguments to AST0, the bridge encodes them as a tuple and attaches internal _res.constructor_args metadata. Conversion back uses that metadata to restore the argument list and removes the internal attribute before returning to the current parsetree.

This preserves the distinction between multiple arguments and a single tuple argument across PPX round trips without requiring changes to the frozen PPX-facing AST.

Breaking change

Code that relied on the previous ambiguity must add explicit tuple parentheses.

For example:

Some(x, y)

must become:

Some((x, y))

when the constructor has one tuple payload.

Testing

The change includes coverage for:

  • nominal constructor expressions and patterns
  • polymorphic variant expressions, patterns, and type payloads
  • unary tuple payloads versus multiple arguments
  • constructor arity mismatch diagnostics
  • AST0 and PPX round trips
  • syntax printing and round trips
  • analysis features and completion locations
  • end-to-end compilation and runtime behavior

Signed-off-by: Christoph Knittel <ck@cca.io>
Signed-off-by: Christoph Knittel <ck@cca.io>
Signed-off-by: Christoph Knittel <ck@cca.io>
Signed-off-by: Christoph Knittel <ck@cca.io>
Signed-off-by: Christoph Knittel <ck@cca.io>
Signed-off-by: Christoph Knittel <ck@cca.io>
Signed-off-by: Christoph Knittel <ck@cca.io>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 3, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-03T18:50:23.455914Z b374049 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Signed-off-by: Christoph Knittel <ck@cca.io>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ba681ec574

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

Comment thread compiler/ml/ast_mapper_from0.ml
Comment thread compiler/ml/typecore.ml
Comment thread compiler/syntax/src/res_comments_table.ml Outdated
Signed-off-by: Christoph Knittel <ck@cca.io>
Signed-off-by: Christoph Knittel <ck@cca.io>
@codecov

codecov Bot commented Sep 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.78199% with 90 lines in your changes missing coverage. Please review.
✅ Project coverage is 77.43%. Comparing base (bc382a4) to head (cbf4a97).

Files with missing lines Patch % Lines
tests/ounit_tests/ounit_ast_mapper0_tests.ml 86.71% 19 Missing ⚠️
analysis/src/dump_ast.ml 0.00% 12 Missing ⚠️
compiler/ml/printast.ml 0.00% 9 Missing ⚠️
compiler/ml/ast_mapper_from0.ml 91.17% 6 Missing ⚠️
compiler/frontend/bs_builtin_ppx.ml 55.55% 4 Missing ⚠️
compiler/ml/ast_mapper.ml 76.47% 4 Missing ⚠️
analysis/src/completion_expressions.ml 76.92% 3 Missing ⚠️
analysis/src/type_utils.ml 40.00% 3 Missing ⚠️
compiler/ml/ast_helper.ml 40.00% 3 Missing ⚠️
compiler/ml/ast_mapper_to0.ml 93.75% 3 Missing ⚠️
... and 16 more
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #8610      +/-   ##
==========================================
+ Coverage   77.32%   77.43%   +0.10%     
==========================================
  Files         467      467              
  Lines       63342    63491     +149     
==========================================
+ Hits        48982    49166     +184     
+ Misses      14360    14325      -35     
Files with missing lines Coverage Δ
analysis/src/codemod.ml 68.96% <ø> (ø)
analysis/src/commands.ml 63.82% <ø> (ø)
analysis/src/completion_patterns.ml 86.40% <100.00%> (-1.32%) ⬇️
analysis/src/diagnostics.ml 75.00% <ø> (ø)
analysis/src/hint.ml 75.00% <100.00%> (ø)
analysis/src/process_attributes.ml 83.78% <100.00%> (ø)
analysis/src/xform.ml 88.20% <100.00%> (+0.19%) ⬆️
compiler/bsc/rescript_compiler_main.ml 71.49% <ø> (ø)
compiler/common/pattern_printer.ml 87.75% <100.00%> (-0.25%) ⬇️
compiler/frontend/ast_derive_projector.ml 90.16% <100.00%> (-0.47%) ⬇️
... and 42 more

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@pkg-pr-new

pkg-pr-new Bot commented Sep 3, 2026

Copy link
Copy Markdown

Open in StackBlitz

rescript

npm i https://pkg.pr.new/rescript-lang/rescript@8610

@rescript/belt

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/belt@8610

@rescript/darwin-arm64

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/darwin-arm64@8610

@rescript/darwin-x64

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/darwin-x64@8610

@rescript/linux-arm64

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/linux-arm64@8610

@rescript/linux-x64

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/linux-x64@8610

@rescript/runtime

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/runtime@8610

@rescript/win32-x64

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/win32-x64@8610

commit: cbf4a97

Signed-off-by: Christoph Knittel <ck@cca.io>
@cknitt

cknitt commented Sep 3, 2026

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b374049de4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

Comment thread compiler/ext/config.ml
Signed-off-by: Christoph Knittel <ck@cca.io>
@cknitt
cknitt requested a review from cristianoc September 3, 2026 19:16
Signed-off-by: Christoph Knittel <ck@cca.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant