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
Eliminate Pjs_fn_make, Pjs_fn_make_unit, and unsafe_adjust_to_arity
With structural arity, "function of arity n" is a construction
invariant rather than a goal state: translcore builds every Lfunction
with exactly the parameters its type declares. The arity-enforcement
layer therefore disappears:
- Function literals are emitted directly; the Pjs_fn_make wrapper that
every function passed through was resolved as a no-op by
lam_pass_alpha_conversion, but only *after* deep_flatten,
simplify_exits and simplify_alias had run with the function hidden
inside an Lprim, acting as an accidental optimization barrier.
- Pjs_fn_make_unit was a one-bit metadata channel: its entire effect
was setting one_unit_arg so js_exp_make drops the unit parameter.
translcore now sets the attribute directly, gated on the parameter
pattern binding no identifiers (a () or _ pattern) - a more
principled test than the alpha pass's check that the parameter was
named "param".
- The active-pattern currying split in transl_function is deleted. It
preserved pattern-effect timing across curried application steps,
which no longer exist: total applications supply all arguments at
once and explicit partial application eta-defers the entire call.
The old output proves the point - the split's closures were
immediately applied by the arity adapter, so only the allocations
are gone (see mutable_uncurry_test).
- The I<N> unboxed-record producer (the @this method-callback
encoding) is removed: the general Record_unboxed translation already
returns the single field unboxed, and the wrapped value is a literal
of matching arity.
With no producers left, both primitive constructors and every consumer
arm are deleted, including the 230-line unsafe_adjust_to_arity (its
only callers were the two Pjs_fn_make resolution sites).
On recursive modules: removing the wrapper lets the static
recursive-module compilation path see module members that are plain
functions, replacing the Primitive_module.init/update bootstrap with
hoisted function declarations. This is safe because the static path's
own applicability check now sees the functions it was designed to
check - the wrapper was hiding them, pessimizing compilation - and the
bootstrap demonstrably remains for members that are not plain
functions (rec_module_test keeps its lazy/value cases dynamic).
Verified: stdlib byte-identical; full test suite green; JS output
changes limited to removed adapter closures, removed no-op module
bootstraps, better name preservation, and constant propagation.
Keep beta-residue let chains (immutable blocks and aliases feeding a
final apply) local in Lam_pass_deep_flatten instead of hoisting them
into the enclosing group: with the wrapper gone, beta reduction happens
before flatten2, and hoisting the argument bindings to toplevel put
them beyond Lam_pass_lets_dce's reach (a_recursive_type kept a named
intermediate that master inlined; the snapshot pins the restored form).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
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
@@ -48,6 +48,7 @@
48
48
49
49
- 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
50
50
- 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
51
+
- Eliminate the `Pjs_fn_make`/`Pjs_fn_make_unit` arity-adjustment primitives and the `unsafe_adjust_to_arity` machinery: with structural arity, functions are constructed at their final arity, so the enforcement layer (and the active-pattern currying split it compensated for) is deleted. Generated code improves: no adapter closures for patterns on mutable fields, better constant propagation and name preservation, and recursive modules whose members are plain functions compile statically without the runtime bootstrap. https://github.com/rescript-lang/rescript/pull/8570
51
52
- Cleanups enabled by structural arity: remove the unreachable `Too_many_arguments` error and the `?in_function` threading through the type checker that existed only to decorate it; remove the dead `function$`-vs-arrow unification bridge, `Ctype.arity`, and the unused parsetree arity helpers; deduplicate the analysis arrow-flattening helpers. https://github.com/rescript-lang/rescript/pull/8569
52
53
53
54
- Make the typed layers n-ary as well: `Types.Tarrow` carries a parameter list, `Texp_function` carries typed parameters (label, ident, pattern, per-parameter exhaustiveness) and a body, and `Ttyp_arrow`/`Otyp_arrow` follow. The `arity` annotation and its `int option` phantom state are gone from the compiler entirely; `push_defaults` in translcore and the hand-rolled gather-until-arity walks in gentype, reanalyze, and the outcome printer are deleted. The cmi and cmt magic numbers are bumped (`Caml1999I023`/`Caml1999T023`). Generated JavaScript is byte-identical across the test suite (optional-parameter internals are named `*opt_<label>*` instead of `*opt*`, visible only in the rare unprettified case); reanalyze no longer emits spurious empty optional-argument references, and genType recovers real parameter names after defaulted parameters. https://github.com/rescript-lang/rescript/pull/8568
Copy file name to clipboardExpand all lines: compiler/core/design.md
-15Lines changed: 0 additions & 15 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -173,20 +173,6 @@ We can simply do inlining, it may have side efffect in `b0`, `b1`, our optimizer
173
173
174
174
Maybe in the future, we should lift the restriction about `variadic` (delegate to `slow` mode when we can not resolve it statically, my personal expereince is that people will complain about why it fails to compile more than why it is slow in some corner cases)
175
175
176
-
Note this also interacts with `[@uncurry]`
177
-
178
-
for example
179
-
180
-
```ocaml
181
-
external filter : 'a array -> ('a -> bool [@uncurry]) -> 'a array = "filter"
182
-
[@@send]
183
-
184
-
let f xs =
185
-
xs |. filter (fun x -> x > 2)
186
-
```
187
-
188
-
Here whether the callback gets inlined to the call of `filter` will have an effect on how `Pjs_fn_make` gets cancelled.
189
-
190
176
Note when we pattern match over the original lamba,`Levent` needs to be removed as early as possible. Due to the existence of `Levent`, we can not pattern match over nested original raw lambda.
191
177
192
178
We turned off event generation temporarily
@@ -474,4 +460,3 @@ we do the optimizer, e.g, `Js_exp_make.int_comp`, we need make sure the peepwhol
0 commit comments