summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Angeletti <florian.angeletti@inria.fr>2021-08-24 16:54:15 +0200
committerFlorian Angeletti <florian.angeletti@inria.fr>2021-08-24 17:14:55 +0200
commit334b176b9f560a393f0a210f288dd353f5708ffb (patch)
treeeae8ad735f55d8b6ffcbbd24426e0b673cfe8f33
parentbc139d67ec05485a9f24f52b028481435e5b61ff (diff)
downloadocaml-334b176b9f560a393f0a210f288dd353f5708ffb.tar.gz
Merge pull request #10558 from Octachron/apply_selective_typing_prim
(cherry picked from commit 1bd0e663b6fcd72879172e176b32b3a9efddad2d)
-rw-r--r--Changes5
-rw-r--r--testsuite/tests/prim-revapply/apply.ml17
-rw-r--r--testsuite/tests/prim-revapply/revapply.ml17
-rw-r--r--typing/typecore.ml40
4 files changed, 75 insertions, 4 deletions
diff --git a/Changes b/Changes
index a7bf2c633f..4826c38847 100644
--- a/Changes
+++ b/Changes
@@ -575,6 +575,11 @@ OCaml 4.13.0
(Damien Doligez, report by Stephen Dolan, review by Nicolás Ojeda Bär and
Sadiq Jaffer)
+- #10450, #10558: keep %apply and %revapply primitives working with abstract
+ types. This breach of backward compatibility was only present in the alpha
+ releases of OCaml 4.13.0 .
+ (Florian Angeletti, review by Thomas Refis and Leo White)
+
- #10454: Check row_more in nondep_type_rec.
(Leo White, review by Thomas Refis)
diff --git a/testsuite/tests/prim-revapply/apply.ml b/testsuite/tests/prim-revapply/apply.ml
index 94a17b272b..685b326344 100644
--- a/testsuite/tests/prim-revapply/apply.ml
+++ b/testsuite/tests/prim-revapply/apply.ml
@@ -42,3 +42,20 @@ let _ =
(* PR#10081 *)
let bump ?(cap = 100) x = min cap (x + 1)
let _f x = bump @@ x (* no warning 48 *)
+
+(* Abstract functions *)
+let _ =
+ let module A:sig
+ type f
+ type x
+ val succ: f
+ val zero:x
+ external (@@): f -> x -> int = "%apply"
+ end = struct
+ type f = int -> int
+ type x = int
+ let succ = succ
+ let zero = 0
+ external (@@): f -> x -> int = "%apply"
+ end in
+ A.(succ @@ zero)
diff --git a/testsuite/tests/prim-revapply/revapply.ml b/testsuite/tests/prim-revapply/revapply.ml
index 4a72154724..f65b109da5 100644
--- a/testsuite/tests/prim-revapply/revapply.ml
+++ b/testsuite/tests/prim-revapply/revapply.ml
@@ -30,3 +30,20 @@ let _f x = x |> bump (* no warning 48 *)
type t = A | B
type s = A | B
let _f (x : t) = x |> function A -> 0 | B -> 1
+
+(* Abstract functions *)
+let _ =
+ let module A:sig
+ type f
+ type x
+ val succ: f
+ val zero:x
+ external (|>): x -> f -> int = "%revapply"
+ end = struct
+ type f = int -> int
+ type x = int
+ let succ = succ
+ let zero = 0
+ external (|>): x -> f -> int = "%revapply"
+ end in
+ A.(zero |> succ)
diff --git a/typing/typecore.ml b/typing/typecore.ml
index ac656fd1ef..87d4a55572 100644
--- a/typing/typecore.ml
+++ b/typing/typecore.ml
@@ -2714,6 +2714,34 @@ let rec is_inferred sexp =
| Pexp_ifthenelse (_, e1, Some e2) -> is_inferred e1 && is_inferred e2
| _ -> false
+(* check if the type of %apply or %revapply matches the type expected by
+ the specialized typing rule for those primitives.
+*)
+type apply_prim =
+ | Apply
+ | Revapply
+let check_apply_prim_type prim typ =
+ match (repr typ).desc with
+ | Tarrow (Nolabel,a,b,_) ->
+ begin match (repr b).desc with
+ | Tarrow(Nolabel,c,d,_) ->
+ let f, x, res =
+ match prim with
+ | Apply -> a, c, d
+ | Revapply -> c, a, d
+ in
+ let f, x, res = repr f, repr x, repr res in
+ begin match f.desc with
+ | Tarrow(Nolabel,fl,fr,_) ->
+ let fl, fr = repr fl, repr fr in
+ is_Tvar fl && is_Tvar fr && is_Tvar x && is_Tvar res
+ && fl == x && fr == res
+ | _ -> false
+ end
+ | _ -> false
+ end
+ | _ -> false
+
(* Merge explanation to type clash error *)
let with_explanation explanation f =
@@ -2919,12 +2947,16 @@ and type_expect_
let funct, sargs =
let funct = type_sfunct sfunct in
match funct.exp_desc, sargs with
- | Texp_ident (_, _, {val_kind = Val_prim {prim_name = "%revapply"}}),
+ | Texp_ident (_, _,
+ {val_kind = Val_prim {prim_name="%revapply"}; val_type}),
[Nolabel, sarg; Nolabel, actual_sfunct]
- when is_inferred actual_sfunct ->
+ when is_inferred actual_sfunct
+ && check_apply_prim_type Revapply val_type ->
type_sfunct actual_sfunct, [Nolabel, sarg]
- | Texp_ident (_, _, {val_kind = Val_prim {prim_name = "%apply"}}),
- [Nolabel, actual_sfunct; Nolabel, sarg] ->
+ | Texp_ident (_, _,
+ {val_kind = Val_prim {prim_name="%apply"}; val_type}),
+ [Nolabel, actual_sfunct; Nolabel, sarg]
+ when check_apply_prim_type Apply val_type ->
type_sfunct actual_sfunct, [Nolabel, sarg]
| _ ->
funct, sargs