Skip to content

Harden the Parsetree0 PPX bridge - #8561

Open
cristianoc wants to merge 2 commits into
codex/function-arity-inclusionfrom
codex/harden-parsetree0-bridge
Open

Harden the Parsetree0 PPX bridge#8561
cristianoc wants to merge 2 commits into
codex/function-arity-inclusionfrom
codex/harden-parsetree0-bridge

Conversation

@cristianoc

Copy link
Copy Markdown
Collaborator

Summary

  • preserve async, await, arrow-type attribute ownership, and JSX container shape when converting through the frozen Parsetree0 PPX representation
  • desugar PPX-emitted OCaml-style function expressions instead of reaching assert false
  • give marshaled current-parsetree streams their own magic numbers, keeping Caml1999M022 and Caml1999N022 exclusive to the frozen external-PPX wire format
  • add focused syntax round-trip coverage and a unit test for the parser-dead Pexp_function input

Why

The current AST and frozen Parsetree0 no longer have identical structure, but parts of the bridge still treated them as if they did. In particular, a single v0 attribute list sometimes represented attributes from two current-AST nodes. This leaked the internal res.async marker, dropped or relocated await and arrow attributes, and could make the formatter recurse indefinitely. JSX container reconstruction also omitted its closing tag, while a v0 Pexp_function emitted by a PPX crashed during conversion.

The bridge now makes those boundaries explicit and keeps the frozen PPX protocol distinct from streams that marshal the evolving current parsetree.

Stack

This PR is stacked on #8559. Review the single commit introduced by this branch; the base PR contains the prerequisite function-arity changes.

Validation

  • make test
  • syntax AST-conversion corpus includes functions, arrow types, async/await, attributes, partial application, and external arity edge cases
  • existing real external-PPX compilation tests remain green

The v0 bridge (ast_mapper_to0 / ast_mapper_from0) had several fidelity
bugs that surfaced whenever code passed through an external PPX:

- the internal res.async marker leaked back into the program as a real
  attribute after decoding;
- attributes on an arrow-type node were merged into the argument's
  attribute list on the way back, which crashed the formatter with a
  stack overflow; the two lists are now kept separable with an internal
  _res.arrow_node_attrs marker, and the arrow_type viewer additionally
  always consumes the head argument so it can never return its input as
  the "return type";
- the await node's own attributes were dropped entirely (losing e.g.
  @outer in "@outer await (@inner e)" and res.braces on async bodies);
  res.await now serves as the boundary between await-node attributes
  and inner-expression attributes;
- JSX container elements were rebuilt without a closing tag, printing
  unclosed elements; a closing tag matching the opening tag is now
  synthesized;
- PPX-emitted OCaml-style `function | p -> e` hit assert false; it is
  now desugared to `fun x -> match x with ...` like the OCaml parser
  would.

Marshaled current-parsetree streams (-as-pp, res_parser -print binary,
Ast_mapper.apply_lazy) now carry their own magic numbers
(ResImpl01300/ResIntf01300); the Caml1999M022/N022 pair is reserved for
the frozen Parsetree0 wire format that external PPXes rely on.

Round-trip sweep over all 350 syntax test files: 37 diverging files
before, 21 after, no regressions; every arrows/functions/async/await
file now round-trips byte-identically. New ast-mapping corpus file
FunctionsAndArrows.res pins the constructs, and a unit test covers the
function-cases desugaring.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
@cristianoc
cristianoc force-pushed the codex/harden-parsetree0-bridge branch from 74abf0e to efc0cc5 Compare August 18, 2026 12:13
@cristianoc cristianoc closed this Aug 18, 2026
@cristianoc cristianoc reopened this Aug 18, 2026
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
@codecov

codecov Bot commented Aug 18, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 77.77778% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 75.59%. Comparing base (1e014c4) to head (9043bbb).

Files with missing lines Patch % Lines
compiler/syntax/src/res_driver_binary.ml 0.00% 4 Missing ⚠️
compiler/ml/ast_mapper.ml 0.00% 2 Missing ⚠️
compiler/syntax/src/res_parsetree_viewer.ml 0.00% 2 Missing ⚠️
compiler/ml/ast_mapper_from0.ml 95.23% 1 Missing ⚠️
tests/ounit_tests/ounit_ast_mapper0_tests.ml 88.88% 1 Missing ⚠️
Additional details and impacted files
@@                        Coverage Diff                         @@
##           codex/function-arity-inclusion    #8561      +/-   ##
==================================================================
+ Coverage                           75.54%   75.59%   +0.04%     
==================================================================
  Files                                 476      476              
  Lines                               62732    62759      +27     
==================================================================
+ Hits                                47393    47443      +50     
+ Misses                              15339    15316      -23     
Files with missing lines Coverage Δ
compiler/core/js_implementation.ml 84.40% <ø> (ø)
compiler/ml/ast_mapper_to0.ml 56.34% <100.00%> (+3.01%) ⬆️
compiler/ml/ast_mapper_from0.ml 57.55% <95.23%> (+3.55%) ⬆️
tests/ounit_tests/ounit_ast_mapper0_tests.ml 86.84% <88.88%> (+0.63%) ⬆️
compiler/ml/ast_mapper.ml 75.11% <0.00%> (ø)
compiler/syntax/src/res_parsetree_viewer.ml 90.61% <0.00%> (-0.49%) ⬇️
compiler/syntax/src/res_driver_binary.ml 0.00% <0.00%> (ø)

... 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 Aug 18, 2026

Copy link
Copy Markdown

Open in StackBlitz

rescript

npm i https://pkg.pr.new/rescript@8561

@rescript/darwin-arm64

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

@rescript/darwin-x64

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

@rescript/linux-arm64

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

@rescript/linux-x64

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

@rescript/runtime

npm i https://pkg.pr.new/@rescript/runtime@8561

@rescript/win32-x64

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

commit: 9043bbb

@cristianoc
cristianoc marked this pull request as ready for review August 18, 2026 13:01
@cristianoc
cristianoc requested a review from cknitt August 18, 2026 13:02
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