summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlain Frisch <alain@frisch.fr>2014-10-03 13:35:02 +0000
committerAlain Frisch <alain@frisch.fr>2014-10-03 13:35:02 +0000
commitb002e8b22e2438c58eed42fb7a7ce292cb71a87e (patch)
tree00210c87b7d94999c062205d86b1149f910b2c57
parentcf2cdb9fc1305b251fd96d67feb7348c088cd858 (diff)
parent7a21fae1a759f7f93f4bb79f091228fb154a9869 (diff)
Sync with trunk.
git-svn-id: http://caml.inria.fr/svn/ocaml/branches/abstract_intel_emit@15448 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
-rw-r--r--.travis-ci.sh2
-rw-r--r--Changes22
-rw-r--r--Makefile.nt4
-rw-r--r--VERSION2
-rw-r--r--asmrun/backtrace.c51
-rwxr-xr-xboot/ocamlcbin1707828 -> 1712043 bytes
-rwxr-xr-xboot/ocamldepbin525703 -> 529442 bytes
-rwxr-xr-xboot/ocamllexbin251380 -> 252280 bytes
-rw-r--r--byterun/gc_ctrl.c2
-rw-r--r--driver/pparse.ml61
-rw-r--r--driver/pparse.mli9
-rw-r--r--otherlibs/win32unix/createprocess.c2
-rw-r--r--parsing/ast_mapper.ml313
-rw-r--r--parsing/ast_mapper.mli28
-rw-r--r--stdlib/camlinternalFormat.ml59
-rw-r--r--stdlib/gc.mli4
-rw-r--r--testsuite/makefiles/Makefile.several4
-rw-r--r--testsuite/tests/backtrace/Makefile11
-rw-r--r--testsuite/tests/backtrace/backtraces_and_finalizers.ml25
-rw-r--r--testsuite/tests/backtrace/backtraces_and_finalizers.reference1
-rw-r--r--testsuite/tests/formats-transition/invalid_formats.ml4
-rw-r--r--testsuite/tests/typing-modules/aliases.ml.reference33
-rw-r--r--testsuite/typing9
-rw-r--r--toplevel/toploop.ml5
-rw-r--r--toplevel/topmain.ml1
-rw-r--r--typing/ctype.ml63
-rw-r--r--typing/datarepr.ml62
-rw-r--r--typing/datarepr.mli16
-rw-r--r--typing/env.ml56
-rw-r--r--typing/env.mli1
-rw-r--r--typing/includecore.ml20
-rw-r--r--typing/includemod.ml9
-rw-r--r--typing/mtype.ml25
-rw-r--r--typing/subst.ml49
-rw-r--r--typing/typemod.ml192
35 files changed, 651 insertions, 494 deletions
diff --git a/.travis-ci.sh b/.travis-ci.sh
index bee3ad19b..d65fcbc63 100644
--- a/.travis-ci.sh
+++ b/.travis-ci.sh
@@ -8,6 +8,8 @@ i386)
cd camlp4 && ./configure && make && sudo make install
git clone git://github.com/ocaml/opam
cd opam && ./configure && make lib-ext && make && sudo make install
+ git config --global user.email "some@name.com"
+ git config --global user.name "Some Name"
opam init -y -a git://github.com/ocaml/opam-repository
opam install -y oasis
opam pin add -y utop https://github.com/diml/utop
diff --git a/Changes b/Changes
index 3b002c9a2..7306f4f5a 100644
--- a/Changes
+++ b/Changes
@@ -9,8 +9,30 @@ Runtime system:
- PR#6517: use ISO C99 types {,u}int{32,64}_t in preference to our homegrown
types {,u}int{32,64}.
(Xavier Leroy)
+
+Standard library:
+- PR#6577: improve performance of %L, %l, %n, %S, %C format specifiers
+ (Alain Frisch)
+- PR#6585: fix memory leak in win32unix/createprocess.c
+
+Type system:
+- PR#6374: allow "_ t" as a short-hand for "(_, _, ..) t" for n-ary type
+ constructors (Alain Frisch)
+* PR#6465: allow incremental weakening of module aliases (Jacques Garrigue).
+ This is done by adding equations to submodules when expanding aliases.
+ In theory this may be incompatible is some corner cases defining a module
+ type through inference, but no breakage known on published code.
+- PR#6593: Functor application in tests/basic-modules fails after commit 15405
+
+OCaml 4.02.1:
+-------------
+
+- PR#4099: Bug in Makefile.nt: won't stop on error (George Necula)
+- PR#6466: Non-exhaustive matching warning message for open types is confusing
- PR#6529: fix quadratic-time algorithm in Consistbl.extract.
(Xavier Leroy)
+- PR#6554: fix race condition when retrieving backtraces (Jérémie Dimino,
+ Mark Shinwell).
Ocaml 4.02.0:
-------------
diff --git a/Makefile.nt b/Makefile.nt
index 4346cbb20..810251ea2 100644
--- a/Makefile.nt
+++ b/Makefile.nt
@@ -268,7 +268,9 @@ installbyt:
cp expunge $(INSTALL_LIBDIR)/expunge.exe
cp toplevel/topdirs.cmi $(INSTALL_LIBDIR)
cd tools ; $(MAKEREC) install
- for i in $(OTHERLIBRARIES); do $(MAKEREC) -C otherlibs/$$i install; done
+ for i in $(OTHERLIBRARIES); do \
+ $(MAKEREC) -C otherlibs/$$i install || exit $$?; \
+ done
if test -n "$(WITH_OCAMLDOC)"; then (cd ocamldoc; $(MAKEREC) install); \
else :; fi
if test -n "$(WITH_DEBUGGER)"; then (cd debugger; $(MAKEREC) install); \
diff --git a/VERSION b/VERSION
index a61a34c25..e3f03ac20 100644
--- a/VERSION
+++ b/VERSION
@@ -1,4 +1,4 @@
-4.03.0+dev3-2014-08-29
+4.03.0+dev4-2014-09-26
# The version string is the first line of this file.
# It must be in the format described in stdlib/sys.mli
diff --git a/asmrun/backtrace.c b/asmrun/backtrace.c
index 773e22cd2..5eb8600cd 100644
--- a/asmrun/backtrace.c
+++ b/asmrun/backtrace.c
@@ -332,13 +332,37 @@ CAMLprim value caml_get_exception_raw_backtrace(value unit)
{
CAMLparam0();
CAMLlocal1(res);
+ const int tag = 0;
- res = caml_alloc(caml_backtrace_pos, 0);
- if(caml_backtrace_buffer != NULL) {
+ /* Beware: the allocations below may cause finalizers to be run, and another
+ backtrace---possibly of a different length---to be stashed (for example
+ if the finalizer raises then catches an exception). We choose to ignore
+ any such finalizer backtraces and return the original one. */
+
+ if (caml_backtrace_buffer == NULL || caml_backtrace_pos == 0) {
+ res = caml_alloc(0, tag);
+ }
+ else {
+ code_t saved_caml_backtrace_buffer[BACKTRACE_BUFFER_SIZE];
+ int saved_caml_backtrace_pos;
intnat i;
- for(i = 0; i < caml_backtrace_pos; i++)
- Field(res, i) = Val_Descrptr(caml_backtrace_buffer[i]);
+
+ saved_caml_backtrace_pos = caml_backtrace_pos;
+
+ if (saved_caml_backtrace_pos > BACKTRACE_BUFFER_SIZE) {
+ saved_caml_backtrace_pos = BACKTRACE_BUFFER_SIZE;
+ }
+
+ memcpy(saved_caml_backtrace_buffer, caml_backtrace_buffer,
+ saved_caml_backtrace_pos * sizeof(code_t));
+
+ res = caml_alloc(saved_caml_backtrace_pos, tag);
+ for (i = 0; i < saved_caml_backtrace_pos; i++) {
+ /* [Val_Descrptr] always returns an immediate. */
+ Field(res, i) = Val_Descrptr(saved_caml_backtrace_buffer[i]);
+ }
}
+
CAMLreturn(res);
}
@@ -355,19 +379,16 @@ CAMLprim value caml_get_exception_raw_backtrace(value unit)
CAMLprim value caml_get_exception_backtrace(value unit)
{
CAMLparam0();
- CAMLlocal4(arr, raw_slot, slot, res);
+ CAMLlocal3(arr, res, backtrace);
+ intnat i;
- arr = caml_alloc(caml_backtrace_pos, 0);
- if (caml_backtrace_buffer == NULL) {
- Assert(caml_backtrace_pos == 0);
- } else {
- intnat i;
- for(i = 0; i < caml_backtrace_pos; i++) {
- raw_slot = Val_Descrptr(caml_backtrace_buffer[i]);
- slot = caml_convert_raw_backtrace_slot(raw_slot);
- caml_modify(&Field(arr, i), slot);
- }
+ backtrace = caml_get_exception_raw_backtrace(Val_unit);
+
+ arr = caml_alloc(Wosize_val(backtrace), 0);
+ for (i = 0; i < Wosize_val(backtrace); i++) {
+ Store_field(arr, i, caml_convert_raw_backtrace_slot(Field(backtrace, i)));
}
+
res = caml_alloc_small(1, 0); Field(res, 0) = arr; /* Some */
CAMLreturn(res);
}
diff --git a/boot/ocamlc b/boot/ocamlc
index 3a04382c5..8282e0114 100755
--- a/boot/ocamlc
+++ b/boot/ocamlc
Binary files differ
diff --git a/boot/ocamldep b/boot/ocamldep
index e7af3bb6d..bb4b76145 100755
--- a/boot/ocamldep
+++ b/boot/ocamldep
Binary files differ
diff --git a/boot/ocamllex b/boot/ocamllex
index 3c88f8eba..01c4739de 100755
--- a/boot/ocamllex
+++ b/boot/ocamllex
Binary files differ
diff --git a/byterun/gc_ctrl.c b/byterun/gc_ctrl.c
index 7e61f0c1b..1ab099da9 100644
--- a/byterun/gc_ctrl.c
+++ b/byterun/gc_ctrl.c
@@ -321,7 +321,7 @@ CAMLprim value caml_gc_get(value v)
res = caml_alloc_tuple (7);
Store_field (res, 0, Val_long (Wsize_bsize (caml_minor_heap_size))); /* s */
- Store_field (res, 1,Val_long(Wsize_bsize(caml_major_heap_increment)));/* i */
+ Store_field (res, 1, Val_long (caml_major_heap_increment)); /* i */
Store_field (res, 2, Val_long (caml_percent_free)); /* o */
Store_field (res, 3, Val_long (caml_verb_gc)); /* v */
Store_field (res, 4, Val_long (caml_percent_max)); /* O */
diff --git a/driver/pparse.ml b/driver/pparse.ml
index 08b9bc736..4b2553f27 100644
--- a/driver/pparse.ml
+++ b/driver/pparse.ml
@@ -39,6 +39,10 @@ let remove_preprocessed inputfile =
None -> ()
| Some _ -> Misc.remove_file inputfile
+
+(* Note: some of the functions here should go to Ast_mapper instead,
+ which would encapsulate the "binary AST" protocol. *)
+
let write_ast magic ast =
let fn = Filename.temp_file "camlppx" "" in
let oc = open_out_bin fn in
@@ -87,41 +91,34 @@ let read_ast magic fn =
Misc.remove_file fn;
raise exn
-let apply_rewriters ~tool_name magic ast =
- let ctx = Ast_mapper.ppx_context ~tool_name () in
+let rewrite magic ast ppxs =
+ read_ast magic
+ (List.fold_left (apply_rewriter magic) (write_ast magic ast)
+ (List.rev ppxs))
+
+let apply_rewriters_str ?(restore = true) ~tool_name ast =
match !Clflags.all_ppx with
| [] -> ast
| ppxs ->
- let ast =
- if magic = Config.ast_impl_magic_number
- then Obj.magic (Ast_helper.Str.attribute ctx :: (Obj.magic ast))
- else Obj.magic (Ast_helper.Sig.attribute ctx :: (Obj.magic ast))
- in
- let fn =
- List.fold_left (apply_rewriter magic) (write_ast magic ast)
- (List.rev ppxs)
- in
- let ast = read_ast magic fn in
- let open Parsetree in
- if magic = Config.ast_impl_magic_number then
- let ast =
- match Obj.magic ast with
- | {pstr_desc = Pstr_attribute({Location.txt = "ocaml.ppx.context"}, _)}
- :: items ->
- items
- | items -> items
- in
- Obj.magic ast
- else
- let ast =
- match Obj.magic ast with
- | {psig_desc = Psig_attribute({Location.txt = "ocaml.ppx.context"}, _)}
- :: items ->
- items
- | items -> items
- in
- Obj.magic ast
+ let ast = Ast_mapper.add_ppx_context_str ~tool_name ast in
+ let ast = rewrite Config.ast_impl_magic_number ast ppxs in
+ Ast_mapper.drop_ppx_context_str ~restore ast
+let apply_rewriters_sig ?(restore = true) ~tool_name ast =
+ match !Clflags.all_ppx with
+ | [] -> ast
+ | ppxs ->
+ let ast = Ast_mapper.add_ppx_context_sig ~tool_name ast in
+ let ast = rewrite Config.ast_intf_magic_number ast ppxs in
+ Ast_mapper.drop_ppx_context_sig ~restore ast
+
+let apply_rewriters ?restore ~tool_name magic ast =
+ if magic = Config.ast_impl_magic_number then
+ Obj.magic (apply_rewriters_str ?restore ~tool_name (Obj.magic ast))
+ else if magic = Config.ast_intf_magic_number then
+ Obj.magic (apply_rewriters_sig ?restore ~tool_name (Obj.magic ast))
+ else
+ assert false
(* Parse a file or get a dumped syntax tree from it *)
@@ -160,7 +157,7 @@ let file ppf ~tool_name inputfile parse_fun ast_magic =
with x -> close_in ic; raise x
in
close_in ic;
- apply_rewriters ~tool_name ast_magic ast
+ apply_rewriters ~restore:false ~tool_name ast_magic ast
let report_error ppf = function
| CannotRun cmd ->
diff --git a/driver/pparse.mli b/driver/pparse.mli
index d45adf91d..bcff4e781 100644
--- a/driver/pparse.mli
+++ b/driver/pparse.mli
@@ -21,7 +21,14 @@ exception Error of error
val preprocess : string -> string
val remove_preprocessed : string -> unit
val file : formatter -> tool_name:string -> string -> (Lexing.lexbuf -> 'a) -> string -> 'a
-val apply_rewriters : tool_name:string -> string -> 'a -> 'a
+val apply_rewriters: ?restore:bool -> tool_name:string -> string -> 'a -> 'a
+ (** If [restore = true] (the default), cookies set by external rewriters will be
+ kept for later calls. *)
+
+val apply_rewriters_str: ?restore:bool -> tool_name:string -> Parsetree.structure -> Parsetree.structure
+val apply_rewriters_sig: ?restore:bool -> tool_name:string -> Parsetree.signature -> Parsetree.signature
+
+
val report_error : formatter -> error -> unit
diff --git a/otherlibs/win32unix/createprocess.c b/otherlibs/win32unix/createprocess.c
index 0e1e37a24..3858a39b8 100644
--- a/otherlibs/win32unix/createprocess.c
+++ b/otherlibs/win32unix/createprocess.c
@@ -53,9 +53,11 @@ value win_create_process_native(value cmd, value cmdline, value env,
/* Create the process */
if (! CreateProcess(exefile, String_val(cmdline), NULL, NULL,
TRUE, flags, envp, NULL, &si, &pi)) {
+ caml_stat_free(exefile);
win32_maperr(GetLastError());
uerror("create_process", cmd);
}
+ caml_stat_free(exefile);
CloseHandle(pi.hThread);
/* Return the process handle as pseudo-PID
(this is consistent with the wait() emulation in the MSVC C library */
diff --git a/parsing/ast_mapper.ml b/parsing/ast_mapper.ml
index f44b12330..669d01449 100644
--- a/parsing/ast_mapper.ml
+++ b/parsing/ast_mapper.ml
@@ -19,7 +19,6 @@
open Asttypes
-open Longident
open Parsetree
open Ast_helper
open Location
@@ -625,79 +624,170 @@ let attribute_of_warning loc s =
{ loc; txt = "ocaml.ppwarning" },
PStr ([Str.eval ~loc (Exp.constant (Const_string (s, None)))])
+module StringMap = Map.Make(struct
+ type t = string
+ let compare = compare
+end)
+
+let cookies = ref StringMap.empty
+
+let get_cookie k =
+ try Some (StringMap.find k !cookies)
+ with Not_found -> None
+
+let set_cookie k v =
+ cookies := StringMap.add k v !cookies
+
let tool_name_ref = ref "_none_"
let tool_name () = !tool_name_ref
-let restore_ppx_context payload =
- let fields =
- match payload with
+
+module PpxContext = struct
+ open Longident
+ open Asttypes
+ open Ast_helper
+
+ let lid name = { txt = Lident name; loc = Location.none }
+
+ let make_string x = Exp.constant (Const_string (x, None))
+
+ let make_bool x =
+ if x
+ then Exp.construct (lid "true") None
+ else Exp.construct (lid "false") None
+
+ let rec make_list f lst =
+ match lst with
+ | x :: rest ->
+ Exp.construct (lid "::") (Some (Exp.tuple [f x; make_list f rest]))
+ | [] ->
+ Exp.construct (lid "[]") None
+
+ let make_pair f1 f2 (x1, x2) =
+ Exp.tuple [f1 x1; f2 x2]
+
+ let make_option f opt =
+ match opt with
+ | Some x -> Exp.construct (lid "Some") (Some (f x))
+ | None -> Exp.construct (lid "None") None
+
+ let get_cookies () =
+ lid "cookies",
+ make_list (make_pair make_string (fun x -> x))
+ (StringMap.bindings !cookies)
+
+ let mk fields =
+ { txt = "ocaml.ppx.context"; loc = Location.none },
+ Parsetree.PStr [Str.eval (Exp.record fields None)]
+
+ let make ~tool_name () =
+ let fields =
+ [
+ lid "tool_name", make_string tool_name;
+ lid "include_dirs", make_list make_string !Clflags.include_dirs;
+ lid "load_path", make_list make_string !Config.load_path;
+ lid "open_modules", make_list make_string !Clflags.open_modules;
+ lid "for_package", make_option make_string !Clflags.for_package;
+ lid "debug", make_bool !Clflags.debug;
+ get_cookies ()
+ ]
+ in
+ mk fields
+
+ let get_fields = function
| PStr [{pstr_desc = Pstr_eval
({ pexp_desc = Pexp_record (fields, None) }, [])}] ->
fields
| _ ->
raise_errorf "Internal error: invalid [@@@ocaml.ppx.context] syntax"
- in
- let field name payload =
- let rec get_string = function
- | { pexp_desc = Pexp_constant (Const_string (str, None)) } -> str
- | _ ->
- raise_errorf
- "Internal error: invalid [@@@ocaml.ppx.context { %s }] string syntax"
- name
- and get_bool pexp =
- match pexp with
- | {pexp_desc = Pexp_construct ({txt = Longident.Lident "true"}, None)} ->
- true
- | {pexp_desc = Pexp_construct ({txt = Longident.Lident "false"}, None)} ->
- false
- | _ ->
- raise_errorf
- "Internal error: invalid [@@@ocaml.ppx.context { %s }] bool syntax"
- name
- and get_list elem = function
- | {pexp_desc =
- Pexp_construct ({txt = Longident.Lident "::"},
- Some {pexp_desc = Pexp_tuple [exp; rest]}) } ->
- elem exp :: get_list elem rest
- | {pexp_desc =
- Pexp_construct ({txt = Longident.Lident "[]"}, None)} ->
- []
- | _ ->
- raise_errorf
- "Internal error: invalid [@@@ocaml.ppx.context { %s }] list syntax"
- name
- and get_option elem = function
- | { pexp_desc =
- Pexp_construct ({ txt = Longident.Lident "Some" }, Some exp) } ->
- Some (elem exp)
- | { pexp_desc =
- Pexp_construct ({ txt = Longident.Lident "None" }, None) } ->
- None
+
+ let restore fields =
+ let field name payload =
+ let rec get_string = function
+ | { pexp_desc = Pexp_constant (Const_string (str, None)) } -> str
+ | _ ->
+ raise_errorf
+ "Internal error: invalid [@@@ocaml.ppx.context { %s }] string syntax"
+ name
+ and get_bool pexp =
+ match pexp with
+ | {pexp_desc = Pexp_construct ({txt = Longident.Lident "true"}, None)} ->
+ true
+ | {pexp_desc = Pexp_construct ({txt = Longident.Lident "false"}, None)} ->
+ false
+ | _ ->
+ raise_errorf
+ "Internal error: invalid [@@@ocaml.ppx.context { %s }] bool syntax"
+ name
+ and get_list elem = function
+ | {pexp_desc =
+ Pexp_construct ({txt = Longident.Lident "::"},
+ Some {pexp_desc = Pexp_tuple [exp; rest]}) } ->
+ elem exp :: get_list elem rest
+ | {pexp_desc =
+ Pexp_construct ({txt = Longident.Lident "[]"}, None)} ->
+ []
+ | _ ->
+ raise_errorf
+ "Internal error: invalid [@@@ocaml.ppx.context { %s }] list syntax"
+ name
+ and get_pair f1 f2 = function
+ | {pexp_desc = Pexp_tuple [e1; e2]} ->
+ (f1 e1, f2 e2)
+ | _ ->
+ raise_errorf
+ "Internal error: invalid [@@@ocaml.ppx.context { %s }] pair syntax"
+ name
+ and get_option elem = function
+ | { pexp_desc =
+ Pexp_construct ({ txt = Longident.Lident "Some" }, Some exp) } ->
+ Some (elem exp)
+ | { pexp_desc =
+ Pexp_construct ({ txt = Longident.Lident "None" }, None) } ->
+ None
+ | _ ->
+ raise_errorf
+ "Internal error: invalid [@@@ocaml.ppx.context { %s }] option syntax"
+ name
+ in
+ match name with
+ | "tool_name" ->
+ tool_name_ref := get_string payload
+ | "include_dirs" ->
+ Clflags.include_dirs := get_list get_string payload
+ | "load_path" ->
+ Config.load_path := get_list get_string payload
+ | "open_modules" ->
+ Clflags.open_modules := get_list get_string payload
+ | "for_package" ->
+ Clflags.for_package := get_option get_string payload
+ | "debug" ->
+ Clflags.debug := get_bool payload
+ | "cookies" ->
+ let l = get_list (get_pair get_string (fun x -> x)) payload in
+ cookies :=
+ List.fold_left
+ (fun s (k, v) -> StringMap.add k v s) StringMap.empty
+ l
| _ ->
- raise_errorf
- "Internal error: invalid [@@@ocaml.ppx.context { %s }] option syntax"
- name
+ ()
in
- match name with
- | "tool_name" ->
- tool_name_ref := get_string payload
- | "include_dirs" ->
- Clflags.include_dirs := get_list get_string payload
- | "load_path" ->
- Config.load_path := get_list get_string payload
- | "open_modules" ->
- Clflags.open_modules := get_list get_string payload
- | "for_package" ->
- Clflags.for_package := get_option get_string payload
- | "debug" ->
- Clflags.debug := get_bool payload
- | _ ->
- ()
- in
- List.iter (function ({txt=Lident name}, x) -> field name x | _ -> ()) fields
+ List.iter (function ({txt=Lident name}, x) -> field name x | _ -> ()) fields
-let apply ~source ~target mapper =
+ let update_cookies fields =
+ let fields =
+ List.filter
+ (function ({txt=Lident "cookies"}, _) -> false | _ -> true)
+ fields
+ in
+ fields @ [get_cookies ()]
+end
+
+let ppx_context = PpxContext.make
+
+
+let apply_lazy ~source ~target mapper =
let ic = open_in_bin source in
let magic =
really_input_string ic (String.length Config.ast_impl_magic_number)
@@ -711,12 +801,17 @@ let apply ~source ~target mapper =
let implem ast =
try
- begin match ast with
- | {pstr_desc = Pstr_attribute ({txt = "ocaml.ppx.context"}, x)} :: _ ->
- restore_ppx_context x
- | _ -> ()
- end;
- mapper.structure mapper ast
+ let fields, ast =
+ match ast with
+ | {pstr_desc = Pstr_attribute ({txt = "ocaml.ppx.context"}, x)} :: l ->
+ PpxContext.get_fields x, l
+ | _ -> [], ast
+ in
+ PpxContext.restore fields;
+ let mapper = mapper () in
+ let ast = mapper.structure mapper ast in
+ let fields = PpxContext.update_cookies fields in
+ Str.attribute (PpxContext.mk fields) :: ast
with exn ->
match error_of_exn exn with
| Some error ->
@@ -726,12 +821,17 @@ let apply ~source ~target mapper =
in
let iface ast =
try
- begin match ast with
- | {psig_desc = Psig_attribute ({txt = "ocaml.ppx.context"}, x)} :: _ ->
- restore_ppx_context x
- | _ -> ()
- end;
- mapper.signature mapper ast
+ let fields, ast =
+ match ast with
+ | {psig_desc = Psig_attribute ({txt = "ocaml.ppx.context"}, x)} :: l ->
+ PpxContext.get_fields x, l
+ | _ -> [], ast
+ in
+ PpxContext.restore fields;
+ let mapper = mapper () in
+ let ast = mapper.signature mapper ast in
+ let fields = PpxContext.update_cookies fields in
+ Sig.attribute (PpxContext.mk fields) :: ast
with exn ->
match error_of_exn exn with
| Some error ->
@@ -750,19 +850,45 @@ let apply ~source ~target mapper =
output_value oc ast;
close_out oc
+let drop_ppx_context_str ~restore = function
+ | {pstr_desc = Pstr_attribute({Location.txt = "ocaml.ppx.context"}, a)}
+ :: items ->
+ if restore then
+ PpxContext.restore (PpxContext.get_fields a);
+ items
+ | items -> items
+
+let drop_ppx_context_sig ~restore = function
+ | {psig_desc = Psig_attribute({Location.txt = "ocaml.ppx.context"}, a)}
+ :: items ->
+ if restore then
+ PpxContext.restore (PpxContext.get_fields a);
+ items
+ | items -> items
+
+let add_ppx_context_str ~tool_name ast =
+ Ast_helper.Str.attribute (ppx_context ~tool_name ()) :: ast
+
+let add_ppx_context_sig ~tool_name ast =
+ Ast_helper.Sig.attribute (ppx_context ~tool_name ()) :: ast
+
+
+let apply ~source ~target mapper =
+ apply_lazy ~source ~target (fun () -> mapper)
+
let run_main mapper =
try
let a = Sys.argv in
let n = Array.length a in
if n > 2 then
- let mapper =
+ let mapper () =
try mapper (Array.to_list (Array.sub a 1 (n - 3)))
with exn ->
(* PR #6463 *)
let f _ _ = raise exn in
{default_mapper with structure = f; signature = f}
in
- apply ~source:a.(n - 2) ~target:a.(n - 1) mapper
+ apply_lazy ~source:a.(n - 2) ~target:a.(n - 1) mapper
else begin
Printf.eprintf "Usage: %s [extra_args] <infile> <outfile>\n%!"
Sys.executable_name;
@@ -774,38 +900,3 @@ let run_main mapper =
let register_function = ref (fun _name f -> run_main f)
let register name f = !register_function name f
-
-
-let ppx_context ~tool_name () =
- let open Longident in
- let open Asttypes in
- let open Ast_helper in
- let lid name = { txt = Lident name; loc = Location.none } in
- let make_string x = Exp.constant (Const_string (x, None)) in
- let make_bool x =
- if x
- then Exp.construct (lid "true") None
- else Exp.construct (lid "false") None
- in
- let rec make_list f lst =
- match lst with
- | x :: rest ->
- Exp.construct (lid "::") (Some (Exp.tuple [f x; make_list f rest]))
- | [] ->
- Exp.construct (lid "[]") None
- in
- let make_option f opt =
- match opt with
- | Some x -> Exp.construct (lid "Some") (Some (f x))
- | None -> Exp.construct (lid "None") None
- in
- { txt = "ocaml.ppx.context"; loc = Location.none },
- Parsetree.PStr [Str.eval (
- Exp.record ([
- lid "tool_name", make_string tool_name;
- lid "include_dirs", make_list make_string !Clflags.include_dirs;
- lid "load_path", make_list make_string !Config.load_path;
- lid "open_modules", make_list make_string !Clflags.open_modules;
- lid "for_package", make_option make_string !Clflags.for_package;
- lid "debug", make_bool !Clflags.debug;
- ]) None)]
diff --git a/parsing/ast_mapper.mli b/parsing/ast_mapper.mli
index 786c37d6b..5a57b19da 100644
--- a/parsing/ast_mapper.mli
+++ b/parsing/ast_mapper.mli
@@ -134,8 +134,28 @@ val attribute_of_warning: Location.t -> string -> attribute
(** {2 Helper functions to call external mappers} *)
-val ppx_context: tool_name:string -> unit -> Parsetree.attribute
+val add_ppx_context_str: tool_name:string -> Parsetree.structure -> Parsetree.structure
(** Extract information from the current environment and encode it
- into an attribute an attribute which can be prepended to
- signature/structure items of an AST to pass the information to an
- external processor. *)
+ into an attribute which is prepended to the list of structure
+ items in order to pass the information to an external
+ processor. *)
+
+val add_ppx_context_sig: tool_name:string -> Parsetree.signature -> Parsetree.signature
+(** Same as [ad_ppx_context_str] for signatures. *)
+
+val drop_ppx_context_str: restore:bool -> Parsetree.structure -> Parsetree.structure
+(** Drop the ocaml.ppx.context attribute from a structure. If
+ [restore] is true, also restore the associated data in the current
+ process. *)
+
+val drop_ppx_context_sig: restore:bool -> Parsetree.signature -> Parsetree.signature
+(** Same as [drop_ppx_context_str] for signatures. *)
+
+(** {2 Cookies} *)
+
+(** Cookies are used to pass information from a ppx processor to
+ a further invocation of itself, when called from the OCaml
+ toplevel (or other tools that support cookies). *)
+
+val set_cookie: string -> Parsetree.expression -> unit
+val get_cookie: string -> Parsetree.expression option
diff --git a/stdlib/camlinternalFormat.ml b/stdlib/camlinternalFormat.ml
index 5dda3a7fc..7fb82dbe2 100644
--- a/stdlib/camlinternalFormat.ml
+++ b/stdlib/camlinternalFormat.ml
@@ -1266,10 +1266,15 @@ let fix_int_precision prec str =
(* Escape a string according to the OCaml lexing convention. *)
let string_to_caml_string str =
- String.concat (String.escaped str) ["\""; "\""]
-
-(* Generate the format_int first argument from an int_conv. *)
-let format_of_iconv iconv = match iconv with
+ let str = String.escaped str in
+ let l = String.length str in
+ let res = Bytes.make (l + 2) '\"' in
+ String.unsafe_blit str 0 res 1 l;
+ Bytes.unsafe_to_string res
+
+(* Generate the format_int/int32/nativeint/int64 first argument
+ from an int_conv. *)
+let format_of_iconv = function
| Int_d -> "%d" | Int_pd -> "%+d" | Int_sd -> "% d"
| Int_i -> "%i" | Int_pi -> "%+i" | Int_si -> "% i"
| Int_x -> "%x" | Int_Cx -> "%#x"
@@ -1277,17 +1282,29 @@ let format_of_iconv iconv = match iconv with
| Int_o -> "%o" | Int_Co -> "%#o"
| Int_u -> "%u"
-(* Generate the format_int32, format_nativeint and format_int64 first
- argument from an int_conv. *)
-let format_of_aconv iconv c =
- let seps = match iconv with
- | Int_d -> ["%";"d"] | Int_pd -> ["%+";"d"] | Int_sd -> ["% ";"d"]
- | Int_i -> ["%";"i"] | Int_pi -> ["%+";"i"] | Int_si -> ["% ";"i"]
- | Int_x -> ["%";"x"] | Int_Cx -> ["%#";"x"]
- | Int_X -> ["%";"X"] | Int_CX -> ["%#";"X"]
- | Int_o -> ["%";"o"] | Int_Co -> ["%#";"o"]
- | Int_u -> ["%";"u"]
- in String.concat (String.make 1 c) seps
+let format_of_iconvL = function
+ | Int_d -> "%Ld" | Int_pd -> "%+Ld" | Int_sd -> "% Ld"
+ | Int_i -> "%Li" | Int_pi -> "%+Li" | Int_si -> "% Li"
+ | Int_x -> "%Lx" | Int_Cx -> "%#Lx"
+ | Int_X -> "%LX" | Int_CX -> "%#LX"
+ | Int_o -> "%Lo" | Int_Co -> "%#Lo"
+ | Int_u -> "%Lu"
+
+let format_of_iconvl = function
+ | Int_d -> "%ld" | Int_pd -> "%+ld" | Int_sd -> "% ld"
+ | Int_i -> "%li" | Int_pi -> "%+li" | Int_si -> "% li"
+ | Int_x -> "%lx" | Int_Cx -> "%#lx"
+ | Int_X -> "%lX" | Int_CX -> "%#lX"
+ | Int_o -> "%lo" | Int_Co -> "%#lo"
+ | Int_u -> "%lu"
+
+let format_of_iconvn = function
+ | Int_d -> "%nd" | Int_pd -> "%+nd" | Int_sd -> "% nd"
+ | Int_i -> "%ni" | Int_pi -> "%+ni" | Int_si -> "% ni"
+ | Int_x -> "%nx" | Int_Cx -> "%#nx"
+ | Int_X -> "%nX" | Int_CX -> "%#nX"
+ | Int_o -> "%no" | Int_Co -> "%#no"
+ | Int_u -> "%nu"
(* Generate the format_float first argument form a float_conv. *)
let format_of_fconv fconv prec =
@@ -1302,9 +1319,9 @@ let format_of_fconv fconv prec =
(* Convert an integer to a string according to a conversion. *)
let convert_int iconv n = format_int (format_of_iconv iconv) n
-let convert_int32 iconv n = format_int32 (format_of_aconv iconv 'l') n
-let convert_nativeint iconv n = format_nativeint (format_of_aconv iconv 'n') n
-let convert_int64 iconv n = format_int64 (format_of_aconv iconv 'L') n
+let convert_int32 iconv n = format_int32 (format_of_iconvl iconv) n
+let convert_nativeint iconv n = format_nativeint (format_of_iconvn iconv) n
+let convert_int64 iconv n = format_int64 (format_of_iconvL iconv) n
(* Convert a float to string. *)
(* Fix special case of "OCaml float format". *)
@@ -1327,7 +1344,11 @@ let convert_float fconv prec x =
(* Convert a char to a string according to the OCaml lexical convention. *)
let format_caml_char c =
- String.concat (Char.escaped c) ["'"; "'"]
+ let str = Char.escaped c in
+ let l = String.length str in
+ let res = Bytes.make (l + 2) '\'' in
+ String.unsafe_blit str 0 res 1 l;
+ Bytes.unsafe_to_string res
(* Convert a format type to string *)
let string_of_fmtty fmtty =
diff --git a/stdlib/gc.mli b/stdlib/gc.mli
index 8cd2a719a..f86a1e687 100644
--- a/stdlib/gc.mli
+++ b/stdlib/gc.mli
@@ -83,7 +83,7 @@ type stat =
type control =
{ mutable minor_heap_size : int;
(** The size (in words) of the minor heap. Changing
- this parameter will trigger a minor collection. Default: 32k. *)
+ this parameter will trigger a minor collection. Default: 256k. *)
mutable major_heap_increment : int;
(** How much to add to the major heap when increasing it. If this
@@ -131,7 +131,7 @@ type control =
mutable stack_limit : int;
(** The maximum size of the stack (in words). This is only
relevant to the byte-code runtime, as the native code runtime
- uses the operating system's stack. Default: 256k. *)
+ uses the operating system's stack. Default: 1024k. *)
mutable allocation_policy : int;
(** The policy used for allocating in the heap. Possible
diff --git a/testsuite/makefiles/Makefile.several b/testsuite/makefiles/Makefile.several
index 3482e3af3..5eb44c393 100644
--- a/testsuite/makefiles/Makefile.several
+++ b/testsuite/makefiles/Makefile.several
@@ -84,7 +84,9 @@ run-all:
run-file:
@printf " $(DESC)"
@rm -f program program.exe
- @$(COMP) $(COMPFLAGS) $(FILE) -o program$(EXE)
+ echo XXXX
+ $(COMP) $(COMPFLAGS) $(FILE) -o program$(EXE)
+ echo YYYY
@F="`basename $(FILE) .ml`"; \
if [ -f $$F.runner ]; then \
RUNTIME="$(RUNTIME)" sh $$F.runner; \
diff --git a/testsuite/tests/backtrace/Makefile b/testsuite/tests/backtrace/Makefile
index 1ca390f94..33ca1ed8b 100644
--- a/testsuite/tests/backtrace/Makefile
+++ b/testsuite/tests/backtrace/Makefile
@@ -16,6 +16,7 @@ EXECNAME=program$(EXE)
ABCDFILES=backtrace.ml
OTHERFILES=backtrace2.ml raw_backtrace.ml \
backtrace_deprecated.ml backtrace_slots.ml
+OTHERFILESNOINLINING=backtraces_and_finalizers.ml
default:
$(MAKE) byte
@@ -69,6 +70,16 @@ native:
>$$F.native.result 2>&1; \
$(DIFF) $$F.reference $$F.native.result >/dev/null \
&& echo " => passed" || echo " => failed"; \
+ done;
+ @for file in $(OTHERFILESNOINLINING); do \
+ rm -f program program.exe; \
+ $(OCAMLOPT) -inline 0 -g -o $(EXECNAME) $$file; \
+ printf " ... testing '$$file' with ocamlopt:"; \
+ F="`basename $$file .ml`"; \
+ (OCAMLRUNPARAM=b=1 ./$(EXECNAME) $$arg || true) \
+ >$$F.native.result 2>&1; \
+ $(DIFF) $$F.reference $$F.native.result >/dev/null \
+ && echo " => passed" || echo " => failed"; \
done
.PHONY: promote
diff --git a/testsuite/tests/backtrace/backtraces_and_finalizers.ml b/testsuite/tests/backtrace/backtraces_and_finalizers.ml
new file mode 100644
index 000000000..22acf1af8
--- /dev/null
+++ b/testsuite/tests/backtrace/backtraces_and_finalizers.ml
@@ -0,0 +1,25 @@
+let () = Printexc.record_backtrace true
+
+let finaliser _ = try raise Exit with _ -> ()
+
+let create () =
+ let x = ref () in
+ Gc.finalise finaliser x;
+ x
+
+let f () = raise Exit
+
+let () =
+ let minor_size = (Gc.get ()).Gc.minor_heap_size in
+ for i = 1 to 100 do
+ Gc.minor ();
+ try
+ ignore (create () : unit ref);
+ f ()
+ with _ ->
+ for i = 1 to minor_size / 2 - 1 do
+ ignore (ref ())
+ done;
+ ignore (Printexc.get_backtrace () : string)
+ done;
+ Printf.printf "ok\n"
diff --git a/testsuite/tests/backtrace/backtraces_and_finalizers.reference b/testsuite/tests/backtrace/backtraces_and_finalizers.reference
new file mode 100644
index 000000000..9766475a4
--- /dev/null
+++ b/testsuite/tests/backtrace/backtraces_and_finalizers.reference
@@ -0,0 +1 @@
+ok
diff --git a/testsuite/tests/formats-transition/invalid_formats.ml b/testsuite/tests/formats-transition/invalid_formats.ml
new file mode 100644
index 000000000..71f796b04
--- /dev/null
+++ b/testsuite/tests/formats-transition/invalid_formats.ml
@@ -0,0 +1,4 @@
+(* Empty file added to create a conflict with branch 4.02 because
+ the test only makes sense on 4.02.x and will not work on 4.03+
+ When merging, don't forget to remove also the .ml.reference file.
+ *)
diff --git a/testsuite/tests/typing-modules/aliases.ml.reference b/testsuite/tests/typing-modules/aliases.ml.reference
index 2bb3231de..e6611acbb 100644
--- a/testsuite/tests/typing-modules/aliases.ml.reference
+++ b/testsuite/tests/typing-modules/aliases.ml.reference
@@ -368,19 +368,7 @@ Error: Unbound module type A
module K : sig module E = B module N = E.O end
# val x : K.N.t = "foo"
# module M : sig type t = A module B : sig type u = B end end
-# Characters 53-54:
- module P : sig type t = M.t = A module B = M.B end = M;; (* should be ok *)
- ^
-Error: Signature mismatch:
- Modules do not match:
- sig type t = M.t = A module B : sig type u = M.B.u = B end end
- is not included in
- sig type t = M.t = A module B = M.B end
- In module B:
- Modules do not match:
- sig type u = M.B.u = B end
- is not included in
- (module M.B)
+# module P : sig type t = M.t = A module B = M.B end
# module P : sig type t = M.t = A module B = M.B end
# module type S = sig module M : sig module P : sig end end module Q = M end
# module type S =
@@ -393,22 +381,5 @@ Error: Signature mismatch:
module M : sig module N : sig end module P : sig end end
module Q = M
end
-# Characters 16-17:
- module R' : S = R;; (* should be ok *)
- ^
-Error: Signature mismatch:
- Modules do not match:
- sig
- module M : sig module N : sig end module P : sig end end
- module Q = M
- end
- is not included in
- S
- In module Q:
- Modules do not match:
- sig module N : sig end module P : sig end end
- is not included in
- sig module N = M.N module P = M.P end
- In module Q.N:
- Modules do not match: sig end is not included in (module M.N)
+# module R' : S
#
diff --git a/testsuite/typing b/testsuite/typing
index cb953d6ac..4357fdf3c 100644
--- a/testsuite/typing
+++ b/testsuite/typing
@@ -1,3 +1,12 @@
+tests/basic
+tests/basic-float
+tests/basic-io
+tests/basic-io-2
+tests/basic-manyargs
+tests/basic-modules
+tests/basic-more
+tests/basic-multdef
+tests/basic-private
tests/typing-extensions
tests/typing-fstclassmod
tests/typing-gadts
diff --git a/toplevel/toploop.ml b/toplevel/toploop.ml
index cf62137c2..220d75967 100644
--- a/toplevel/toploop.ml
+++ b/toplevel/toploop.ml
@@ -327,7 +327,10 @@ let phrase ppf phr =
let phr =
match phr with
| Ptop_def str ->
- Ptop_def (Pparse.apply_rewriters ~tool_name:"ocaml" ast_impl_magic_number str)
+ let str =
+ Pparse.apply_rewriters_str ~restore:true ~tool_name:"ocaml" str
+ in
+ Ptop_def str
| phr -> phr
in
if !Clflags.dump_parsetree then Printast.top_phrase ppf phr;
diff --git a/toplevel/topmain.ml b/toplevel/topmain.ml
index d1dbeca9d..0d8f2d4c2 100644
--- a/toplevel/topmain.ml
+++ b/toplevel/topmain.ml
@@ -41,6 +41,7 @@ let file_argument name =
let newargs = Array.sub Sys.argv !Arg.current
(Array.length Sys.argv - !Arg.current)
in
+ Compenv.readenv ppf Before_link;
if prepare ppf && Toploop.run_script ppf name newargs
then exit 0
else exit 2
diff --git a/typing/ctype.ml b/typing/ctype.ml
index 78852a439..a7d31e7c8 100644
--- a/typing/ctype.ml
+++ b/typing/ctype.ml
@@ -775,7 +775,7 @@ let rec update_level env level ty =
if level < get_level env p then raise (Unify [(ty, newvar2 level)]);
iter_type_expr (update_level env level) ty
end
- | Tpackage (p, nl, tl) when level < get_level env p ->
+ | Tpackage (p, nl, tl) when level < Path.binding_time p ->
let p' = normalize_package_path env p in
if Path.same p p' then raise (Unify [(ty, newvar2 level)]);
log_type ty; ty.desc <- Tpackage (p', nl, tl);
@@ -1185,26 +1185,31 @@ let instance_parameterized_type_2 sch_args sch_lst sch =
cleanup_types ();
(ty_args, ty_lst, ty)
+let map_kind f = function
+ | Type_abstract -> Type_abstract
+ | Type_open -> Type_open
+ | Type_variant cl ->
+ Type_variant (
+ List.map
+ (fun c ->
+ {c with
+ cd_args = List.map f c.cd_args;
+ cd_res = may_map f c.cd_res
+ })
+ cl)
+ | Type_record (fl, rr) ->
+ Type_record (
+ List.map
+ (fun l ->
+ {l with ld_type = f l.ld_type}
+ ) fl, rr)
+
+
let instance_declaration decl =
let decl =
{decl with type_params = List.map simple_copy decl.type_params;
type_manifest = may_map simple_copy decl.type_manifest;
- type_kind = match decl.type_kind with
- | Type_abstract -> Type_abstract
- | Type_variant cl ->
- Type_variant (
- List.map
- (fun c ->
- {c with cd_args=List.map simple_copy c.cd_args;
- cd_res=may_map simple_copy c.cd_res})
- cl)
- | Type_record (fl, rr) ->
- Type_record (
- List.map
- (fun l ->
- {l with ld_type = copy l.ld_type}
- ) fl, rr)
- | Type_open -> Type_open
+ type_kind = map_kind simple_copy decl.type_kind;
}
in
cleanup_types ();
@@ -4325,29 +4330,7 @@ let nondep_type_decl env mid id is_covariant decl =
try
let params = List.map (nondep_type_rec env mid) decl.type_params in
let tk =
- try match decl.type_kind with
- Type_abstract ->
- Type_abstract
- | Type_variant cstrs ->
- Type_variant
- (List.map
- (fun c ->
- {c with
- cd_args = List.map (nondep_type_rec env mid) c.cd_args;
- cd_res = may_map (nondep_type_rec env mid) c.cd_res;
- }
- )
- cstrs)
- | Type_record(lbls, rep) ->
- Type_record
- (List.map
- (fun l ->
- {l with ld_type = nondep_type_rec env mid l.ld_type}
- )
- lbls,
- rep)
- | Type_open ->
- Type_open
+ try map_kind (nondep_type_rec env mid) decl.type_kind
with Not_found when is_covariant -> Type_abstract
and tm =
try match decl.type_manifest with
diff --git a/typing/datarepr.ml b/typing/datarepr.ml
index faeb48f0a..4922cbb0d 100644
--- a/typing/datarepr.ml
+++ b/typing/datarepr.ml
@@ -39,7 +39,21 @@ let free_vars ty =
unmark_type ty;
!ret
-let constructor_descrs ty_res cstrs priv =
+let newgenconstr path tyl = newgenty (Tconstr (path, tyl, ref Mnil))
+
+let constructor_args cd_args cd_res =
+ let arg_vars_set = free_vars (newgenty (Ttuple cd_args)) in
+ let existentials =
+ match cd_res with
+ | None -> []
+ | Some type_ret ->
+ let res_vars = free_vars type_ret in
+ TypeSet.elements (TypeSet.diff arg_vars_set res_vars)
+ in
+ existentials, cd_args
+
+let constructor_descrs ty_path decl cstrs =
+ let ty_res = newgenconstr ty_path decl.type_params in
let num_consts = ref 0 and num_nonconsts = ref 0 and num_normal = ref 0 in
List.iter
(fun {cd_args; cd_res; _} ->
@@ -60,25 +74,20 @@ let constructor_descrs ty_res cstrs priv =
describe_constructors (idx_const+1) idx_nonconst rem)
| _ -> (Cstr_block idx_nonconst,
describe_constructors idx_const (idx_nonconst+1) rem) in
- let existentials =
- match cd_res with
- | None -> []
- | Some type_ret ->
- let res_vars = free_vars type_ret in
- let arg_vars = free_vars (newgenty (Ttuple cd_args)) in
- TypeSet.elements (TypeSet.diff arg_vars res_vars)
+ let existentials, cstr_args =
+ constructor_args cd_args cd_res
in
let cstr =
{ cstr_name = Ident.name cd_id;
cstr_res = ty_res;
cstr_existentials = existentials;
- cstr_args = cd_args;
- cstr_arity = List.length cd_args;
+ cstr_args;
+ cstr_arity = List.length cstr_args;
cstr_tag = tag;
cstr_consts = !num_consts;
cstr_nonconsts = !num_nonconsts;
cstr_normal = !num_normal;
- cstr_private = priv;
+ cstr_private = decl.type_private;
cstr_generalized = cd_res <> None;
cstr_loc = cd_loc;
cstr_attributes = cd_attributes;
@@ -90,24 +99,17 @@ let extension_descr path_ext ext =
let ty_res =
match ext.ext_ret_type with
Some type_ret -> type_ret
- | None ->
- newgenty (Tconstr(ext.ext_type_path, ext.ext_type_params, ref Mnil))
+ | None -> newgenconstr ext.ext_type_path ext.ext_type_params
in
- let tag = Cstr_extension(path_ext, ext.ext_args = []) in
- let existentials =
- match ext.ext_ret_type with
- | None -> []
- | Some type_ret ->
- let ret_vars = free_vars type_ret in
- let arg_vars = free_vars (newgenty (Ttuple ext.ext_args)) in
- TypeSet.elements (TypeSet.diff arg_vars ret_vars)
+ let existentials, cstr_args =
+ constructor_args ext.ext_args ext.ext_ret_type
in
{ cstr_name = Path.last path_ext;
cstr_res = ty_res;
cstr_existentials = existentials;
- cstr_args = ext.ext_args;
- cstr_arity = List.length ext.ext_args;
- cstr_tag = tag;
+ cstr_args;
+ cstr_arity = List.length cstr_args;
+ cstr_tag = Cstr_extension(path_ext, cstr_args = []);
cstr_consts = -1;
cstr_nonconsts = -1;
cstr_private = ext.ext_private;
@@ -164,3 +166,15 @@ let rec find_constr tag num_const num_nonconst = function
let find_constr_by_tag tag cstrlist =
find_constr tag 0 0 cstrlist
+
+let constructors_of_type ty_path decl =
+ match decl.type_kind with
+ | Type_variant cstrs -> constructor_descrs ty_path decl cstrs
+ | Type_record _ | Type_abstract | Type_open -> []
+
+let labels_of_type ty_path decl =
+ match decl.type_kind with
+ | Type_record(labels, rep) ->
+ label_descrs (newgenconstr ty_path decl.type_params)
+ labels rep decl.type_private
+ | Type_variant _ | Type_abstract | Type_open -> []
diff --git a/typing/datarepr.mli b/typing/datarepr.mli
index 8e298debd..d56446a24 100644
--- a/typing/datarepr.mli
+++ b/typing/datarepr.mli
@@ -13,18 +13,18 @@
(* Compute constructor and label descriptions from type declarations,
determining their representation. *)
-open Asttypes
open Types
-val constructor_descrs:
- type_expr -> constructor_declaration list ->
- private_flag -> (Ident.t * constructor_description) list
val extension_descr:
Path.t -> extension_constructor -> constructor_description
-val label_descrs:
- type_expr -> label_declaration list ->
- record_representation -> private_flag ->
- (Ident.t * label_description) list
+
+val labels_of_type:
+ Path.t -> type_declaration ->
+ (Ident.t * label_description) list
+val constructors_of_type:
+ Path.t -> type_declaration ->
+ (Ident.t * constructor_description) list
+
exception Constr_not_found
diff --git a/typing/env.ml b/typing/env.ml
index a8c6de1a5..5655197a9 100644
--- a/typing/env.ml
+++ b/typing/env.ml
@@ -293,7 +293,7 @@ let current_unit = ref ""
type pers_struct =
{ ps_name: string;
- ps_sig: signature;
+ ps_sig: signature Lazy.t;
ps_comps: module_components;
ps_crcs: (string * Digest.t option) list;
mutable ps_crcs_checked: bool;
@@ -348,7 +348,7 @@ let read_pers_struct modname filename =
(Mty_signature sign)
in
let ps = { ps_name = name;
- ps_sig = sign;
+ ps_sig = lazy (Subst.signature Subst.identity sign);
ps_comps = comps;
ps_crcs = crcs;
ps_filename = filename;
@@ -489,7 +489,7 @@ let find_module ~alias path env =
with Not_found ->
if Ident.persistent id then
let ps = find_pers_struct (Ident.name id) in
- md (Mty_signature(ps.ps_sig))
+ md (Mty_signature(Lazy.force ps.ps_sig))
else raise Not_found
end
| Pdot(p, s, pos) ->
@@ -1069,28 +1069,6 @@ let rec scrape_alias env ?path mty =
let scrape_alias env mty = scrape_alias env mty
-(* Compute constructor descriptions *)
-
-let constructors_of_type ty_path decl =
- let handle_variants cstrs =
- Datarepr.constructor_descrs
- (newgenty (Tconstr(ty_path, decl.type_params, ref Mnil)))
- cstrs decl.type_private
- in
- match decl.type_kind with
- | Type_variant cstrs -> handle_variants cstrs
- | Type_record _ | Type_abstract | Type_open -> []
-
-(* Compute label descriptions *)
-
-let labels_of_type ty_path decl =
- match decl.type_kind with
- Type_record(labels, rep) ->
- Datarepr.label_descrs
- (newgenty (Tconstr(ty_path, decl.type_params, ref Mnil)))
- labels rep decl.type_private
- | Type_variant _ | Type_abstract | Type_open -> []
-
(* Given a signature and a root path, prefix all idents in the signature
by the root path and build the corresponding substitution. *)
@@ -1209,8 +1187,10 @@ and components_of_module_maker (env, sub, path, mty) =
end
| Sig_type(id, decl, _) ->
let decl' = Subst.type_declaration sub decl in
- let constructors = List.map snd (constructors_of_type path decl') in
- let labels = List.map snd (labels_of_type path decl') in
+ let constructors =
+ List.map snd (Datarepr.constructors_of_type path decl') in
+ let labels =
+ List.map snd (Datarepr.labels_of_type path decl') in
c.comp_types <-
Tbl.add (Ident.name id)
((decl', (constructors, labels)), nopos)
@@ -1307,8 +1287,8 @@ and store_type ~check slot id path info env renv =
if check then
check_usage loc id (fun s -> Warnings.Unused_type_declaration s)
type_declarations;
- let constructors = constructors_of_type path info in
- let labels = labels_of_type path info in
+ let constructors = Datarepr.constructors_of_type path info in
+ let labels = Datarepr.labels_of_type path info in
let descrs = (List.map snd constructors, List.map snd labels) in
if check && not loc.Location.loc_ghost &&
@@ -1435,8 +1415,7 @@ let _ =
(* Insertion of bindings by identifier *)
-let add_functor_arg ?(arg=false) id env =
- if not arg then env else
+let add_functor_arg id env =
{env with
functor_args = Ident.add id () env.functor_args;
summary = Env_functor_arg (env.summary, id)}
@@ -1450,14 +1429,14 @@ let add_type ~check id info env =
and add_extension ~check id ext env =
store_extension ~check None id (Pident id) ext env env
-and add_module_declaration ?arg id md env =
+and add_module_declaration ?(arg=false) id md env =
let path =
(*match md.md_type with
Mty_alias path -> normalize_path env path
| _ ->*) Pident id
in
let env = store_module None id path md env env in
- add_functor_arg ?arg id env
+ if arg then add_functor_arg id env else env
and add_modtype id info env =
store_modtype None id (Pident id) info env env
@@ -1508,7 +1487,7 @@ let add_item comp env =
Sig_value(id, decl) -> add_value id decl env
| Sig_type(id, decl, _) -> add_type ~check:false id decl env
| Sig_typext(id, ext, _) -> add_extension ~check:false id ext env
- | Sig_module(id, md, _) -> add_module_declaration id md env
+ | Sig_module(id, md, _) -> add_module_declaration id md env
| Sig_modtype(id, decl) -> add_modtype id decl env
| Sig_class(id, decl, _) -> add_class id decl env
| Sig_class_type(id, decl, _) -> add_cltype id decl env
@@ -1553,7 +1532,8 @@ let open_signature slot root sg env0 =
let open_pers_signature name env =
let ps = find_pers_struct name in
- open_signature None (Pident(Ident.create_persistent name)) ps.ps_sig env
+ open_signature None (Pident(Ident.create_persistent name))
+ (Lazy.force ps.ps_sig) env
let open_signature ?(loc = Location.none) ?(toplevel = false) ovf root sg env =
if not toplevel && ovf = Asttypes.Fresh && not loc.Location.loc_ghost
@@ -1590,7 +1570,7 @@ let open_signature ?(loc = Location.none) ?(toplevel = false) ovf root sg env =
let read_signature modname filename =
let ps = read_pers_struct modname filename in
check_consistency ps;
- ps.ps_sig
+ Lazy.force ps.ps_sig
(* Return the CRC of the interface of the given compilation unit *)
@@ -1636,7 +1616,7 @@ let save_signature_with_imports sg modname filename imports =
(Pident(Ident.create_persistent modname)) (Mty_signature sg) in
let ps =
{ ps_name = modname;
- ps_sig = sg;
+ ps_sig = lazy (Subst.signature Subst.identity sg);
ps_comps = comps;
ps_crcs = (cmi.cmi_name, Some crc) :: imports;
ps_filename = filename;
@@ -1710,7 +1690,7 @@ let fold_modules f lid env acc =
None -> acc
| Some ps ->
f name (Pident(Ident.create_persistent name))
- (md (Mty_signature ps.ps_sig)) acc)
+ (md (Mty_signature (Lazy.force ps.ps_sig))) acc)
persistent_structures
acc
| Some l ->
diff --git a/typing/env.mli b/typing/env.mli
index ed2f6f1c5..4ab08e83a 100644
--- a/typing/env.mli
+++ b/typing/env.mli
@@ -61,6 +61,7 @@ val find_type_expansion_opt:
(* Find the manifest type information associated to a type for the sake
of the compiler's type-based optimisations. *)
val find_modtype_expansion: Path.t -> t -> module_type
+val add_functor_arg: Ident.t -> t -> t
val is_functor_arg: Path.t -> t -> bool
val normalize_path: Location.t option -> t -> Path.t -> Path.t
(* Normalize the path to a concrete value or module.
diff --git a/typing/includecore.ml b/typing/includecore.ml
index 88fad1e5b..ee247adad 100644
--- a/typing/includecore.ml
+++ b/typing/includecore.ml
@@ -154,7 +154,7 @@ let report_type_mismatch first second decl ppf =
if err = Manifest then () else
Format.fprintf ppf "@ %a." (report_type_mismatch0 first second decl) err)
-let rec compare_variants env decl1 decl2 n cstrs1 cstrs2 =
+let rec compare_variants env params1 params2 n cstrs1 cstrs2 =
match cstrs1, cstrs2 with
[], [] -> []
| [], c::_ -> [Field_missing (true, c.Types.cd_id)]
@@ -173,15 +173,14 @@ let rec compare_variants env decl1 decl2 n cstrs1 cstrs2 =
| _ ->
if Misc.for_all2
(fun ty1 ty2 ->
- Ctype.equal env true (ty1::decl1.type_params)
- (ty2::decl2.type_params))
+ Ctype.equal env true (ty1::params1) (ty2::params2))
(arg1) (arg2)
then
- compare_variants env decl1 decl2 (n+1) rem1 rem2
+ compare_variants env params1 params2 (n+1) rem1 rem2
else [Field_type cstr1]
-let rec compare_records env decl1 decl2 n labels1 labels2 =
+let rec compare_records env params1 params2 n labels1 labels2 =
match labels1, labels2 with
[], [] -> []
| [], l::_ -> [Field_missing (true, l.ld_id)]
@@ -191,9 +190,9 @@ let rec compare_records env decl1 decl2 n labels1 labels2 =
if Ident.name lab1 <> Ident.name lab2
then [Field_names (n, lab1, lab2)]
else if mut1 <> mut2 then [Field_mutable lab1] else
- if Ctype.equal env true (arg1::decl1.type_params)
- (arg2::decl2.type_params)
- then compare_records env decl1 decl2 (n+1) rem1 rem2
+ if Ctype.equal env true (arg1::params1)
+ (arg2::params2)
+ then compare_records env params1 params2 (n+1) rem1 rem2
else [Field_type lab1]
let type_declarations ?(equality = false) env name decl1 id decl2 =
@@ -215,9 +214,10 @@ let type_declarations ?(equality = false) env name decl1 id decl2 =
in
mark cstrs1 usage name decl1;
if equality then mark cstrs2 Env.Positive (Ident.name id) decl2;
- compare_variants env decl1 decl2 1 cstrs1 cstrs2
+ compare_variants env decl1.type_params decl2.type_params 1 cstrs1 cstrs2
| (Type_record(labels1,rep1), Type_record(labels2,rep2)) ->
- let err = compare_records env decl1 decl2 1 labels1 labels2 in
+ let err = compare_records env decl1.type_params decl2.type_params
+ 1 labels1 labels2 in
if err <> [] || rep1 = rep2 then err else
[Record_representation (rep2 = Record_float)]
| (Type_open, Type_open) -> []
diff --git a/typing/includemod.ml b/typing/includemod.ml
index 223214f36..3eb26fbd6 100644
--- a/typing/includemod.ml
+++ b/typing/includemod.ml
@@ -379,9 +379,11 @@ and signature_components env cxt subst = function
extension_constructors env cxt subst id1 ext1 ext2;
(pos, Tcoerce_none) :: signature_components env cxt subst rem
| (Sig_module(id1, mty1, _), Sig_module(id2, mty2, _), pos) :: rem ->
+ let p1 = Pident id1 in
let cc =
modtypes env (Module id1::cxt) subst
- (Mtype.strengthen env mty1.md_type (Pident id1)) mty2.md_type in
+ (Mtype.strengthen (Env.add_functor_arg id1 env) mty1.md_type p1)
+ mty2.md_type in
(pos, cc) :: signature_components env cxt subst rem
| (Sig_modtype(id1, info1), Sig_modtype(id2, info2), pos) :: rem ->
modtype_infos env cxt subst id1 info1 info2;
@@ -418,7 +420,10 @@ and check_modtype_equiv env cxt mty1 mty2 =
modtypes env cxt Subst.identity mty2 mty1)
with
(Tcoerce_none, Tcoerce_none) -> ()
- | (_, _) -> raise(Error [cxt, env, Modtype_permutation])
+ | (c1, c2) ->
+ (* Format.eprintf "@[c1 = %a@ c2 = %a@]@."
+ print_coercion c1 print_coercion c2; *)
+ raise(Error [cxt, env, Modtype_permutation])
(* Simplified inclusion check between module types (for Env) *)
diff --git a/typing/mtype.ml b/typing/mtype.ml
index dd766a913..19253a10e 100644
--- a/typing/mtype.ml
+++ b/typing/mtype.ml
@@ -33,18 +33,18 @@ let freshen mty =
let rec strengthen env mty p =
match scrape env mty with
Mty_signature sg ->
- Mty_signature(strengthen_sig env sg p)
+ Mty_signature(strengthen_sig env sg p 0)
| Mty_functor(param, arg, res)
when !Clflags.applicative_functors && Ident.name param <> "*" ->
Mty_functor(param, arg, strengthen env res (Papply(p, Pident param)))
| mty ->
mty
-and strengthen_sig env sg p =
+and strengthen_sig env sg p pos =
match sg with
[] -> []
| (Sig_value(id, desc) as sigelt) :: rem ->
- sigelt :: strengthen_sig env rem p
+ sigelt :: strengthen_sig env rem p (pos+1)
| Sig_type(id, decl, rs) :: rem ->
let newdecl =
match decl.type_manifest, decl.type_private, decl.type_kind with
@@ -59,13 +59,18 @@ and strengthen_sig env sg p =
else
{ decl with type_manifest = manif }
in
- Sig_type(id, newdecl, rs) :: strengthen_sig env rem p
+ Sig_type(id, newdecl, rs) :: strengthen_sig env rem p pos
| (Sig_typext(id, ext, es) as sigelt) :: rem ->
- sigelt :: strengthen_sig env rem p
+ sigelt :: strengthen_sig env rem p (pos+1)
| Sig_module(id, md, rs) :: rem ->
- let str = strengthen_decl env md (Pdot(p, Ident.name id, nopos)) in
+ let str =
+ if Env.is_functor_arg p env then
+ strengthen_decl env md (Pdot(p, Ident.name id, pos))
+ else
+ {md with md_type = Mty_alias (Pdot(p, Ident.name id, pos))}
+ in
Sig_module(id, str, rs)
- :: strengthen_sig (Env.add_module_declaration id md env) rem p
+ :: strengthen_sig (Env.add_module_declaration id md env) rem p (pos+1)
(* Need to add the module in case it defines manifest module types *)
| Sig_modtype(id, decl) :: rem ->
let newdecl =
@@ -76,12 +81,12 @@ and strengthen_sig env sg p =
decl
in
Sig_modtype(id, newdecl) ::
- strengthen_sig (Env.add_modtype id decl env) rem p
+ strengthen_sig (Env.add_modtype id decl env) rem p pos
(* Need to add the module type in case it is manifest *)
| (Sig_class(id, decl, rs) as sigelt) :: rem ->
- sigelt :: strengthen_sig env rem p
+ sigelt :: strengthen_sig env rem p (pos+1)
| (Sig_class_type(id, decl, rs) as sigelt) :: rem ->
- sigelt :: strengthen_sig env rem p
+ sigelt :: strengthen_sig env rem p pos
and strengthen_decl env md p =
{md with md_type = strengthen env md.md_type p}
diff --git a/typing/subst.ml b/typing/subst.ml
index 2e84be01f..5b1b0c67f 100644
--- a/typing/subst.ml
+++ b/typing/subst.ml
@@ -184,6 +184,27 @@ let type_expr s ty =
cleanup_types ();
ty'
+let label_declaration s l =
+ {
+ ld_id = l.ld_id;
+ ld_mutable = l.ld_mutable;
+ ld_type = typexp s l.ld_type;
+ ld_loc = loc s l.ld_loc;
+ ld_attributes = attrs s l.ld_attributes;
+ }
+
+let constructor_arguments s args =
+ List.map (typexp s) args
+
+let constructor_declaration s c =
+ {
+ cd_id = c.cd_id;
+ cd_args = constructor_arguments s c.cd_args;
+ cd_res = may_map (typexp s) c.cd_res;
+ cd_loc = loc s c.cd_loc;
+ cd_attributes = attrs s c.cd_attributes;
+ }
+
let type_declaration s decl =
let decl =
{ type_params = List.map (typexp s) decl.type_params;
@@ -192,31 +213,9 @@ let type_declaration s decl =
begin match decl.type_kind with
Type_abstract -> Type_abstract
| Type_variant cstrs ->
- Type_variant
- (List.map
- (fun c ->
- {
- cd_id = c.cd_id;
- cd_args = List.map (typexp s) c.cd_args;
- cd_res = may_map (typexp s) c.cd_res;
- cd_loc = loc s c.cd_loc;
- cd_attributes = attrs s c.cd_attributes;
- }
- )
- cstrs)
+ Type_variant (List.map (constructor_declaration s) cstrs)
| Type_record(lbls, rep) ->
- Type_record
- (List.map (fun l ->
- {
- ld_id = l.ld_id;
- ld_mutable = l.ld_mutable;
- ld_type = typexp s l.ld_type;
- ld_loc = loc s l.ld_loc;
- ld_attributes = attrs s l.ld_attributes;
- }
- )
- lbls,
- rep)
+ Type_record (List.map (label_declaration s) lbls, rep)
| Type_open -> Type_open
end;
type_manifest =
@@ -303,7 +302,7 @@ let extension_constructor s ext =
let ext =
{ ext_type_path = type_path s ext.ext_type_path;
ext_type_params = List.map (typexp s) ext.ext_type_params;
- ext_args = List.map (typexp s) ext.ext_args;
+ ext_args = constructor_arguments s ext.ext_args;
ext_ret_type = may_map (typexp s) ext.ext_ret_type;
ext_private = ext.ext_private;
ext_attributes = ext.ext_attributes;
diff --git a/typing/typemod.ml b/typing/typemod.ml
index 94f8c621a..f6ea9d192 100644
--- a/typing/typemod.ml
+++ b/typing/typemod.ml
@@ -138,6 +138,10 @@ let make p n i =
let open Variance in
set May_pos p (set May_neg n (set May_weak n (set Inj i null)))
+let ensure_functor_arg p env =
+ if Env.is_functor_arg p env then env else
+ Env.add_functor_arg (Path.head p) env
+
let merge_constraint initial_env loc sg constr =
let lid =
match constr with
@@ -212,6 +216,7 @@ let merge_constraint initial_env loc sg constr =
when Ident.name id = s ->
let path, md' = Typetexp.find_module initial_env loc lid'.txt in
let md'' = {md' with md_type = Mtype.remove_aliases env md'.md_type} in
+ let env = ensure_functor_arg path env in
let newmd = Mtype.strengthen_decl env md'' path in
ignore(Includemod.modtypes env newmd.md_type md.md_type);
(Pident id, lid, Twith_module (path, lid')),
@@ -219,6 +224,7 @@ let merge_constraint initial_env loc sg constr =
| (Sig_module(id, md, rs) :: rem, [s], Pwith_modsubst (_, lid'))
when Ident.name id = s ->
let path, md' = Typetexp.find_module initial_env loc lid'.txt in
+ let env = ensure_functor_arg path env in
let newmd = Mtype.strengthen_decl env md' path in
ignore(Includemod.modtypes env newmd.md_type md.md_type);
real_id := Some id;
@@ -431,16 +437,30 @@ let check cl loc set_ref name =
then raise(Error(loc, Env.empty, Repeated_name(cl, name)))
else set_ref := StringSet.add name !set_ref
-let check_name cl set_ref name =
- check cl name.loc set_ref name.txt
+type names =
+ {
+ types: StringSet.t ref;
+ modules: StringSet.t ref;
+ modtypes: StringSet.t ref;
+ }
-let check_sig_item type_names module_names modtype_names loc = function
- Sig_type(id, _, _) ->
- check "type" loc type_names (Ident.name id)
- | Sig_module(id, _, _) ->
- check "module" loc module_names (Ident.name id)
- | Sig_modtype(id, _) ->
- check "module type" loc modtype_names (Ident.name id)
+let new_names () =
+ {
+ types = ref StringSet.empty;
+ modules = ref StringSet.empty;
+ modtypes = ref StringSet.empty;
+ }
+
+
+let check_name check names name = check names name.loc name.txt
+let check_type names loc s = check "type" loc names.types s
+let check_module names loc s = check "module" loc names.modules s
+let check_modtype names loc s = check "module type" loc names.modtypes s
+
+let check_sig_item names loc = function
+ | Sig_type(id, _, _) -> check_type names loc (Ident.name id)
+ | Sig_module(id, _, _) -> check_module names loc (Ident.name id)
+ | Sig_modtype(id, _) -> check_modtype names loc (Ident.name id)
| _ -> ()
let rec remove_duplicates val_ids ext_ids = function
@@ -542,9 +562,7 @@ let rec transl_modtype env smty =
and transl_signature env sg =
- let type_names = ref StringSet.empty
- and module_names = ref StringSet.empty
- and modtype_names = ref StringSet.empty in
+ let names = new_names () in
let rec transl_sig env sg =
Ctype.init_def(Ident.current_time());
match sg with
@@ -562,8 +580,7 @@ and transl_signature env sg =
final_env
| Psig_type sdecls ->
List.iter
- (fun decl ->
- check_name "type" type_names decl.ptype_name)
+ (fun decl -> check_name check_type names decl.ptype_name)
sdecls;
let (decls, newenv) = Typedecl.transl_type_decl env sdecls in
let (trem, rem, final_env) = transl_sig newenv srem in
@@ -600,7 +617,7 @@ and transl_signature env sg =
Sig_typext(ext.ext_id, ext.ext_type, Text_exception) :: rem),
final_env
| Psig_module pmd ->
- check_name "module" module_names pmd.pmd_name;
+ check_name check_module names pmd.pmd_name;
let tmty = transl_modtype env pmd.pmd_type in
let md = {
md_type=tmty.mty_type;
@@ -619,7 +636,7 @@ and transl_signature env sg =
final_env
| Psig_recmodule sdecls ->
List.iter
- (fun pmd -> check_name "module" module_names pmd.pmd_name)
+ (fun pmd -> check_name check_module names pmd.pmd_name)
sdecls;
let (decls, newenv) =
transl_recmodule_modtypes item.psig_loc env sdecls in
@@ -635,7 +652,7 @@ and transl_signature env sg =
final_env
| Psig_modtype pmtd ->
let newenv, mtd, sg =
- transl_modtype_decl modtype_names env item.psig_loc pmtd
+ transl_modtype_decl names env item.psig_loc pmtd
in
let (trem, rem, final_env) = transl_sig newenv srem in
mksig (Tsig_modtype mtd) env loc :: trem,
@@ -652,10 +669,7 @@ and transl_signature env sg =
let mty = tmty.mty_type in
let sg = Subst.signature Subst.identity
(extract_sig env smty.pmty_loc mty) in
- List.iter
- (check_sig_item type_names module_names modtype_names
- item.psig_loc)
- sg;
+ List.iter (check_sig_item names item.psig_loc) sg;
let newenv = Env.add_signature sg env in
let incl =
{ incl_mod = tmty;
@@ -671,7 +685,7 @@ and transl_signature env sg =
final_env
| Psig_class cl ->
List.iter
- (fun {pci_name = name} -> check_name "type" type_names name)
+ (fun {pci_name} -> check_name check_type names pci_name)
cl;
let (classes, newenv) = Typeclass.class_descriptions env cl in
let (trem, rem, final_env) = transl_sig newenv srem in
@@ -693,7 +707,7 @@ and transl_signature env sg =
final_env
| Psig_class_type cl ->
List.iter
- (fun {pci_name = name} -> check_name "type" type_names name)
+ (fun {pci_name} -> check_name check_type names pci_name)
cl;
let (classes, newenv) = Typeclass.class_type_declarations env cl in
let (trem,rem, final_env) = transl_sig newenv srem in
@@ -725,9 +739,9 @@ and transl_signature env sg =
((Cmt_format.Partial_signature sg) :: previous_saved_types);
sg
-and transl_modtype_decl modtype_names env loc
+and transl_modtype_decl names env loc
{pmtd_name; pmtd_type; pmtd_attributes; pmtd_loc} =
- check_name "module type" modtype_names pmtd_name;
+ check_name check_modtype names pmtd_name;
let tmty = Misc.may_map (transl_modtype env) pmtd_type in
let decl =
{
@@ -812,22 +826,31 @@ and transl_recmodule_modtypes loc env sdecls =
keep only the last (rightmost) one. *)
let simplify_signature sg =
- let rec simplif val_names ext_names res = function
- [] -> res
- | (Sig_value(id, descr) as component) :: sg ->
- let name = Ident.name id in
- simplif (StringSet.add name val_names) ext_names
- (if StringSet.mem name val_names then res else component :: res)
- sg
- | (Sig_typext(id, ext, es) as component) :: sg ->
- let name = Ident.name id in
- simplif val_names (StringSet.add name ext_names)
- (if StringSet.mem name ext_names then res else component :: res)
- sg
- | component :: sg ->
- simplif val_names ext_names (component :: res) sg
+ let rec aux = function
+ | [] -> [], StringSet.empty, StringSet.empty
+ | (Sig_value(id, descr) as component) :: sg ->
+ let (sg, val_names, ext_names) as k = aux sg in
+ let name = Ident.name id in
+ if StringSet.mem name val_names then k
+ else (component :: sg, StringSet.add name val_names, ext_names)
+ | (Sig_typext(id, ext, es) as component) :: sg ->
+ let (sg, val_names, ext_names) as k = aux sg in
+ let name = Ident.name id in
+ if StringSet.mem name ext_names then
+ (* #6510 *)
+ match es, sg with
+ | Text_first, Sig_typext(id2, ext2, Text_next) :: rest ->
+ (Sig_typext(id2, ext2, Text_first) :: rest,
+ val_names, ext_names)
+ | _ -> k
+ else
+ (component :: sg, val_names, StringSet.add name ext_names)
+ | component :: sg ->
+ let (sg, val_names, ext_names) = aux sg in
+ (component :: sg, val_names, ext_names)
in
- simplif StringSet.empty StringSet.empty [] (List.rev sg)
+ let (sg, _, _) = aux sg in
+ sg
(* Try to convert a module expression to a module path. *)
@@ -919,8 +942,10 @@ let check_recmodule_inclusion env bindings =
the number of mutually recursive declarations. *)
let subst_and_strengthen env s id mty =
- Mtype.strengthen env (Subst.modtype s mty)
- (Subst.module_path s (Pident id)) in
+ let p = Subst.module_path s (Pident id) in
+ let env = ensure_functor_arg p env in
+ Mtype.strengthen env (Subst.modtype s mty) p
+ in
let rec check_incl first_time n env s =
if n > 0 then begin
@@ -1191,9 +1216,7 @@ let rec type_module ?(alias=false) sttn funct_body anchor env smod =
raise (Error_forward (Typetexp.error_of_extension ext))
and type_structure ?(toplevel = false) funct_body anchor env sstr scope =
- let type_names = ref StringSet.empty
- and module_names = ref StringSet.empty
- and modtype_names = ref StringSet.empty in
+ let names = new_names () in
let type_str_item env srem {pstr_loc = loc; pstr_desc = desc} =
match desc with
@@ -1227,7 +1250,7 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope =
Tstr_primitive desc, [Sig_value(desc.val_id, desc.val_val)], newenv
| Pstr_type sdecls ->
List.iter
- (fun decl -> check_name "type" type_names decl.ptype_name)
+ (fun decl -> check_name check_type names decl.ptype_name)
sdecls;
let (decls, newenv) = Typedecl.transl_type_decl env sdecls in
Tstr_type decls,
@@ -1251,7 +1274,7 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope =
| Pstr_module {pmb_name = name; pmb_expr = smodl; pmb_attributes = attrs;
pmb_loc;
} ->
- check_name "module" module_names name;
+ check_name check_module names name;
let modl =
type_module ~alias:true true funct_body
(anchor_submodule name.txt anchor) env smodl in
@@ -1288,7 +1311,7 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope =
sbind
in
List.iter
- (fun (name, _, _, _, _) -> check_name "module" module_names name)
+ (fun (name, _, _, _, _) -> check_name check_module names name)
sbind;
let (decls, newenv) =
transl_recmodule_modtypes loc env
@@ -1335,7 +1358,7 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope =
| Pstr_modtype pmtd ->
(* check that it is non-abstract *)
let newenv, mtd, sg =
- transl_modtype_decl modtype_names env loc pmtd
+ transl_modtype_decl names env loc pmtd
in
Tstr_modtype mtd, [sg], newenv
| Pstr_open sod ->
@@ -1343,7 +1366,7 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope =
Tstr_open od, [], newenv
| Pstr_class cl ->
List.iter
- (fun {pci_name = name} -> check_name "type" type_names name)
+ (fun {pci_name} -> check_name check_type names pci_name)
cl;
let (classes, new_env) = Typeclass.class_declarations env cl in
Tstr_class
@@ -1370,7 +1393,7 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope =
new_env
| Pstr_class_type cl ->
List.iter
- (fun {pci_name = name} -> check_name "type" type_names name)
+ (fun {pci_name} -> check_name check_type names pci_name)
cl;
let (classes, new_env) = Typeclass.class_type_declarations env cl in
Tstr_class_type
@@ -1395,29 +1418,7 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope =
(* Rename all identifiers bound by this signature to avoid clashes *)
let sg = Subst.signature Subst.identity
(extract_sig_open env smodl.pmod_loc modl.mod_type) in
- let sg =
- match modl.mod_desc with
- Tmod_ident (p, _) when not (Env.is_functor_arg p env) ->
- Env.add_required_global (Path.head p);
- let pos = ref 0 in
- List.map
- (function
- | Sig_module (id, md, rs) ->
- let n = !pos in incr pos;
- Sig_module (id, {md with md_type =
- Mty_alias (Pdot(p,Ident.name id,n))},
- rs)
- | Sig_value (_, {val_kind=Val_reg})
- | Sig_typext _ | Sig_class _ as it ->
- incr pos; it
- | Sig_value _ | Sig_type _ | Sig_modtype _
- | Sig_class_type _ as it ->
- it)
- sg
- | _ -> sg
- in
- List.iter
- (check_sig_item type_names module_names modtype_names loc) sg;
+ List.iter (check_sig_item names loc) sg;
let new_env = Env.add_signature sg env in
let incl =
{ incl_mod = modl;
@@ -1480,49 +1481,6 @@ and normalize_signature_item env = function
| Sig_module(id, md, _) -> normalize_modtype env md.md_type
| _ -> ()
-(* Simplify multiple specifications of a value or an extension in a signature.
- (Other signature components, e.g. types, modules, etc, are checked for
- name uniqueness.) If multiple specifications with the same name,
- keep only the last (rightmost) one. *)
-
-let rec simplify_modtype mty =
- match mty with
- Mty_ident path -> mty
- | Mty_alias path -> mty
- | Mty_functor(id, arg, res) -> Mty_functor(id, arg, simplify_modtype res)
- | Mty_signature sg -> Mty_signature(simplify_signature sg)
-
-and simplify_signature sg =
- let rec aux = function
- | [] -> [], StringSet.empty, StringSet.empty
- | (Sig_value(id, descr) as component) :: sg ->
- let (sg, val_names, ext_names) as k = aux sg in
- let name = Ident.name id in
- if StringSet.mem name val_names then k
- else (component :: sg, StringSet.add name val_names, ext_names)
- | (Sig_typext(id, ext, es) as component) :: sg ->
- let (sg, val_names, ext_names) as k = aux sg in
- let name = Ident.name id in
- if StringSet.mem name ext_names then
- (* #6510 *)
- match es, sg with
- | Text_first, Sig_typext(id2, ext2, Text_next) :: rest ->
- (Sig_typext(id2, ext2, Text_first) :: rest,
- val_names, ext_names)
- | _ -> k
- else
- (component :: sg, val_names, StringSet.add name ext_names)
- | Sig_module(id, md, rs) :: sg ->
- let (sg, val_names, ext_names) = aux sg in
- let md = {md with md_type = simplify_modtype md.md_type} in
- (Sig_module(id, md, rs) :: sg, val_names, ext_names)
- | component :: sg ->
- let (sg, val_names, ext_names) = aux sg in
- (component :: sg, val_names, ext_names)
- in
- let (sg, _, _) = aux sg in
- sg
-
(* Extract the module type of a module expression *)
let type_module_type_of env smod =