Skip to content

Commit 36611cd

Browse files
committed
Fix external signature inclusion for opaque function types
1 parent 3d9c244 commit 36611cd

File tree

5 files changed

+43
-0
lines changed

5 files changed

+43
-0
lines changed

compiler/ml/includecore.ml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,31 @@ open Typedtree
2424

2525
exception Dont_match
2626

27+
(* When comparing externals in signatures, re-derive arity/from_constructor from
28+
the value's type so abstract aliases (e.g. opaque function types) don't keep
29+
default zeros stored in the primitive descriptor, which would make equal
30+
externals look different. *)
31+
let normalize_primitive ~env val_type (prim : Primitive.description) =
32+
match Ctype.get_arity env val_type with
33+
| Some prim_arity ->
34+
let prim_from_constructor =
35+
match (Ctype.repr val_type).desc with
36+
| Tconstr _ -> true
37+
| _ -> prim.prim_from_constructor
38+
in
39+
Primitive.with_arity prim ~arity:prim_arity
40+
~from_constructor:prim_from_constructor
41+
| None -> prim
42+
2743
let value_descriptions ~loc env name (vd1 : Types.value_description)
2844
(vd2 : Types.value_description) =
2945
Builtin_attributes.check_deprecated_inclusion ~def:vd1.val_loc
3046
~use:vd2.val_loc loc vd1.val_attributes vd2.val_attributes (Ident.name name);
3147
if Ctype.moregeneral env true vd1.val_type vd2.val_type then
3248
match (vd1.val_kind, vd2.val_kind) with
3349
| Val_prim p1, Val_prim p2 ->
50+
let p1 = normalize_primitive ~env vd1.val_type p1 in
51+
let p2 = normalize_primitive ~env vd2.val_type p2 in
3452
if !Primitive.coerce p1 p2 then Tcoerce_none else raise Dont_match
3553
| Val_prim p, _ ->
3654
let pc =

compiler/ml/primitive.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ type description = {
3030

3131
let set_transformed_jsx d ~transformed_jsx = {d with transformed_jsx}
3232

33+
let with_arity d ~arity ~from_constructor =
34+
{d with prim_arity = arity; prim_from_constructor = from_constructor}
35+
3336
let coerce : (description -> description -> bool) ref =
3437
ref (fun (p1 : description) (p2 : description) -> p1 = p2)
3538

compiler/ml/primitive.mli

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ type description = private {
2727

2828
val set_transformed_jsx : description -> transformed_jsx:bool -> description
2929

30+
val with_arity :
31+
description -> arity:int -> from_constructor:bool -> description
32+
3033
(* Invariant [List.length d.prim_native_repr_args = d.prim_arity] *)
3134

3235
val parse_declaration :
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Generated by ReScript, PLEASE EDIT WITH CARE
2+
3+
4+
let B = {};
5+
6+
export {
7+
B,
8+
}
9+
/* No side effect */
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/* Regression for https://github.com/rescript-lang/rescript/issues/8038 */
2+
module type A = {
3+
type t
4+
@module external dep: t = "dep"
5+
}
6+
7+
module B: A = {
8+
type t = string => string
9+
@module external dep: t = "dep"
10+
}

0 commit comments

Comments
 (0)