ocaml/0001-Do-not-trigger-warning-when-calling-virtual-methods-.patch
2022-06-18 12:29:36 +01:00

193 lines
7.0 KiB
Diff

From 3f6a90f1ac47c480522a009d6ea56e2acfb7112f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicol=C3=A1s=20Ojeda=20B=C3=A4r?= <n.oje.bar@gmail.com>
Date: Wed, 27 Apr 2022 14:46:47 +0200
Subject: [PATCH 1/9] Do not trigger warning when calling virtual methods
introduced by constraining "self" (#11204)
(cherry picked from commit 1e7af3f6261502bb384dc9e23a74ad0990bfd854)
---
Changes | 11 ++++++-
testsuite/tests/typing-objects/Tests.ml | 15 ++++++++++
typing/typeclass.ml | 40 ++++++++++---------------
3 files changed, 40 insertions(+), 26 deletions(-)
diff --git a/Changes b/Changes
index a8ce94bdc6..931a74b8d1 100644
--- a/Changes
+++ b/Changes
@@ -1,3 +1,13 @@
+OCaml 4.14 maintenance branch
+-----------------------------
+
+### Bug fixes:
+
+- #11204: Fix regression introduced in 4.14.0 that would trigger Warning 17 when
+ calling virtual methods introduced by constraining the self type from within
+ the class definition.
+ (Nicolás Ojeda Bär, review by Leo White)
+
OCaml 4.14.0 (28 March 2022)
----------------------------
@@ -62,7 +72,6 @@ OCaml 4.14.0 (28 March 2022)
definition-aware operations.
(Ulysse Gérard, Thomas Refis and Leo White, review by Florian Angeletti)
-
### Language features:
- #10462: Add attribute to produce a compiler error for polls.
diff --git a/testsuite/tests/typing-objects/Tests.ml b/testsuite/tests/typing-objects/Tests.ml
index f617bcf1b9..3dcd87c43c 100644
--- a/testsuite/tests/typing-objects/Tests.ml
+++ b/testsuite/tests/typing-objects/Tests.ml
@@ -955,6 +955,21 @@ Warning 17 [undeclared-virtual-method]: the virtual method m is not declared.
class c : object method m : int method n : int end
|}];;
+class virtual c = object (self : 'c)
+ constraint 'c = < f : int; .. >
+end
+[%%expect {|
+class virtual c : object method virtual f : int end
+|}];;
+
+class virtual c = object (self : 'c)
+ constraint 'c = < f : int; .. >
+ method g = self # f
+end
+[%%expect {|
+class virtual c : object method virtual f : int method g : int end
+|}];;
+
class [ 'a ] c = object (_ : 'a) end;;
let o = object
method m = 1
diff --git a/typing/typeclass.ml b/typing/typeclass.ml
index 048ee998b0..fedbc0e025 100644
--- a/typing/typeclass.ml
+++ b/typing/typeclass.ml
@@ -552,12 +552,11 @@ type first_pass_accummulater =
concrete_vals : VarSet.t;
local_meths : MethSet.t;
local_vals : VarSet.t;
- vars : Ident.t Vars.t;
- meths : Ident.t Meths.t; }
+ vars : Ident.t Vars.t; }
let rec class_field_first_pass self_loc cl_num sign self_scope acc cf =
let { rev_fields; val_env; par_env; concrete_meths; concrete_vals;
- local_meths; local_vals; vars; meths } = acc
+ local_meths; local_vals; vars } = acc
in
let loc = cf.pcf_loc in
let attributes = cf.pcf_attributes in
@@ -612,13 +611,6 @@ let rec class_field_first_pass self_loc cl_num sign self_scope acc cf =
(val_env, par_env, inherited_vars, vars))
parent_sign.csig_vars (val_env, par_env, [], vars)
in
- let meths =
- Meths.fold
- (fun label _ meths ->
- if Meths.mem label meths then meths
- else Meths.add label (Ident.create_local label) meths)
- parent_sign.csig_meths meths
- in
(* Methods available through super *)
let super_meths =
MethSet.fold
@@ -641,7 +633,7 @@ let rec class_field_first_pass self_loc cl_num sign self_scope acc cf =
in
let rev_fields = field :: rev_fields in
{ acc with rev_fields; val_env; par_env;
- concrete_meths; concrete_vals; vars; meths })
+ concrete_meths; concrete_vals; vars })
| Pcf_val (label, mut, Cfk_virtual styp) ->
with_attrs
(fun () ->
@@ -723,15 +715,11 @@ let rec class_field_first_pass self_loc cl_num sign self_scope acc cf =
let cty = transl_simple_type val_env false sty in
let ty = cty.ctyp_type in
add_method loc val_env label.txt priv Virtual ty sign;
- let meths =
- if Meths.mem label.txt meths then meths
- else Meths.add label.txt (Ident.create_local label.txt) meths
- in
let field =
Virtual_method { label; priv; cty; loc; attributes }
in
let rev_fields = field :: rev_fields in
- { acc with rev_fields; meths })
+ { acc with rev_fields })
| Pcf_method (label, priv, Cfk_concrete (override, expr)) ->
with_attrs
@@ -785,10 +773,6 @@ let rec class_field_first_pass self_loc cl_num sign self_scope acc cf =
raise(Error(loc, val_env,
Field_type_mismatch ("method", label.txt, err)))
end;
- let meths =
- if Meths.mem label.txt meths then meths
- else Meths.add label.txt (Ident.create_local label.txt) meths
- in
let sdefinition = make_method self_loc cl_num expr in
let warning_state = Warnings.backup () in
let field =
@@ -799,7 +783,7 @@ let rec class_field_first_pass self_loc cl_num sign self_scope acc cf =
let rev_fields = field :: rev_fields in
let concrete_meths = MethSet.add label.txt concrete_meths in
let local_meths = MethSet.add label.txt local_meths in
- { acc with rev_fields; concrete_meths; local_meths; meths })
+ { acc with rev_fields; concrete_meths; local_meths })
| Pcf_constraint (sty1, sty2) ->
with_attrs
@@ -837,11 +821,10 @@ and class_fields_first_pass self_loc cl_num sign self_scope
let local_meths = MethSet.empty in
let local_vals = VarSet.empty in
let vars = Vars.empty in
- let meths = Meths.empty in
let init_acc =
{ rev_fields; val_env; par_env;
concrete_meths; concrete_vals;
- local_meths; local_vals; vars; meths }
+ local_meths; local_vals; vars }
in
let acc =
Builtin_attributes.warning_scope []
@@ -850,7 +833,7 @@ and class_fields_first_pass self_loc cl_num sign self_scope
(class_field_first_pass self_loc cl_num sign self_scope)
init_acc cfs)
in
- List.rev acc.rev_fields, acc.vars, acc.meths
+ List.rev acc.rev_fields, acc.vars
and class_field_second_pass cl_num sign met_env field =
let mkcf desc loc attrs =
@@ -1003,7 +986,7 @@ and class_structure cl_num virt self_scope final val_env met_env loc
end;
(* Typing of class fields *)
- let (fields, vars, meths) =
+ let (fields, vars) =
class_fields_first_pass self_loc cl_num sign self_scope
val_env par_env str
in
@@ -1016,6 +999,13 @@ and class_structure cl_num virt self_scope final val_env met_env loc
update_class_signature loc val_env
~warn_implicit_public:false virt kind sign;
+ let meths =
+ Meths.fold
+ (fun label _ meths ->
+ Meths.add label (Ident.create_local label) meths)
+ sign.csig_meths Meths.empty
+ in
+
(* Close the signature if it is final *)
begin match final with
| Not_final -> ()
--
2.36.1