Skip to content

Make the typed layers n-ary: Tarrow params and Texp_function params - #8568

Merged
cristianoc merged 1 commit into
masterfrom
codex/nary-typed-layers
Aug 20, 2026
Merged

Make the typed layers n-ary: Tarrow params and Texp_function params#8568
cristianoc merged 1 commit into
masterfrom
codex/nary-typed-layers

Conversation

@cristianoc

@cristianoc cristianoc commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Part of the n-ary functions series tracked in #8557 (item 5; stacked on #8566 via base branch only — each PR merges independently).

What

Types.Tarrow carries a parameter list (Tarrow of arg list * type_expr); Texp_function carries typed parameters {fp_lbl; fp_param; fp_pat; fp_partial} and a body; Ttyp_arrow and Otyp_arrow follow. The arity annotation and its int option phantom state are gone from the compiler.

Type relations compare parameters pairwise; a length mismatch is structural incompatibility (which also makes mcomp's arrow verdict sound: arrows of different lengths can never unify). filter_arrow becomes filter_arrow_n. type_function types all parameters against one arrow, checking expected labels up front to preserve the dedicated Abstract_wrong_label diagnostics; optional-parameter defaults desugar to uniquified *opt_<label>* bindings stacked at the head of the body. type_application is a single parameters-to-arguments matching loop preserving the legacy commutation, optional auto-fill, eta-expansion placeholder, and error-selection behavior.

translcore's push_defaults is deleted (defaults now sit in the body by construction) and transl_function walks the parameter list, keeping the active-pattern split. Downstream, the gather-until-arity walkers in gentype and the outcome printer, reanalyze's two arity-corrective helpers, and typedecl's structural arity fallback are all deleted.

The cmi and cmt magic numbers are bumped to Caml1999I023/Caml1999T023 — clean builds required; cmt-consuming tools rebuilt in lockstep in-tree.

Generated JavaScript

Byte-identical across the test suite except:

  • A bug fix: defaults of optional parameters in curried functions are now computed when their own parameter group is applied ((~x=d, y) => (~z=d, w) => ... no longer defers x's default to the inner application); pinned by the uncurried_default.args snapshot.
  • Optional-parameter internals are named *opt_<label>* instead of *opt* in the one unprettified case (mario_game).

Tooling

Termination analysis restored (pre-existing bug, fixed here since this PR must touch the code anyway): collecting a binding's callees had been gated since 2024 (c37be1e8a) on arity-less function nodes, which uncurried code never produces — effectively disabling the mechanism that adds helpers calling @progress functions to the function table. The n-ary node has no arity to gate on; collection now runs for every function binding, discharging 3 false positives in the termination corpus (15 → 12 reported issues).

Method arity mismatches report unlabelled argument counts precisely, and missing-argument lists print in source order. Reanalyze no longer emits spurious empty optional-argument references; genType recovers real parameter names after defaulted parameters.

🤖 Generated with Claude Code

@cristianoc
cristianoc force-pushed the codex/nary-typed-layers branch from 5cdc8bc to f18adb7 Compare August 20, 2026 07:08
@cristianoc
cristianoc changed the base branch from codex/nary-parsetree to master August 20, 2026 07:10

@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: 5cdc8bc959

ℹ️ 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 CHANGELOG.md Outdated
Comment thread compiler/ml/typecore.ml
@cristianoc
cristianoc force-pushed the codex/nary-typed-layers branch from f18adb7 to 4c9e95f Compare August 20, 2026 07:24

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Declared error-message improvement: the count is now explicitly about unlabelled arguments ("takes 2 unlabelled arguments, but is called with just 1") instead of a raw total that miscounted labeled/mixed calls.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Declared fix: the missing-arguments list now prints in source order (~b, ~c, ~d); the old order was an artifact of walking the curried chain inside-out.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Declared genType fix: _4d — real parameter names are recovered after a defaulted parameter (the old gather-until-arity walk lost names past the default).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Same mechanism as LabeledFun.gen.tsx: the positional placeholder _2 is replaced by the parameter's actual (compiler-introduced) name for the unit parameter — faithful name recovery, if less pretty.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The declared *opt_<label>* naming in the one unprettified case: $staropt$star$1$staropt_dir$star. Pure renaming of optional-parameter internals; no structural change. This and uncurried_default.args.mjs are the only two .mjs files that change in this PR — everything else is byte-identical, as the commit message claims.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This is the headline bug fix, visible in the JS: x's default is now computed in the outer function's body before the inner closure is returned, instead of being deferred to the inner application. The fixture gained a comment pinning exactly this, so any regression shows up as a snapshot diff. The xOpt/zOpt names are the same renaming as mario_game.mjs, prettified.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Exactly six removed lines, all DeadOptionalArgs.addReferences … argNames: argNamesMaybe: with both lists empty — the declared "spurious empty optional-argument references" reanalyze no longer emits. No dead/live verdicts change; nothing is added.

@codecov

codecov Bot commented Aug 20, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 79.16667% with 105 lines in your changes missing coverage. Please review.
✅ Project coverage is 75.82%. Comparing base (124bc4b) to head (d980cec).

Files with missing lines Patch % Lines
compiler/ml/typecore.ml 84.91% 35 Missing ⚠️
compiler/ml/ctype.ml 63.26% 18 Missing ⚠️
compiler/ml/printtyped.ml 0.00% 12 Missing ⚠️
analysis/src/type_utils.ml 69.23% 8 Missing ⚠️
compiler/ml/oprint.ml 0.00% 8 Missing ⚠️
compiler/ml/typedtree_iter.ml 0.00% 5 Missing ⚠️
compiler/gentype/translate_core_type.ml 80.00% 4 Missing ⚠️
compiler/gentype/translate_structure.ml 75.00% 4 Missing ⚠️
compiler/ml/printtyp.ml 73.33% 4 Missing ⚠️
compiler/ml/record_type_spread.ml 0.00% 4 Missing ⚠️
... and 2 more
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #8568      +/-   ##
==========================================
- Coverage   75.84%   75.82%   -0.02%     
==========================================
  Files         475      475              
  Lines       62835    62904      +69     
==========================================
+ Hits        47655    47699      +44     
- Misses      15180    15205      +25     
Files with missing lines Coverage Δ
analysis/reanalyze/src/arnold.ml 84.91% <100.00%> (+1.60%) ⬆️
analysis/reanalyze/src/dead_optional_args.ml 92.00% <100.00%> (+5.33%) ⬆️
analysis/reanalyze/src/dead_value.ml 85.77% <ø> (+0.69%) ⬆️
analysis/src/completion_back_end.ml 81.74% <100.00%> (+0.01%) ⬆️
analysis/src/completion_jsx.ml 75.00% <100.00%> (ø)
analysis/src/create_interface.ml 86.87% <100.00%> (-0.09%) ⬇️
analysis/src/process_cmt.ml 82.00% <100.00%> (+0.18%) ⬆️
analysis/src/shared.ml 68.18% <100.00%> (+0.73%) ⬆️
compiler/core/lam_convert.ml 79.43% <100.00%> (+0.29%) ⬆️
compiler/gentype/translate_type_expr_from_types.ml 88.76% <100.00%> (-0.33%) ⬇️
... and 24 more

... and 1 file 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 20, 2026

Copy link
Copy Markdown

Open in StackBlitz

rescript

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

@rescript/belt

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

@rescript/darwin-arm64

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

@rescript/darwin-x64

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

@rescript/linux-arm64

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

@rescript/linux-x64

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

@rescript/runtime

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

@rescript/win32-x64

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

commit: d980cec

@cristianoc
cristianoc force-pushed the codex/nary-typed-layers branch from 4c9e95f to eed5fe7 Compare August 20, 2026 07:49
@github-actions

Copy link
Copy Markdown

@cristianoc
cristianoc force-pushed the codex/nary-typed-layers branch from eed5fe7 to 63409eb Compare August 20, 2026 08:15
@@ -544,15 +544,12 @@ module Find_functions_called = struct
{super with Tast_mapper.expr}

let find_callees (expression : Typedtree.expression) =

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we not remove this function?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done in 0196f60 — removed Find_functions_called entirely along with the full dead cascade it anchored: the never-firing progress-function arm in Extend_function_table.traverse_expr (its guard intersected an always-empty set), the now-unused ~progress_functions/~value_bindings_table parameters, and the always-empty callees field of value_bindings_table (triple → pair). Net −60 lines. The reanalyze suite, including the termination-analysis corpus, passes with zero expectation changes — confirming none of it was reachable.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Update — your question turned out to be exactly the right one, with the opposite resolution. Digging into the history: this was never intentionally dead code. The collection guard was tightened to Texp_function {arity = None} in c37be1e (Dec 2024, "Remove difference on termination analysis tests") — a shape uncurried code never produces — which silently disabled the progress-function extension and introduced 3 false positives that the termination corpus has been carrying since (functions whose progress flows through un-annotated helpers like parseInt). The stub here was a faithful translation of that disabled state. Now restored in d980cec instead of deleted: the n-ary node has no arity to gate on, so callees are collected for every function binding — the corpus's false positives are discharged (15 → 12 issues) and parseInt & co. are back in the function table with their +Parser.next progress summaries. Declared in the PR description and CHANGELOG.

@cristianoc
cristianoc force-pushed the codex/nary-typed-layers branch from 63409eb to 0196f60 Compare August 20, 2026 14:22
Types.Tarrow carries a parameter list (Tarrow of arg list * type_expr);
Texp_function carries typed parameters {fp_lbl; fp_param; fp_pat;
fp_partial} and a body; Ttyp_arrow and Otyp_arrow follow. The arity
annotation and its int-option phantom state are gone from the compiler.

Type relations compare parameters pairwise; a length mismatch is
structural incompatibility (which also makes mcomp's arrow verdict
sound: arrows of different lengths can never unify). filter_arrow
becomes filter_arrow_n. type_function types all parameters against one
arrow, checking expected labels up front to preserve the dedicated
Abstract_wrong_label diagnostics; optional-parameter defaults desugar
to uniquified *opt_<label>* bindings stacked at the head of the body.
type_application is a single parameters-to-arguments matching loop
preserving the legacy commutation, optional auto-fill, eta-expansion
placeholder, and error-selection behavior.

translcore's push_defaults is deleted (defaults now sit in the body by
construction) and transl_function walks the parameter list, keeping the
active-pattern split. Downstream, the gather-until-arity walkers in
gentype and the outcome printer, reanalyze's two arity-corrective
helpers, and typedecl's structural arity fallback are all deleted.

The cmi and cmt magic numbers are bumped to Caml1999I023/Caml1999T023.

Generated JavaScript is byte-identical across the test suite except:
- a bug fix: defaults of optional parameters in curried functions are
  now computed when their own parameter group is applied ((~x=d, y) =>
  (~z=d, w) => ... no longer defers x's default to the inner
  application); pinned by the uncurried_default.args snapshot;
- optional-parameter internals are named *opt_<label>* instead of
  *opt* in the one unprettified case (mario_game).

Error-message improvements: method arity mismatches report unlabelled
argument counts precisely, and missing-argument lists print in source
order. Reanalyze no longer emits spurious empty optional-argument
references; genType recovers real parameter names after defaulted
parameters.

Restore the termination analysis' progress-function extension: collecting
a binding's callees had been gated (since c37be1e) on arity-less
function nodes, which uncurried code never produces and which no longer
exist at all - effectively disabling the mechanism that adds helpers
calling @progress functions to the function table, and producing false
positives for functions whose progress flows through such helpers. The
n-ary node has no arity to gate on; collect for every function binding.

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/nary-typed-layers branch from 0196f60 to d980cec Compare August 20, 2026 14:37
@cristianoc
cristianoc merged commit d0440c3 into master Aug 20, 2026
29 checks passed
@cristianoc
cristianoc deleted the codex/nary-typed-layers branch August 20, 2026 15:12
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.

2 participants