From 2022164e480d71d6365ded80412b7d78865582bf Mon Sep 17 00:00:00 2001 From: Christoph Knittel Date: Sun, 30 Nov 2025 10:56:39 +0100 Subject: [PATCH 1/2] Fix external signature inclusion for opaque function types --- compiler/ml/includecore.ml | 18 ++++++++++++++++++ compiler/ml/primitive.ml | 3 +++ compiler/ml/primitive.mli | 3 +++ tests/tests/src/gpr_8038_opaque_external.mjs | 9 +++++++++ tests/tests/src/gpr_8038_opaque_external.res | 10 ++++++++++ 5 files changed, 43 insertions(+) create mode 100644 tests/tests/src/gpr_8038_opaque_external.mjs create mode 100644 tests/tests/src/gpr_8038_opaque_external.res diff --git a/compiler/ml/includecore.ml b/compiler/ml/includecore.ml index b1db9e5f16..05753d36c8 100644 --- a/compiler/ml/includecore.ml +++ b/compiler/ml/includecore.ml @@ -24,6 +24,22 @@ open Typedtree exception Dont_match +(* When comparing externals in signatures, re-derive arity/from_constructor from + the value's type so abstract aliases (e.g. opaque function types) don't keep + default zeros stored in the primitive descriptor, which would make equal + externals look different. *) +let normalize_primitive ~env val_type (prim : Primitive.description) = + match Ctype.get_arity env val_type with + | Some prim_arity -> + let prim_from_constructor = + match (Ctype.repr val_type).desc with + | Tconstr _ -> true + | _ -> prim.prim_from_constructor + in + Primitive.with_arity prim ~arity:prim_arity + ~from_constructor:prim_from_constructor + | None -> prim + let value_descriptions ~loc env name (vd1 : Types.value_description) (vd2 : Types.value_description) = Builtin_attributes.check_deprecated_inclusion ~def:vd1.val_loc @@ -31,6 +47,8 @@ let value_descriptions ~loc env name (vd1 : Types.value_description) if Ctype.moregeneral env true vd1.val_type vd2.val_type then match (vd1.val_kind, vd2.val_kind) with | Val_prim p1, Val_prim p2 -> + let p1 = normalize_primitive ~env vd1.val_type p1 in + let p2 = normalize_primitive ~env vd2.val_type p2 in if !Primitive.coerce p1 p2 then Tcoerce_none else raise Dont_match | Val_prim p, _ -> let pc = diff --git a/compiler/ml/primitive.ml b/compiler/ml/primitive.ml index 3ddc60a488..f632606e9a 100644 --- a/compiler/ml/primitive.ml +++ b/compiler/ml/primitive.ml @@ -30,6 +30,9 @@ type description = { let set_transformed_jsx d ~transformed_jsx = {d with transformed_jsx} +let with_arity d ~arity ~from_constructor = + {d with prim_arity = arity; prim_from_constructor = from_constructor} + let coerce : (description -> description -> bool) ref = ref (fun (p1 : description) (p2 : description) -> p1 = p2) diff --git a/compiler/ml/primitive.mli b/compiler/ml/primitive.mli index 8f5c58100d..c5b43c3b30 100644 --- a/compiler/ml/primitive.mli +++ b/compiler/ml/primitive.mli @@ -27,6 +27,9 @@ type description = private { val set_transformed_jsx : description -> transformed_jsx:bool -> description +val with_arity : + description -> arity:int -> from_constructor:bool -> description + (* Invariant [List.length d.prim_native_repr_args = d.prim_arity] *) val parse_declaration : diff --git a/tests/tests/src/gpr_8038_opaque_external.mjs b/tests/tests/src/gpr_8038_opaque_external.mjs new file mode 100644 index 0000000000..25597c4d0a --- /dev/null +++ b/tests/tests/src/gpr_8038_opaque_external.mjs @@ -0,0 +1,9 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + + +let B = {}; + +export { + B, +} +/* No side effect */ diff --git a/tests/tests/src/gpr_8038_opaque_external.res b/tests/tests/src/gpr_8038_opaque_external.res new file mode 100644 index 0000000000..fca5c3134c --- /dev/null +++ b/tests/tests/src/gpr_8038_opaque_external.res @@ -0,0 +1,10 @@ +/* Regression for https://github.com/rescript-lang/rescript/issues/8038 */ +module type A = { + type t + @module external dep: t = "dep" +} + +module B: A = { + type t = string => string + @module external dep: t = "dep" +} From 3a78abe66be8668c12c6503800204f8ad7087593 Mon Sep 17 00:00:00 2001 From: Christoph Knittel Date: Sun, 30 Nov 2025 11:16:13 +0100 Subject: [PATCH 2/2] CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c1dbb4f74..388fb08246 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ #### :bug: Bug fix - Rewatch: warnings for unsupported/unknown rescript.json fields. https://github.com/rescript-lang/rescript/pull/8031 +- Fix external signature inclusion for opaque function types. https://github.com/rescript-lang/rescript/pull/8045 #### :memo: Documentation