Skip to content

Commit 3565257

Browse files
authored
Fix fatal error for external with @as (#7978)
* Fix fatal error for external with @as * Add a synthetic unit argument when all external parameters collapse to constants * Simplify * CHANGELOG
1 parent 98fa501 commit 3565257

File tree

4 files changed

+29
-3
lines changed

4 files changed

+29
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#### :bug: Bug fix
2222

2323
- Fix @directive on function level with async and multiple parameters. https://github.com/rescript-lang/rescript/pull/7977
24+
- Fix fatal error for external with @as. https://github.com/rescript-lang/rescript/pull/7978
2425

2526
#### :memo: Documentation
2627

compiler/frontend/ast_external_process.ml

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,24 @@ let handle_attributes (loc : Bs_loc.t) (type_annotation : Parsetree.core_type)
997997
new_arg_types,
998998
if arg_type = Ignore then i else i + 1 ))
999999
in
1000+
(* If every original argument was erased (e.g. all `@as(json ...) _`),
1001+
keep the external binding callable by threading a final `unit`
1002+
parameter through the type and arg specs. *)
1003+
let args, arg_type_specs =
1004+
match (args, arg_type_specs_length) with
1005+
| [], n when n > 0 ->
1006+
let unit_type =
1007+
Ast_helper.Typ.constr ~loc
1008+
(Location.mkloc (Longident.Lident "unit") loc)
1009+
[]
1010+
in
1011+
let unit_arg = {Parsetree.attrs = []; lbl = Nolabel; typ = unit_type} in
1012+
( [unit_arg],
1013+
arg_type_specs
1014+
@ [{External_arg_spec.arg_label = Arg_empty; arg_type = Extern_unit}]
1015+
)
1016+
| _ -> (args, arg_type_specs)
1017+
in
10001018
let ffi : External_ffi_types.external_spec =
10011019
external_desc_of_non_obj loc external_desc prim_name_with_source
10021020
arg_type_specs_length arg_types_ty arg_type_specs
@@ -1008,8 +1026,7 @@ let handle_attributes (loc : Bs_loc.t) (type_annotation : Parsetree.core_type)
10081026
let return_wrapper =
10091027
check_return_wrapper loc external_desc.return_wrapper result_type
10101028
in
1011-
let fn_type = Ast_helper.Typ.arrows ~loc args result_type in
1012-
( build_uncurried_type ~arity:(List.length args) fn_type,
1029+
( Ast_helper.Typ.arrows ~loc args result_type,
10131030
External_ffi_types.ffi_bs arg_type_specs return_wrapper ffi,
10141031
unused_attrs,
10151032
relative )

tests/tests/src/AsInUncurriedExternals.mjs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@ function shouldNotFail(objectMode, name) {
1919
return 3;
2020
}
2121

22+
let x = somescope.somefn({foo:true});
23+
2224
export {
2325
mo,
2426
options,
2527
shouldNotFail,
28+
x,
2629
}
27-
/* No side effect */
30+
/* x Not a pure module */

tests/tests/src/AsInUncurriedExternals.res

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,8 @@ let mo = makeOptions
1313
let options = mo(~name="foo", ())
1414

1515
let shouldNotFail: (~objectMode: _, ~name: string) => int = (~objectMode, ~name) => 3
16+
17+
@scope("somescope")
18+
external constantArgOnly: @as(json`{foo:true}`) _ => string = "somefn"
19+
20+
let x = constantArgOnly()

0 commit comments

Comments
 (0)