Skip to content

Commit 7a53982

Browse files
committed
New mechanism to determine arity of externals.
The arity of external declarations is currently determined just based on the untyped parse tree. This is probably because the "real" arity is ambiguous in curried mode, and the convention is that an explicit type of the form `t1 => t2 => t3` determines arity 2, but type aliases are ignored. Here's an example: https://rescript-lang.org/try?version=v11.1.2&code=C4TwDgpgBArlC8UAUBLAdsANFdwCUCAfDhgFAACAbgIYA2UEAHsBAE5p1SUCMAXLAigAiSkKgB6cVGqsUoKADNWAewC2AlAGccqsLRQBjORRr0mLdp0oAmfqgzZcBeMVyCRYydNnytDRnqGxqS0EMCK3IKMRFzcSIyYjHghYYrWUTE28YnJQA In the example ```res type u = (int, int) => int @Val external v1: u = "v" // arity from u is implicit @Val external v2: (int, int) => int = "v" // arity is explicit let f1 = x => v1(x,x) let f2 = x => v2(x,x) ``` we have that `v2` is determined to have arity 2, but the arity of `v1` is not determined. As a consequence, the code generated for `f1` uses runtime `Curry`, both in curried an uncurried mode. This PR uses the actual type coming from the type checker when in uncurried mode, as that does not suffer from ambiguity. The consequences are that the external behaves the same however the type is defined, and in the example, no `Curry` runtime is generated.
1 parent 94ac53e commit 7a53982

File tree

16 files changed

+79
-98
lines changed

16 files changed

+79
-98
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
- Throws an instance of JavaScript's `new Error()` and adds the extension payload for `cause` option. https://github.com/rescript-lang/rescript-compiler/pull/6611
2020
- Allow free vars in types for type coercion `e :> t`. https://github.com/rescript-lang/rescript-compiler/pull/6828
2121
- Allow `private` in with constraints. https://github.com/rescript-lang/rescript-compiler/pull/6843
22+
- Improved mechanism to determine arity of externals, which is consistent however the type is written. https://github.com/rescript-lang/rescript-compiler/pull/6874
2223

2324
#### :boom: Breaking Change
2425

jscomp/build_tests/react_ppx/src/gpr_3695_test.bs.js

Lines changed: 1 addition & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jscomp/frontend/external_ffi_types.ml

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -240,14 +240,7 @@ let from_string s : t =
240240

241241
let () =
242242
Primitive.coerce :=
243-
fun ({
244-
prim_name;
245-
prim_arity;
246-
prim_native_name;
247-
prim_alloc = _;
248-
prim_native_repr_args = _;
249-
prim_native_repr_res = _;
250-
} :
243+
fun ({prim_name; prim_arity; prim_native_name; prim_alloc = _} :
251244
Primitive.description) (p2 : Primitive.description) ->
252245
let p2_native = p2.prim_native_name in
253246
prim_name = p2.prim_name && prim_arity = p2.prim_arity

jscomp/gentype_tests/typescript-react-example/src/ImportHookDefault.res.js

Lines changed: 7 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jscomp/gentype_tests/typescript-react-example/src/ImportHooks.res.js

Lines changed: 4 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jscomp/gentype_tests/typescript-react-example/src/ImportIndex.res.js

Lines changed: 4 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jscomp/gentype_tests/typescript-react-example/src/JSXV4.res.js

Lines changed: 4 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jscomp/gentype_tests/typescript-react-example/src/MyInput.res.js

Lines changed: 4 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jscomp/ml/primitive.ml

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,49 +20,32 @@ open Parsetree
2020

2121
type boxed_integer = Pbigint | Pint32 | Pint64
2222

23-
type native_repr =
24-
| Same_as_ocaml_repr
25-
2623
type description =
2724
{ prim_name: string; (* Name of primitive or C function *)
2825
prim_arity: int; (* Number of arguments *)
2926
prim_alloc: bool; (* Does it allocates or raise? *)
3027
prim_native_name: string; (* Name of C function for the nat. code gen. *)
31-
prim_native_repr_args: native_repr list;
32-
prim_native_repr_res: native_repr }
28+
}
3329

3430
let coerce : (description -> description -> bool) ref =
3531
ref (fun
3632
(p1 : description) (p2 : description) ->
3733
p1 = p2
3834
)
3935

40-
41-
42-
let rec make_native_repr_args arity x =
43-
if arity = 0 then
44-
[]
45-
else
46-
x :: make_native_repr_args (arity - 1) x
47-
4836
let simple ~name ~arity ~alloc =
4937
{prim_name = name;
5038
prim_arity = arity;
5139
prim_alloc = alloc;
52-
prim_native_name = "";
53-
prim_native_repr_args = make_native_repr_args arity Same_as_ocaml_repr;
54-
prim_native_repr_res = Same_as_ocaml_repr}
40+
prim_native_name = "";}
5541

56-
let make ~name ~alloc ~native_name ~native_repr_args ~native_repr_res =
42+
let make ~name ~alloc ~native_name ~arity =
5743
{prim_name = name;
58-
prim_arity = List.length native_repr_args;
44+
prim_arity = arity;
5945
prim_alloc = alloc;
60-
prim_native_name = native_name;
61-
prim_native_repr_args = native_repr_args;
62-
prim_native_repr_res = native_repr_res}
46+
prim_native_name = native_name;}
6347

64-
let parse_declaration valdecl ~native_repr_args ~native_repr_res =
65-
let arity = List.length native_repr_args in
48+
let parse_declaration valdecl ~arity =
6649
let name, native_name =
6750
match valdecl.pval_prim with
6851
| name :: name2 :: _ -> (name, name2)
@@ -73,9 +56,7 @@ let parse_declaration valdecl ~native_repr_args ~native_repr_res =
7356
{prim_name = name;
7457
prim_arity = arity;
7558
prim_alloc = true;
76-
prim_native_name = native_name;
77-
prim_native_repr_args = native_repr_args;
78-
prim_native_repr_res = native_repr_res}
59+
prim_native_name = native_name;}
7960

8061
open Outcometree
8162

jscomp/ml/primitive.mli

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,12 @@
1717

1818
type boxed_integer = Pbigint | Pint32 | Pint64
1919

20-
(* Representation of arguments/result for the native code version
21-
of a primitive *)
22-
type native_repr =
23-
| Same_as_ocaml_repr
24-
2520
type description = private
2621
{ prim_name: string; (* Name of primitive or C function *)
2722
prim_arity: int; (* Number of arguments *)
2823
prim_alloc: bool; (* Does it allocates or raise? *)
2924
prim_native_name: string; (* Name of C function for the nat. code gen. *)
30-
prim_native_repr_args: native_repr list;
31-
prim_native_repr_res: native_repr }
25+
}
3226

3327
(* Invariant [List.length d.prim_native_repr_args = d.prim_arity] *)
3428

@@ -42,14 +36,12 @@ val make
4236
: name:string
4337
-> alloc:bool
4438
-> native_name:string
45-
-> native_repr_args: native_repr list
46-
-> native_repr_res: native_repr
39+
-> arity: int
4740
-> description
4841

4942
val parse_declaration
5043
: Parsetree.value_description
51-
-> native_repr_args:native_repr list
52-
-> native_repr_res:native_repr
44+
-> arity: int
5345
-> description
5446

5547
val print

0 commit comments

Comments
 (0)