summaryrefslogtreecommitdiff
path: root/typing
diff options
context:
space:
mode:
Diffstat (limited to 'typing')
-rw-r--r--typing/btype.ml14
-rw-r--r--typing/ctype.ml14
-rw-r--r--typing/env.ml12
-rw-r--r--typing/subst.ml61
-rw-r--r--typing/subst.mli2
5 files changed, 71 insertions, 32 deletions
diff --git a/typing/btype.ml b/typing/btype.ml
index dd5ec5d4f6..35d18909b4 100644
--- a/typing/btype.ml
+++ b/typing/btype.ml
@@ -149,6 +149,7 @@ let rec iter_abbrev f = function
| Mlink rem -> iter_abbrev f !rem
let copy_row f fixed row keep more =
+ let bound = ref [] in
let fields = List.map
(fun (l, fi) -> l,
match row_field_repr fi with
@@ -156,15 +157,19 @@ let copy_row f fixed row keep more =
| Reither(c, tl, m, e) ->
let e = if keep then e else ref None in
let m = if row.row_fixed then fixed else m in
- Reither(c, List.map f tl, m , e)
+ let tl = List.map f tl in
+ bound := List.filter
+ (function {desc=Tconstr(_,[],_)} -> false | _ -> true)
+ (List.map repr tl)
+ @ !bound;
+ Reither(c, tl, m, e)
| _ -> fi)
row.row_fields in
let name =
match row.row_name with None -> None
| Some (path, tl) -> Some (path, List.map f tl) in
{ row_fields = fields; row_more = more;
- row_bound = List.map f row.row_bound;
- row_fixed = row.row_fixed && fixed;
+ row_bound = !bound; row_fixed = row.row_fixed && fixed;
row_closed = row.row_closed; row_name = name; }
let rec copy_kind = function
@@ -194,6 +199,9 @@ let rec copy_type_desc f = function
| Tunivar -> Tunivar
| Tpoly (ty, tyl) -> Tpoly (f ty, List.map f tyl)
+
+(* Utilities for copying *)
+
let saved_desc = ref []
(* Saved association of generic nodes with their description. *)
diff --git a/typing/ctype.ml b/typing/ctype.ml
index 3a22b553c1..1bfe2538bf 100644
--- a/typing/ctype.ml
+++ b/typing/ctype.ml
@@ -2786,12 +2786,15 @@ let rec normalize_type_rec env ty =
f
else f
| _ -> f)
- row.row_fields
+ row.row_fields in
+ let fields =
+ List.sort (fun (p,_) (q,_) -> compare p q)
+ (List.filter (fun (_,fi) -> fi <> Rabsent) fields)
and bound = List.fold_left
(fun tyl ty -> if List.memq ty tyl then tyl else ty :: tyl)
[] (List.map repr row.row_bound)
in ty.desc <- Tvariant {row with row_fields = fields; row_bound = bound}
- | Tobject (_, nm) ->
+ | Tobject (fi, nm) ->
begin match !nm with
| None -> ()
| Some (n, v :: l) ->
@@ -2803,7 +2806,12 @@ let rec normalize_type_rec env ty =
end
| _ ->
fatal_error "Ctype.normalize_type_rec"
- end
+ end;
+ let fi = repr fi in
+ if fi.level < lowest_level then () else
+ let fields, row = flatten_fields fi in
+ let fi' = build_fields fi.level fields row in
+ fi.desc <- fi'.desc
| _ -> ()
end;
iter_type_expr (normalize_type_rec env) ty
diff --git a/typing/env.ml b/typing/env.ml
index 060363b2be..ddaa92e28a 100644
--- a/typing/env.ml
+++ b/typing/env.ml
@@ -719,9 +719,8 @@ let imported_units() =
let save_signature sg modname filename =
Btype.cleanup_abbrev ();
- let comps =
- components_of_module empty Subst.identity
- (Pident(Ident.create_persistent modname)) (Tmty_signature sg) in
+ Subst.reset_for_saving ();
+ let sg = Subst.signature (Subst.for_saving Subst.identity) sg in
let oc = open_out_bin filename in
try
output_string oc cmi_magic_number;
@@ -730,16 +729,19 @@ let save_signature sg modname filename =
let crc = Digest.file filename in
let crcs = (modname, crc) :: imported_units() in
output_value oc crcs;
+ close_out oc;
(* Enter signature in persistent table so that imported_unit()
will also return its crc *)
+ let comps =
+ components_of_module empty Subst.identity
+ (Pident(Ident.create_persistent modname)) (Tmty_signature sg) in
let ps =
{ ps_name = modname;
ps_sig = sg;
ps_comps = comps;
ps_crcs = crcs;
ps_filename = filename } in
- Hashtbl.add persistent_structures modname ps;
- close_out oc
+ Hashtbl.add persistent_structures modname ps
with exn ->
close_out oc;
remove_file filename;
diff --git a/typing/subst.ml b/typing/subst.ml
index 45fe325756..66646c157c 100644
--- a/typing/subst.ml
+++ b/typing/subst.ml
@@ -22,25 +22,20 @@ open Btype
type t =
{ types: (Ident.t, Path.t) Tbl.t;
modules: (Ident.t, Path.t) Tbl.t;
- modtypes: (Ident.t, module_type) Tbl.t }
+ modtypes: (Ident.t, module_type) Tbl.t;
+ for_saving: bool }
let identity =
- { types = Tbl.empty; modules = Tbl.empty; modtypes = Tbl.empty }
+ { types = Tbl.empty; modules = Tbl.empty; modtypes = Tbl.empty;
+ for_saving = false }
-let add_type id p s =
- { types = Tbl.add id p s.types;
- modules = s.modules;
- modtypes = s.modtypes }
+let add_type id p s = { s with types = Tbl.add id p s.types }
-let add_module id p s =
- { types = s.types;
- modules = Tbl.add id p s.modules;
- modtypes = s.modtypes }
+let add_module id p s = { s with modules = Tbl.add id p s.modules }
-let add_modtype id ty s =
- { types = s.types;
- modules = s.modules;
- modtypes = Tbl.add id ty s.modtypes }
+let add_modtype id ty s = { s with modtypes = Tbl.add id ty s.modtypes }
+
+let for_saving s = { s with for_saving = true }
let rec module_path s = function
Pident id as p ->
@@ -58,12 +53,23 @@ let type_path s = function
| Papply(p1, p2) ->
fatal_error "Subst.type_path"
+(* Special type ids for saved signatures *)
+
+let new_id = ref (-1)
+let reset_for_saving () = new_id := -1
+
+let newpersty desc =
+ decr new_id; { desc = desc; level = generic_level; id = !new_id }
+
(* Similar to [Ctype.nondep_type_rec]. *)
let rec typexp s ty =
let ty = repr ty in
match ty.desc with
Tvar | Tunivar ->
- ty
+ if s.for_saving then
+ let ty' = newpersty ty.desc in
+ save_desc ty ty.desc; ty.desc <- Tsubst ty'; ty'
+ else ty
| Tsubst ty ->
ty
(* cannot do it, since it would omit subsitution
@@ -73,7 +79,8 @@ let rec typexp s ty =
| _ ->
let desc = ty.desc in
save_desc ty desc;
- let ty' = newgenvar () in (* Stub *)
+ (* Make a stub *)
+ let ty' = if s.for_saving then newpersty Tvar else newgenvar () in
ty.desc <- Tsubst ty';
ty'.desc <-
begin match desc with
@@ -90,18 +97,27 @@ let rec typexp s ty =
let more = repr row.row_more in
(* We must substitute in a subtle way *)
begin match more.desc with
- Tsubst ty2 ->
+ Tsubst ({desc=Tvariant _} as ty2) ->
(* This variant type has been already copied *)
ty.desc <- Tsubst ty2; (* avoid Tlink in the new type *)
Tlink ty2
| _ ->
let static = static_row row in
+ (* Various cases for the row variable *)
+ let more' =
+ match more.desc with Tsubst ty -> ty
+ | _ ->
+ if s.for_saving then newpersty more.desc else
+ if static then newgenvar () else more
+ in
(* Register new type first for recursion *)
save_desc more more.desc;
more.desc <- ty.desc;
- let more' = if static then newgenvar () else more in
(* Return a new copy *)
- let row = copy_row (typexp s) true row true more' in
+ let row =
+ copy_row (typexp s) true row (not s.for_saving) more' in
+ let row =
+ if s.for_saving then {row with row_bound = []} else row in
match row.row_name with
Some (p, tl) ->
Tvariant {row with row_name = Some (type_path s p, tl)}
@@ -115,6 +131,7 @@ let rec typexp s ty =
| Fabsent ->
Tlink (typexp s t2)
| Fvar _ (* {contents = None} *) as k ->
+ let k = if s.for_saving then Fvar(ref None) else k in
Tfield(label, k, typexp s t1, typexp s t2)
end
| _ -> copy_type_desc (typexp s) desc
@@ -183,7 +200,8 @@ let class_declaration s decl =
| Some ty -> Some (typexp s ty)
end }
in
- cleanup_types ();
+ (* Do not clean up if saving: next is cltype_declaration *)
+ if not s.for_saving then cleanup_types ();
decl
let cltype_declaration s decl =
@@ -192,7 +210,8 @@ let cltype_declaration s decl =
clty_type = class_type s decl.clty_type;
clty_path = type_path s decl.clty_path }
in
- cleanup_types ();
+ (* Do not clean up if saving: next is type_declaration *)
+ if not s.for_saving then cleanup_types ();
decl
let class_type s cty =
diff --git a/typing/subst.mli b/typing/subst.mli
index 1da0cd18c0..b2220bb49e 100644
--- a/typing/subst.mli
+++ b/typing/subst.mli
@@ -35,6 +35,8 @@ val identity: t
val add_type: Ident.t -> Path.t -> t -> t
val add_module: Ident.t -> Path.t -> t -> t
val add_modtype: Ident.t -> module_type -> t -> t
+val for_saving: t -> t
+val reset_for_saving: unit -> unit
val type_expr: t -> type_expr -> type_expr
val class_type: t -> class_type -> class_type