ocaml/0014-Merge-pull-request-114...

148 lines
4.4 KiB
Diff

From 4bb84be29e2ea5eb9f979c5e3bcbde1933aa300e Mon Sep 17 00:00:00 2001
From: Florian Angeletti <florian.angeletti@inria.fr>
Date: Mon, 18 Jul 2022 10:08:53 +0200
Subject: [PATCH 14/24] Merge pull request #11417 from
lpw25/fix-virtual-class-type-constrs
Fix regression allowing virtual methods in non-virtual classes
(cherry picked from commit 4be851ed8ea1f0c6be13dce04dcc97493c6c004b)
---
Changes | 13 +-----
testsuite/tests/typing-objects/Tests.ml | 61 +++++++++++++++++++++++++
typing/typeclass.ml | 11 +++++
3 files changed, 74 insertions(+), 11 deletions(-)
diff --git a/Changes b/Changes
index 6f92ee9965..a9a9ee92f4 100644
--- a/Changes
+++ b/Changes
@@ -25,17 +25,8 @@ OCaml 4.14 maintenance branch
- #11392, #11392: assertion failure with -rectypes and external definitions
(Gabriel Scherer, review by Florian Angeletti, report by Dmitrii Kosarev)
-### Compiler user-interface and warnings:
-
-- #11184: Stop calling ranlib on created / installed libraries
- (Sébastien Hinderer, review by Xavier Leroy)
-
-### Manual and documentation:
-
-- #11045, #11409: document that the array argument to `caml_callbackN`
- must not have been declared by `CAMLlocalN`.
- (Xavier Leroy, report by Stephen Dolan, review by Gabriel Scherer.)
-
+- #11417: Fix regression allowing virtual methods in non-virtual classes.
+ (Leo White, review by Florian Angeletti)
OCaml 4.14.0 (28 March 2022)
----------------------------
diff --git a/testsuite/tests/typing-objects/Tests.ml b/testsuite/tests/typing-objects/Tests.ml
index 3dcd87c43c..9cab28e432 100644
--- a/testsuite/tests/typing-objects/Tests.ml
+++ b/testsuite/tests/typing-objects/Tests.ml
@@ -1344,3 +1344,64 @@ let _ = (new foo)#f true
class foo : object method f : bool -> bool end
- : bool = true
|}];;
+
+
+class c : object
+ method virtual m : int
+end = object
+ method m = 9
+ end
+[%%expect {|
+Lines 1-3, characters 10-3:
+1 | ..........object
+2 | method virtual m : int
+3 | end.........
+Error: This non-virtual class type has virtual methods.
+ The following methods are virtual : m
+|}];;
+
+class virtual c : object
+ method virtual m : int
+end = object
+ method m = 42
+ end
+[%%expect {|
+class virtual c : object method virtual m : int end
+|}];;
+
+class virtual cv = object
+ method virtual m : int
+ end
+
+class c : cv = object
+ method m = 42
+ end
+[%%expect {|
+class virtual cv : object method virtual m : int end
+Line 5, characters 10-12:
+5 | class c : cv = object
+ ^^
+Error: This non-virtual class type has virtual methods.
+ The following methods are virtual : m
+|}];;
+
+class virtual c : cv = object
+ method m = 41
+ end
+[%%expect {|
+class virtual c : cv
+|}];;
+
+class c = cv
+[%%expect {|
+Line 1, characters 10-12:
+1 | class c = cv
+ ^^
+Error: This non-virtual class has virtual methods.
+ The following methods are virtual : m
+|}];;
+
+class virtual c = cv
+[%%expect {|
+class virtual c : cv
+|}];;
diff --git a/typing/typeclass.ml b/typing/typeclass.ml
index fedbc0e025..8fa8523cc9 100644
--- a/typing/typeclass.ml
+++ b/typing/typeclass.ml
@@ -177,6 +177,13 @@ let check_virtual loc env virt kind sign =
| meths, vars ->
raise(Error(loc, env, Virtual_class(kind, meths, vars)))
+let rec check_virtual_clty loc env virt kind clty =
+ match clty with
+ | Cty_constr(_, _, clty) | Cty_arrow(_, _, clty) ->
+ check_virtual_clty loc env virt kind clty
+ | Cty_signature sign ->
+ check_virtual loc env virt kind sign
+
(* Return the constructor type associated to a class type *)
let rec constructor_type constr cty =
match cty with
@@ -398,6 +405,8 @@ and class_type_aux env virt self_scope scty =
) styl params
in
let typ = Cty_constr (path, params, clty) in
+ (* Check for unexpected virtual methods *)
+ check_virtual_clty scty.pcty_loc env virt Class_type typ;
cltyp (Tcty_constr ( path, lid , ctys)) typ
| Pcty_signature pcsig ->
@@ -1077,6 +1086,8 @@ and class_expr_aux cl_num val_env met_env virt self_scope scl =
try Ctype.unify val_env ty' ty with Ctype.Unify err ->
raise(Error(cty'.ctyp_loc, val_env, Parameter_mismatch err)))
tyl params;
+ (* Check for unexpected virtual methods *)
+ check_virtual_clty scl.pcl_loc val_env virt Class clty';
let cl =
rc {cl_desc = Tcl_ident (path, lid, tyl);
cl_loc = scl.pcl_loc;
--
2.37.0.rc2