summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlain Frisch <alain@frisch.fr>2017-07-20 08:17:30 +0200
committerGitHub <noreply@github.com>2017-07-20 08:17:30 +0200
commitfd47ba9649f784c7d0772bdf282b8e7c8f1fe5aa (patch)
treeca04dce4e190f80e7dc5d2610404c238a6372358
parent23ba4788f0a30e4c64565e9a08bc6557b58b95bf (diff)
downloadocaml-fd47ba9649f784c7d0772bdf282b8e7c8f1fe5aa.tar.gz
Support 'let open' in class and class type expressions (#1249)
* Support 'let open' in class and class type expressions. * Adapt ocamlprof. * Adapt ocamldoc. * Add tests. * Changelog. * Manual.
-rw-r--r--Changes4
-rw-r--r--bytecomp/translclass.ml8
-rw-r--r--manual/manual/refman/classes.etex9
-rw-r--r--manual/manual/refman/exten.etex11
-rw-r--r--ocamldoc/odoc_sig.ml1
-rw-r--r--parsing/ast_helper.ml2
-rw-r--r--parsing/ast_helper.mli4
-rwxr-xr-xparsing/ast_iterator.ml4
-rw-r--r--parsing/ast_mapper.ml4
-rw-r--r--parsing/depend.ml4
-rw-r--r--parsing/parser.mly6
-rw-r--r--parsing/parsetree.mli7
-rw-r--r--parsing/pprintast.ml6
-rw-r--r--parsing/printast.ml8
-rw-r--r--testsuite/tests/parsetree/source.ml15
-rwxr-xr-xtestsuite/tests/typing-objects/open_in_classes.ml17
-rw-r--r--testsuite/tests/typing-objects/open_in_classes.ml.reference5
-rw-r--r--tools/ocamlprof.ml1
-rw-r--r--typing/env.ml12
-rw-r--r--typing/env.mli1
-rw-r--r--typing/printtyped.ml6
-rw-r--r--typing/tast_mapper.ml4
-rw-r--r--typing/typeclass.ml18
-rw-r--r--typing/typecore.ml8
-rw-r--r--typing/typecore.mli3
-rw-r--r--typing/typedtree.ml2
-rw-r--r--typing/typedtree.mli4
-rw-r--r--typing/typedtreeIter.ml5
-rw-r--r--typing/typedtreeMap.ml6
-rw-r--r--typing/typemod.ml4
-rw-r--r--typing/typemod.mli2
-rw-r--r--typing/untypeast.ml5
32 files changed, 182 insertions, 14 deletions
diff --git a/Changes b/Changes
index 5ecdf45639..8376357080 100644
--- a/Changes
+++ b/Changes
@@ -9,6 +9,10 @@ Working version
can be used as a placeholder for a polymorphic function.
(Stephen Dolan)
+- GPR#1249, MPR#6271, MPR#7529: Support "let open M in ..."
+ in class expressions and class type expressions.
+ (Alain Frisch, reviews by Thomas Refis and Jacques Garrigue)
+
### Code generation and optimizations:
- MPR#5324, GPR#375: An alternative Linear Scan register allocator for
diff --git a/bytecomp/translclass.ml b/bytecomp/translclass.ml
index 03f575920d..e71e77fa7c 100644
--- a/bytecomp/translclass.ml
+++ b/bytecomp/translclass.ml
@@ -195,7 +195,8 @@ let rec build_object_init cl_table obj params inh_init obj_init cl =
build_object_init cl_table obj (vals @ params) inh_init obj_init cl
in
(inh_init, Translcore.transl_let rec_flag defs obj_init)
- | Tcl_constraint (cl, _, _vals, _pub_meths, _concr_meths) ->
+ | Tcl_open (_, _, _, _, cl)
+ | Tcl_constraint (cl, _, _, _, _) ->
build_object_init cl_table obj params inh_init obj_init cl
let rec build_object_init_0 cl_table params cl copy_env subst_env top ids =
@@ -386,6 +387,8 @@ let rec build_class_init cla cstr super inh_init cl_init msubst top cl =
Lsequence(mkappl (oo_prim "narrow", narrow_args),
cl_init))
end
+ | Tcl_open (_, _, _, _, cl) ->
+ build_class_init cla cstr super inh_init cl_init msubst top cl
let rec build_class_lets cl ids =
match cl.cl_desc with
@@ -407,6 +410,7 @@ let rec get_class_meths cl =
| Tcl_fun (_, _, _, cl, _)
| Tcl_let (_, _, _, cl)
| Tcl_apply (cl, _)
+ | Tcl_open (_, _, _, _, cl)
| Tcl_constraint (cl, _, _, _, _) -> get_class_meths cl
(*
@@ -452,6 +456,8 @@ let rec transl_class_rebind obj_init cl vf =
in
check_constraint cl.cl_type;
(path, obj_init)
+ | Tcl_open (_, _, _, _, cl) ->
+ transl_class_rebind obj_init cl vf
let rec transl_class_rebind_0 self obj_init cl vf =
match cl.cl_desc with
diff --git a/manual/manual/refman/classes.etex b/manual/manual/refman/classes.etex
index d9f27d7402..2480357c9f 100644
--- a/manual/manual/refman/classes.etex
+++ b/manual/manual/refman/classes.etex
@@ -27,6 +27,7 @@ class-type:
class-body-type:
'object' ['(' typexpr ')'] {class-field-spec} 'end'
| ['[' typexpr {',' typexpr} ']'] classtype-path
+ | 'let' 'open' module-path 'in' class-body-type
;
%\end{syntax} \begin{syntax}
class-field-spec:
@@ -75,6 +76,10 @@ virtual method will match a concrete method, which makes it possible
to forget its implementation. An immutable instance variable will match a
mutable instance variable.
+\subsubsection*{Local opens}
+
+Local opens are supported in class types since OCaml 4.06.
+
\subsubsection*{Inheritance}
\ikwd{inherit\@\texttt{inherit}}
@@ -173,6 +178,7 @@ class-expr:
| 'fun' {{parameter}} '->' class-expr
| 'let' ['rec'] let-binding {'and' let-binding} 'in' class-expr
| 'object' class-body 'end'
+ | 'let' 'open' module-path 'in' class-expr
;
%BEGIN LATEX
\end{syntax} \begin{syntax}
@@ -258,6 +264,9 @@ definition, it will be evaluated when the class is created (just as if
the definition was outside of the class).
Otherwise, it will be evaluated when the object constructor is called.
+\subsubsection*{Local opens}
+
+Local opens are supported in class expressions since OCaml 4.06.
\subsubsection*{Class\label{ss:class-body} body}
\begin{syntax}
diff --git a/manual/manual/refman/exten.etex b/manual/manual/refman/exten.etex
index 0fee6f5fc3..4b4ddb2e76 100644
--- a/manual/manual/refman/exten.etex
+++ b/manual/manual/refman/exten.etex
@@ -1020,6 +1020,15 @@ specification:
expr:
...
| 'let' 'open!' module-path 'in' expr
+;
+class-body-type:
+ ...
+ | 'let' 'open!' module-path 'in' class-body-type
+;
+class-expr:
+ ...
+ | 'let' 'open!' module-path 'in' class-expr
+;
\end{syntax}
Since OCaml 4.01, @"open"@ statements shadowing an existing identifier
@@ -1027,6 +1036,8 @@ Since OCaml 4.01, @"open"@ statements shadowing an existing identifier
character after the @"open"@ keyword indicates that such a shadowing is
intentional and should not trigger the warning.
+This is also available (since OCaml 4.06) for local opens in class
+expressions and class type expressions.
\section{Generalized algebraic datatypes} \ikwd{type\@\texttt{type}}
\ikwd{match\@\texttt{match}} \label{s:gadts}
diff --git a/ocamldoc/odoc_sig.ml b/ocamldoc/odoc_sig.ml
index 5bc67b8016..925f95c508 100644
--- a/ocamldoc/odoc_sig.ml
+++ b/ocamldoc/odoc_sig.ml
@@ -606,6 +606,7 @@ module Analyser =
ic_text = text_opt ;
}
+ | Parsetree.Pcty_open _ (* one could also traverse the open *)
| Parsetree.Pcty_signature _
| Parsetree.Pcty_arrow _ ->
(* we don't have a name for the class signature, so we call it "object ... end" *)
diff --git a/parsing/ast_helper.ml b/parsing/ast_helper.ml
index ac1fc40da5..4a0c78386d 100644
--- a/parsing/ast_helper.ml
+++ b/parsing/ast_helper.ml
@@ -286,6 +286,7 @@ module Cl = struct
let let_ ?loc ?attrs a b c = mk ?loc ?attrs (Pcl_let (a, b, c))
let constraint_ ?loc ?attrs a b = mk ?loc ?attrs (Pcl_constraint (a, b))
let extension ?loc ?attrs a = mk ?loc ?attrs (Pcl_extension a)
+ let open_ ?loc ?attrs a b c = mk ?loc ?attrs (Pcl_open (a, b, c))
end
module Cty = struct
@@ -301,6 +302,7 @@ module Cty = struct
let signature ?loc ?attrs a = mk ?loc ?attrs (Pcty_signature a)
let arrow ?loc ?attrs a b c = mk ?loc ?attrs (Pcty_arrow (a, b, c))
let extension ?loc ?attrs a = mk ?loc ?attrs (Pcty_extension a)
+ let open_ ?loc ?attrs a b c = mk ?loc ?attrs (Pcty_open (a, b, c))
end
module Ctf = struct
diff --git a/parsing/ast_helper.mli b/parsing/ast_helper.mli
index 0a216bdb56..9a817883f9 100644
--- a/parsing/ast_helper.mli
+++ b/parsing/ast_helper.mli
@@ -353,6 +353,8 @@ module Cty:
val arrow: ?loc:loc -> ?attrs:attrs -> arg_label -> core_type ->
class_type -> class_type
val extension: ?loc:loc -> ?attrs:attrs -> extension -> class_type
+ val open_: ?loc:loc -> ?attrs:attrs -> override_flag -> lid -> class_type
+ -> class_type
end
(** Class type fields *)
@@ -391,6 +393,8 @@ module Cl:
val constraint_: ?loc:loc -> ?attrs:attrs -> class_expr -> class_type ->
class_expr
val extension: ?loc:loc -> ?attrs:attrs -> extension -> class_expr
+ val open_: ?loc:loc -> ?attrs:attrs -> override_flag -> lid -> class_expr
+ -> class_expr
end
(** Class fields *)
diff --git a/parsing/ast_iterator.ml b/parsing/ast_iterator.ml
index 8518438d82..7323a5fa03 100755
--- a/parsing/ast_iterator.ml
+++ b/parsing/ast_iterator.ml
@@ -182,6 +182,8 @@ module CT = struct
| Pcty_arrow (_lab, t, ct) ->
sub.typ sub t; sub.class_type sub ct
| Pcty_extension x -> sub.extension sub x
+ | Pcty_open (_ovf, lid, e) ->
+ iter_loc sub lid; sub.class_type sub e
let iter_field sub {pctf_desc = desc; pctf_loc = loc; pctf_attributes = attrs}
=
@@ -427,6 +429,8 @@ module CE = struct
| Pcl_constraint (ce, ct) ->
sub.class_expr sub ce; sub.class_type sub ct
| Pcl_extension x -> sub.extension sub x
+ | Pcl_open (_ovf, lid, e) ->
+ iter_loc sub lid; sub.class_expr sub e
let iter_kind sub = function
| Cfk_concrete (_o, e) -> sub.expr sub e
diff --git a/parsing/ast_mapper.ml b/parsing/ast_mapper.ml
index 4962cc2cdb..5c744a22f6 100644
--- a/parsing/ast_mapper.ml
+++ b/parsing/ast_mapper.ml
@@ -191,6 +191,8 @@ module CT = struct
| Pcty_arrow (lab, t, ct) ->
arrow ~loc ~attrs lab (sub.typ sub t) (sub.class_type sub ct)
| Pcty_extension x -> extension ~loc ~attrs (sub.extension sub x)
+ | Pcty_open (ovf, lid, ct) ->
+ open_ ~loc ~attrs ovf (map_loc sub lid) (sub.class_type sub ct)
let map_field sub {pctf_desc = desc; pctf_loc = loc; pctf_attributes = attrs}
=
@@ -451,6 +453,8 @@ module CE = struct
| Pcl_constraint (ce, ct) ->
constraint_ ~loc ~attrs (sub.class_expr sub ce) (sub.class_type sub ct)
| Pcl_extension x -> extension ~loc ~attrs (sub.extension sub x)
+ | Pcl_open (ovf, lid, ce) ->
+ open_ ~loc ~attrs ovf (map_loc sub lid) (sub.class_expr sub ce)
let map_kind sub = function
| Cfk_concrete (o, e) -> Cfk_concrete (o, sub.expr sub e)
diff --git a/parsing/depend.ml b/parsing/depend.ml
index 7adb900ed1..910ad8992c 100644
--- a/parsing/depend.ml
+++ b/parsing/depend.ml
@@ -167,6 +167,8 @@ let rec add_class_type bv cty =
| Pcty_arrow(_, ty1, cty2) ->
add_type bv ty1; add_class_type bv cty2
| Pcty_extension e -> handle_extension e
+ | Pcty_open (_ovf, m, e) ->
+ let bv = open_module bv m.txt in add_class_type bv e
and add_class_type_field bv pctf =
match pctf.pctf_desc with
@@ -502,6 +504,8 @@ and add_class_expr bv ce =
| Pcl_constraint(ce, ct) ->
add_class_expr bv ce; add_class_type bv ct
| Pcl_extension e -> handle_extension e
+ | Pcl_open (_ovf, m, e) ->
+ let bv = open_module bv m.txt in add_class_expr bv e
and add_class_field bv pcf =
match pcf.pcf_desc with
diff --git a/parsing/parser.mly b/parsing/parser.mly
index 2dc49aa420..451350afa1 100644
--- a/parsing/parser.mly
+++ b/parsing/parser.mly
@@ -260,6 +260,8 @@ let mkpat_attrs d attrs =
let wrap_class_attrs body attrs =
{body with pcl_attributes = attrs @ body.pcl_attributes}
+let wrap_class_type_attrs body attrs =
+ {body with pcty_attributes = attrs @ body.pcty_attributes}
let wrap_mod_attrs body attrs =
{body with pmod_attributes = attrs @ body.pmod_attributes}
let wrap_mty_attrs body attrs =
@@ -1033,6 +1035,8 @@ class_expr:
{ mkclass(Pcl_apply($1, List.rev $2)) }
| let_bindings IN class_expr
{ class_of_let_bindings $1 $3 }
+ | LET OPEN override_flag attributes mod_longident IN class_expr
+ { wrap_class_attrs (mkclass(Pcl_open($3, mkrhs $5 5, $7))) $4 }
| class_expr attribute
{ Cl.attr $1 $2 }
| extension
@@ -1165,6 +1169,8 @@ class_signature:
{ Cty.attr $1 $2 }
| extension
{ mkcty(Pcty_extension $1) }
+ | LET OPEN override_flag attributes mod_longident IN class_signature
+ { wrap_class_type_attrs (mkcty(Pcty_open($3, mkrhs $5 5, $7))) $4 }
;
class_sig_body:
class_self_type class_sig_fields
diff --git a/parsing/parsetree.mli b/parsing/parsetree.mli
index 1155ddc9ec..e1961aae42 100644
--- a/parsing/parsetree.mli
+++ b/parsing/parsetree.mli
@@ -501,6 +501,8 @@ and class_type_desc =
*)
| Pcty_extension of extension
(* [%id] *)
+ | Pcty_open of override_flag * Longident.t loc * class_type
+ (* let open M in CT *)
and class_signature =
{
@@ -590,7 +592,10 @@ and class_expr_desc =
| Pcl_constraint of class_expr * class_type
(* (CE : CT) *)
| Pcl_extension of extension
- (* [%id] *)
+ (* [%id] *)
+ | Pcl_open of override_flag * Longident.t loc * class_expr
+ (* let open M in CE *)
+
and class_structure =
{
diff --git a/parsing/pprintast.ml b/parsing/pprintast.ml
index 1b38fe461f..fe3c84d577 100644
--- a/parsing/pprintast.ml
+++ b/parsing/pprintast.ml
@@ -795,6 +795,9 @@ and class_type ctxt f x =
| Pcty_extension e ->
extension ctxt f e;
attributes ctxt f x.pcty_attributes
+ | Pcty_open (ovf, lid, e) ->
+ pp f "@[<2>let open%s %a in@;%a@]" (override ovf) longident_loc lid
+ (class_type ctxt) e
(* [class type a = object end] *)
and class_type_declaration_list ctxt f l =
@@ -911,6 +914,9 @@ and class_expr ctxt f x =
(class_expr ctxt) ce
(class_type ctxt) ct
| Pcl_extension e -> extension ctxt f e
+ | Pcl_open (ovf, lid, e) ->
+ pp f "@[<2>let open%s %a in@;%a@]" (override ovf) longident_loc lid
+ (class_expr ctxt) e
and module_type ctxt f x =
if x.pmty_attributes <> [] then begin
diff --git a/parsing/printast.ml b/parsing/printast.ml
index 6e167b3e47..73d9d7a21c 100644
--- a/parsing/printast.ml
+++ b/parsing/printast.ml
@@ -482,6 +482,10 @@ and class_type i ppf x =
| Pcty_extension (s, arg) ->
line i ppf "Pcty_extension \"%s\"\n" s.txt;
payload i ppf arg
+ | Pcty_open (ovf, m, e) ->
+ line i ppf "Pcty_open %a \"%a\"\n" fmt_override_flag ovf
+ fmt_longident_loc m;
+ class_type i ppf e
and class_signature i ppf cs =
line i ppf "class_signature\n";
@@ -569,6 +573,10 @@ and class_expr i ppf x =
| Pcl_extension (s, arg) ->
line i ppf "Pcl_extension \"%s\"\n" s.txt;
payload i ppf arg
+ | Pcl_open (ovf, m, e) ->
+ line i ppf "Pcl_open %a \"%a\"\n" fmt_override_flag ovf
+ fmt_longident_loc m;
+ class_expr i ppf e
and class_structure i ppf { pcstr_self = p; pcstr_fields = l } =
line i ppf "class_structure\n";
diff --git a/testsuite/tests/parsetree/source.ml b/testsuite/tests/parsetree/source.ml
index 99ecea98af..ef67a9746a 100644
--- a/testsuite/tests/parsetree/source.ml
+++ b/testsuite/tests/parsetree/source.ml
@@ -7298,3 +7298,18 @@ fun contents -> {contents=contents[@foo]};;
(* https://github.com/LexiFi/gen_js_api/issues/61 *)
let () = foo##.bar := ();;
+
+(* "let open" in classes and class types *)
+
+class c =
+ let open M in
+ object
+ method f : t = x
+ end
+;;
+class type ct =
+ let open M in
+ object
+ method f : t
+ end
+;;
diff --git a/testsuite/tests/typing-objects/open_in_classes.ml b/testsuite/tests/typing-objects/open_in_classes.ml
new file mode 100755
index 0000000000..24c0b34dfe
--- /dev/null
+++ b/testsuite/tests/typing-objects/open_in_classes.ml
@@ -0,0 +1,17 @@
+module M = struct
+ type t = int
+ let x = 42
+end
+;;
+class c =
+ let open M in
+ object
+ method f : t = x
+ end
+;;
+class type ct =
+ let open M in
+ object
+ method f : t
+ end
+;;
diff --git a/testsuite/tests/typing-objects/open_in_classes.ml.reference b/testsuite/tests/typing-objects/open_in_classes.ml.reference
new file mode 100644
index 0000000000..eaafa30f16
--- /dev/null
+++ b/testsuite/tests/typing-objects/open_in_classes.ml.reference
@@ -0,0 +1,5 @@
+
+# module M : sig type t = int val x : int end
+# class c : object method f : M.t end
+# class type ct = object method f : M.t end
+#
diff --git a/tools/ocamlprof.ml b/tools/ocamlprof.ml
index fb08ffd5ea..2e72d52cf0 100644
--- a/tools/ocamlprof.ml
+++ b/tools/ocamlprof.ml
@@ -367,6 +367,7 @@ and rewrite_class_expr iflag cexpr =
| Pcl_let (_, spat_sexp_list, cexpr) ->
rewrite_patexp_list iflag spat_sexp_list;
rewrite_class_expr iflag cexpr
+ | Pcl_open (_, _, cexpr)
| Pcl_constraint (cexpr, _) ->
rewrite_class_expr iflag cexpr
| Pcl_extension _ -> ()
diff --git a/typing/env.ml b/typing/env.ml
index a1105fab89..c5e26fc1e4 100644
--- a/typing/env.ml
+++ b/typing/env.ml
@@ -2078,17 +2078,21 @@ let open_pers_signature name env =
| Some env -> env
| None -> assert false (* a compilation unit cannot refer to a functor *)
-let open_signature ?(loc = Location.none) ?(toplevel = false) ovf root env =
+let open_signature
+ ?(used_slot = ref false)
+ ?(loc = Location.none) ?(toplevel = false) ovf root env =
if not toplevel && ovf = Asttypes.Fresh && not loc.Location.loc_ghost
&& (Warnings.is_active (Warnings.Unused_open "")
|| Warnings.is_active (Warnings.Open_shadow_identifier ("", ""))
|| Warnings.is_active (Warnings.Open_shadow_label_constructor ("","")))
then begin
- let used = ref false in
+ let used = used_slot in
!add_delayed_check_forward
(fun () ->
- if not !used then
- Location.prerr_warning loc (Warnings.Unused_open (Path.name root))
+ if not !used then begin
+ used := true;
+ Location.prerr_warning loc (Warnings.Unused_open (Path.name root))
+ end
);
let shadowed = ref [] in
let slot s b =
diff --git a/typing/env.mli b/typing/env.mli
index ff737e3e89..f96c76b7c1 100644
--- a/typing/env.mli
+++ b/typing/env.mli
@@ -156,6 +156,7 @@ val add_signature: signature -> t -> t
Used to implement open. Returns None if the path refers to a functor,
not a structure. *)
val open_signature:
+ ?used_slot:bool ref ->
?loc:Location.t -> ?toplevel:bool -> Asttypes.override_flag -> Path.t ->
t -> t option
diff --git a/typing/printtyped.ml b/typing/printtyped.ml
index 78e1b60a5b..0609504b8e 100644
--- a/typing/printtyped.ml
+++ b/typing/printtyped.ml
@@ -479,6 +479,9 @@ and class_type i ppf x =
arg_label i ppf l;
core_type i ppf co;
class_type i ppf cl;
+ | Tcty_open (ovf, m, _, _, e) ->
+ line i ppf "Tcty_open %a \"%a\"\n" fmt_override_flag ovf fmt_path m;
+ class_type i ppf e
and class_signature i ppf { csig_self = ct; csig_fields = l } =
line i ppf "class_signature\n";
@@ -560,6 +563,9 @@ and class_expr i ppf x =
class_expr i ppf ce;
class_type i ppf ct
| Tcl_constraint (ce, None, _, _, _) -> class_expr i ppf ce
+ | Tcl_open (ovf, m, _, _, e) ->
+ line i ppf "Tcty_open %a \"%a\"\n" fmt_override_flag ovf fmt_path m;
+ class_expr i ppf e
and class_structure i ppf { cstr_self = p; cstr_fields = l } =
line i ppf "class_structure\n";
diff --git a/typing/tast_mapper.ml b/typing/tast_mapper.ml
index 0873dd4c9e..ce67092958 100644
--- a/typing/tast_mapper.ml
+++ b/typing/tast_mapper.ml
@@ -521,6 +521,8 @@ let class_expr sub x =
)
| Tcl_ident (path, lid, tyl) ->
Tcl_ident (path, lid, List.map (sub.typ sub) tyl)
+ | Tcl_open (ovf, p, lid, env, e) ->
+ Tcl_open (ovf, p, lid, sub.env sub env, sub.class_expr sub e)
in
{x with cl_desc; cl_env}
@@ -541,6 +543,8 @@ let class_type sub x =
sub.typ sub ct,
sub.class_type sub cl
)
+ | Tcty_open (ovf, p, lid, env, e) ->
+ Tcty_open (ovf, p, lid, sub.env sub env, sub.class_type sub e)
in
{x with cltyp_desc; cltyp_env}
diff --git a/typing/typeclass.ml b/typing/typeclass.ml
index 51f8a256dc..f3b10dd75f 100644
--- a/typing/typeclass.ml
+++ b/typing/typeclass.ml
@@ -540,6 +540,12 @@ and class_type env scty =
let clty = class_type env scty in
let typ = Cty_arrow (l, ty, clty.cltyp_type) in
cltyp (Tcty_arrow (l, cty, clty)) typ
+
+ | Pcty_open (ovf, lid, e) ->
+ let (path, newenv) = !Typecore.type_open ovf env scty.pcty_loc lid in
+ let clty = class_type newenv e in
+ cltyp (Tcty_open (ovf, path, lid, newenv, clty)) clty.cltyp_type
+
| Pcty_extension ext ->
raise (Error_forward (Builtin_attributes.error_of_extension ext))
@@ -1191,6 +1197,17 @@ and class_expr cl_num val_env met_env scl =
cl_env = val_env;
cl_attributes = scl.pcl_attributes;
}
+ | Pcl_open (ovf, lid, e) ->
+ let used_slot = ref false in
+ let (path, new_val_env) = !Typecore.type_open ~used_slot ovf val_env scl.pcl_loc lid in
+ let (_path, new_met_env) = !Typecore.type_open ~used_slot ovf met_env scl.pcl_loc lid in
+ let cl = class_expr cl_num new_val_env new_met_env e in
+ rc {cl_desc = Tcl_open (ovf, path, lid, new_val_env, cl);
+ cl_loc = scl.pcl_loc;
+ cl_type = cl.cl_type;
+ cl_env = val_env;
+ cl_attributes = scl.pcl_attributes;
+ }
| Pcl_extension ext ->
raise (Error_forward (Builtin_attributes.error_of_extension ext))
@@ -1704,6 +1721,7 @@ let rec unify_parents env ty cl =
| _exn -> assert false
end
| Tcl_structure st -> unify_parents_struct env ty st
+ | Tcl_open (_, _, _, _, cl)
| Tcl_fun (_, _, _, cl, _)
| Tcl_apply (cl, _)
| Tcl_let (_, _, _, cl)
diff --git a/typing/typecore.ml b/typing/typecore.ml
index d76710f1de..a1e47a10e6 100644
--- a/typing/typecore.ml
+++ b/typing/typecore.ml
@@ -89,8 +89,11 @@ let type_module =
(* Forward declaration, to be filled in by Typemod.type_open *)
-let type_open =
- ref (fun _ -> assert false)
+let type_open :
+ (?used_slot:bool ref -> override_flag -> Env.t -> Location.t ->
+ Longident.t loc -> Path.t * Env.t)
+ ref =
+ ref (fun ?used_slot:_ _ -> assert false)
(* Forward declaration, to be filled in by Typemod.type_package *)
@@ -220,6 +223,7 @@ let iter_expression f e =
class_expr ce; List.iter (fun (_, e) -> expr e) lel
| Pcl_let (_, pel, ce) ->
List.iter binding pel; class_expr ce
+ | Pcl_open (_, _, ce)
| Pcl_constraint (ce, _) -> class_expr ce
| Pcl_extension _ -> ()
diff --git a/typing/typecore.mli b/typing/typecore.mli
index 7b64ee343c..b9ad77bff9 100644
--- a/typing/typecore.mli
+++ b/typing/typecore.mli
@@ -135,7 +135,8 @@ val report_error: Env.t -> formatter -> error -> unit
val type_module: (Env.t -> Parsetree.module_expr -> Typedtree.module_expr) ref
(* Forward declaration, to be filled in by Typemod.type_open *)
val type_open:
- (override_flag -> Env.t -> Location.t -> Longident.t loc -> Path.t * Env.t)
+ (?used_slot:bool ref -> override_flag -> Env.t -> Location.t ->
+ Longident.t loc -> Path.t * Env.t)
ref
(* Forward declaration, to be filled in by Typeclass.class_structure *)
val type_object:
diff --git a/typing/typedtree.ml b/typing/typedtree.ml
index db4440c18f..02888dfdad 100644
--- a/typing/typedtree.ml
+++ b/typing/typedtree.ml
@@ -153,6 +153,7 @@ and class_expr_desc =
| Tcl_constraint of
class_expr * class_type option * string list * string list * Concr.t
(* Visible instance variables, methods and concretes methods *)
+ | Tcl_open of override_flag * Path.t * Longident.t loc * Env.t * class_expr
and class_structure =
{
@@ -478,6 +479,7 @@ and class_type_desc =
Tcty_constr of Path.t * Longident.t loc * core_type list
| Tcty_signature of class_signature
| Tcty_arrow of arg_label * core_type * class_type
+ | Tcty_open of override_flag * Path.t * Longident.t loc * Env.t * class_type
and class_signature = {
csig_self: core_type;
diff --git a/typing/typedtree.mli b/typing/typedtree.mli
index ee26bca3e1..261b4a4bc2 100644
--- a/typing/typedtree.mli
+++ b/typing/typedtree.mli
@@ -267,7 +267,8 @@ and class_expr_desc =
(Ident.t * string loc * expression) list * class_expr
| Tcl_constraint of
class_expr * class_type option * string list * string list * Concr.t
- (* Visible instance variables, methods and concretes methods *)
+ (* Visible instance variables, methods and concretes methods *)
+ | Tcl_open of override_flag * Path.t * Longident.t loc * Env.t * class_expr
and class_structure =
{
@@ -600,6 +601,7 @@ and class_type_desc =
Tcty_constr of Path.t * Longident.t loc * core_type list
| Tcty_signature of class_signature
| Tcty_arrow of arg_label * core_type * class_type
+ | Tcty_open of override_flag * Path.t * Longident.t loc * Env.t * class_type
and class_signature = {
csig_self : core_type;
diff --git a/typing/typedtreeIter.ml b/typing/typedtreeIter.ml
index fd04e55210..5babcea065 100644
--- a/typing/typedtreeIter.ml
+++ b/typing/typedtreeIter.ml
@@ -511,6 +511,9 @@ module MakeIterator(Iter : IteratorArgument) : sig
| Tcl_ident (_, _, tyl) ->
List.iter iter_core_type tyl
+
+ | Tcl_open (_, _, _, _, e) ->
+ iter_class_expr e
end;
Iter.leave_class_expr cexpr;
@@ -524,6 +527,8 @@ module MakeIterator(Iter : IteratorArgument) : sig
| Tcty_arrow (_label, ct, cl) ->
iter_core_type ct;
iter_class_type cl
+ | Tcty_open (_, _, _, _, e) ->
+ iter_class_type e
end;
Iter.leave_class_type ct;
diff --git a/typing/typedtreeMap.ml b/typing/typedtreeMap.ml
index 58249be2a6..58983a11b8 100644
--- a/typing/typedtreeMap.ml
+++ b/typing/typedtreeMap.ml
@@ -566,7 +566,9 @@ module MakeMap(Map : MapArgument) = struct
Some (map_class_type clty), vals, meths, concrs)
| Tcl_ident (id, name, tyl) ->
- Tcl_ident (id, name, List.map map_core_type tyl)
+ Tcl_ident (id, name, List.map map_core_type tyl)
+ | Tcl_open (ovf, p, lid, env, e) ->
+ Tcl_open (ovf, p, lid, env, map_class_expr e)
in
Map.leave_class_expr { cexpr with cl_desc = cl_desc }
@@ -579,6 +581,8 @@ module MakeMap(Map : MapArgument) = struct
Tcty_constr (path, lid, List.map map_core_type list)
| Tcty_arrow (label, ct, cl) ->
Tcty_arrow (label, map_core_type ct, map_class_type cl)
+ | Tcty_open (ovf, p, lid, env, e) ->
+ Tcty_open (ovf, p, lid, env, map_class_type e)
in
Map.leave_class_type { ct with cltyp_desc = cltyp_desc }
diff --git a/typing/typemod.ml b/typing/typemod.ml
index 376128be6e..175442869d 100644
--- a/typing/typemod.ml
+++ b/typing/typemod.ml
@@ -82,9 +82,9 @@ let extract_sig_open env loc mty =
(* Compute the environment after opening a module *)
-let type_open_ ?toplevel ovf env loc lid =
+let type_open_ ?used_slot ?toplevel ovf env loc lid =
let path = Typetexp.lookup_module ~load:true env lid.loc lid.txt in
- match Env.open_signature ~loc ?toplevel ovf path env with
+ match Env.open_signature ~loc ?used_slot ?toplevel ovf path env with
| Some env -> path, env
| None ->
let md = Env.find_module path env in
diff --git a/typing/typemod.mli b/typing/typemod.mli
index fbda10b5e8..b975eb2ac0 100644
--- a/typing/typemod.mli
+++ b/typing/typemod.mli
@@ -36,7 +36,7 @@ val transl_signature:
val check_nongen_schemes:
Env.t -> Types.signature -> unit
val type_open_:
- ?toplevel:bool -> Asttypes.override_flag ->
+ ?used_slot:bool ref -> ?toplevel:bool -> Asttypes.override_flag ->
Env.t -> Location.t -> Longident.t Asttypes.loc -> Path.t * Env.t
val modtype_of_package:
Env.t -> Location.t ->
diff --git a/typing/untypeast.ml b/typing/untypeast.ml
index 0cb58f484a..10f4271b54 100644
--- a/typing/untypeast.ml
+++ b/typing/untypeast.ml
@@ -634,6 +634,9 @@ let class_expr sub cexpr =
| Tcl_constraint (cl, Some clty, _vals, _meths, _concrs) ->
Pcl_constraint (sub.class_expr sub cl, sub.class_type sub clty)
+ | Tcl_open (ovf, _p, lid, _env, e) ->
+ Pcl_open (ovf, lid, sub.class_expr sub e)
+
| Tcl_ident _ -> assert false
| Tcl_constraint (_, None, _, _, _) -> assert false
in
@@ -648,6 +651,8 @@ let class_type sub ct =
Pcty_constr (map_loc sub lid, List.map (sub.typ sub) list)
| Tcty_arrow (label, ct, cl) ->
Pcty_arrow (label, sub.typ sub ct, sub.class_type sub cl)
+ | Tcty_open (ovf, _p, lid, _env, e) ->
+ Pcty_open (ovf, lid, sub.class_type sub e)
in
Cty.mk ~loc ~attrs desc