You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Represent optional parameters with defaults structurally instead of by name sniffing
The desugaring of an optional parameter with a default (~x=3) binds the
option-carrying parameter to a synthetic *opt_<label>* variable, and that
fact was recovered downstream by pattern-matching on the variable name in
four places across three compiler layers: typecore's is_fake_let (matching
the pre-n-ary name "*opt*" exactly, so it had silently rotted into dead
code), matching's *sth* let-elimination peephole, lam_convert's
rename_optional_parameters (which also had to re-recognize the whole
compiled body shape to rename the parameter to xOpt for JS output), and
gentype's *opt prefix check.
Represent the fact structurally instead:
- Typedtree.function_param gains an fp_has_default field.
- type_function replaces the carrier ident right after typing: fp_param
becomes a fresh ident named <label>Opt, substituted at the carrier's
only two occurrences (the parameter pattern's binder and the synthetic
match's scrutinee), both nodes the desugaring itself generated. The
unspellable name still exists during typing, where names must be
impossible to capture or shadow, but dies before the typedtree leaves
the function. The Lambda IR is born with the final parameter name and
no residual binding.
- lam_convert's rename_optional_parameters and is_opt_param_name are
deleted; the Lfunction case is a plain conversion.
- matching's *sth* peephole is generalized to eliminate any alias binding
of the form let v = arg in v, with no name test.
- gentype uses fp_has_default instead of sniffing the ident name.
- is_fake_let now keys on the #optional_arg_default attribute the
desugaring plants, restoring its intended behavior: an unused defaulted
parameter warns as an unused parameter (27), not an unused let (26).
- The write-only #default attribute is removed, along with its dead
parsetree consumer.
Visible improvements: parameter names in emitted JS now consistently
derive from the label, including cases the old shape-match silently
missed and leaked mangled names for (mario_game.mjs's make$2 had
$staropt_id$star as a parameter; it is now idOpt).
Signed-Off-By: Cristiano Calcagno <ccrisccris@gmail.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PCtQiaDijUqA2fujQXvKUw
Copy file name to clipboardExpand all lines: CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -52,6 +52,7 @@
52
52
#### :house: Internal
53
53
54
54
- Give nominal variants one canonical runtime layout: compute their JavaScript representation once after typing each declaration, replace positional constructor tags with semantic runtime descriptors, and make construction, matching, coercion, printing, diagnostics, and GenType consume the stored representation instead of reinterpreting annotations. Pattern matching keeps occurrence-specific plans local without adding another Lambda or Lam expression form. https://github.com/rescript-lang/rescript/pull/8579
55
+
- Represent optional parameters with defaults structurally instead of recovering them downstream by pattern-matching on the synthetic `*opt_<label>*`/`*sth*` variable names: `Typedtree.function_param` gains an `fp_has_default` field, the type checker gives the compiled parameter its final `<label>Opt` ident before the typedtree leaves the function, and the name-sniffing consumers (`lam_convert`'s shape-matching rename pass, `matching`'s `*sth*` peephole, gentype's prefix check, and typecore's dead `is_fake_let`/`#default` vestiges) are deleted or generalized. Parameter names in emitted JS now consistently derive from the label, including cases the old shape-match silently missed and leaked mangled names for (`$staropt_id$star` → `idOpt`), and an unused defaulted parameter warns as an unused parameter (27) rather than an unused let binding (26). The CMT magic number is bumped to `Caml1999T025`. https://github.com/rescript-lang/rescript/pull/8580
55
56
- Sync the platform npm package's compiler binaries (`packages/@rescript/<platform>/bin`) via dune promotion on every `dune build`, instead of Makefile/CI copy steps that only ran when make did: a plain `dune build` can no longer leave `cli/*.js` and the test harnesses running a stale compiler. https://github.com/rescript-lang/rescript/pull/8560
56
57
- Remove unused compiler IR definitions, modules, helpers, error variants, and Typedtree fields. https://github.com/rescript-lang/rescript/pull/8551https://github.com/rescript-lang/rescript/pull/8555
57
58
- Make locally abstract value constraints (`let f: type a. t = value`) structural in the parsetree, remove the obsolete `Pexp_newtype` and `Texp_newtype` wrapper metadata, and keep the old encoding confined to the frozen external-PPX bridge. The CMT magic number is bumped to `Caml1999T024`. https://github.com/rescript-lang/rescript/pull/8575
0 commit comments