summaryrefslogtreecommitdiff
path: root/typing/mtype.ml
diff options
context:
space:
mode:
Diffstat (limited to 'typing/mtype.ml')
-rw-r--r--typing/mtype.ml158
1 files changed, 154 insertions, 4 deletions
diff --git a/typing/mtype.ml b/typing/mtype.ml
index 53850d962a..a5e0d811dd 100644
--- a/typing/mtype.ml
+++ b/typing/mtype.ml
@@ -34,7 +34,8 @@ let rec strengthen env mty p =
match scrape env mty with
Mty_signature sg ->
Mty_signature(strengthen_sig env sg p)
- | Mty_functor(param, arg, res) when !Clflags.applicative_functors ->
+ | 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
@@ -85,6 +86,7 @@ and strengthen_sig env sg p =
and strengthen_decl env md p =
{md with md_type = strengthen env md.md_type p}
+let () = Env.strengthen := strengthen
(* In nondep_supertype, env is only used for the type it assigns to id.
Hence there is no need to keep env up-to-date by adding the bindings
@@ -100,13 +102,19 @@ let nondep_supertype env mid mty =
if Path.isfree mid p then
nondep_mty env va (Env.find_modtype_expansion p env)
else mty
+ | Mty_alias p ->
+ if Path.isfree mid p then
+ nondep_mty env va (Env.find_module p env).md_type
+ else mty
| Mty_signature sg ->
Mty_signature(nondep_sig env va sg)
| Mty_functor(param, arg, res) ->
let var_inv =
match va with Co -> Contra | Contra -> Co | Strict -> Strict in
- Mty_functor(param, nondep_mty env var_inv arg,
- nondep_mty (Env.add_module param arg env) va res)
+ Mty_functor(param, Misc.may_map (nondep_mty env var_inv) arg,
+ nondep_mty
+ (Env.add_module ~arg:true param
+ (Btype.default_mty arg) env) va res)
and nondep_sig env va = function
[] -> []
@@ -135,7 +143,8 @@ let nondep_supertype env mid mty =
Sig_modtype(id, nondep_modtype_decl env d) :: rem'
with Not_found ->
match va with
- Co -> Sig_modtype(id, {mtd_type=None; mtd_attributes=[]}) :: rem'
+ Co -> Sig_modtype(id, {mtd_type=None; mtd_loc=Location.none;
+ mtd_attributes=[]}) :: rem'
| _ -> raise Not_found
end
| Sig_class(id, d, rs) ->
@@ -186,6 +195,7 @@ and enrich_item env p = function
let rec type_paths env p mty =
match scrape env mty with
Mty_ident p -> []
+ | Mty_alias p -> []
| Mty_signature sg -> type_paths_sig env p 0 sg
| Mty_functor(param, arg, res) -> []
@@ -212,6 +222,7 @@ let rec no_code_needed env mty =
Mty_ident p -> false
| Mty_signature sg -> no_code_needed_sig env sg
| Mty_functor(_, _, _) -> false
+ | Mty_alias p -> true
and no_code_needed_sig env sg =
match sg with
@@ -228,3 +239,142 @@ and no_code_needed_sig env sg =
no_code_needed_sig env rem
| (Sig_exception _ | Sig_class _) :: rem ->
false
+
+
+(* Check whether a module type may return types *)
+
+let rec contains_type env = function
+ Mty_ident path ->
+ (try Misc.may (contains_type env) (Env.find_modtype path env).mtd_type
+ with Not_found -> raise Exit)
+ | Mty_signature sg ->
+ contains_type_sig env sg
+ | Mty_functor (_, _, body) ->
+ contains_type env body
+ | Mty_alias _ ->
+ ()
+
+and contains_type_sig env = List.iter (contains_type_item env)
+
+and contains_type_item env = function
+ Sig_type (_,({type_manifest = None} |
+ {type_kind = Type_abstract; type_private = Private}),_)
+ | Sig_modtype _ ->
+ raise Exit
+ | Sig_module (_, {md_type = mty}, _) ->
+ contains_type env mty
+ | Sig_value _
+ | Sig_type _
+ | Sig_exception _
+ | Sig_class _
+ | Sig_class_type _ ->
+ ()
+
+let contains_type env mty =
+ try contains_type env mty; false with Exit -> true
+
+
+(* Remove module aliases from a signature *)
+
+module P = struct
+ type t = Path.t
+ let compare p1 p2 =
+ if Path.same p1 p2 then 0 else compare p1 p2
+end
+module PathSet = Set.Make (P)
+module PathMap = Map.Make (P)
+module IdentSet = Set.Make (struct type t = Ident.t let compare = compare end)
+
+let rec get_prefixes = function
+ Pident _ -> PathSet.empty
+ | Pdot (p, _, _)
+ | Papply (p, _) -> PathSet.add p (get_prefixes p)
+
+let rec get_arg_paths = function
+ Pident _ -> PathSet.empty
+ | Pdot (p, _, _) -> get_arg_paths p
+ | Papply (p1, p2) ->
+ PathSet.add p2
+ (PathSet.union (get_prefixes p2)
+ (PathSet.union (get_arg_paths p1) (get_arg_paths p2)))
+
+let rec rollback_path subst p =
+ try Pident (PathMap.find p subst)
+ with Not_found ->
+ match p with
+ Pident _ | Papply _ -> p
+ | Pdot (p1, s, n) ->
+ let p1' = rollback_path subst p1 in
+ if Path.same p1 p1' then p else rollback_path subst (Pdot (p1', s, n))
+
+let rec collect_ids subst bindings p =
+ begin match rollback_path subst p with
+ Pident id ->
+ let ids =
+ try collect_ids subst bindings (Ident.find_same id bindings)
+ with Not_found -> IdentSet.empty
+ in
+ IdentSet.add id ids
+ | _ -> IdentSet.empty
+ end
+
+let collect_arg_paths mty =
+ let open Btype in
+ let paths = ref PathSet.empty
+ and subst = ref PathMap.empty
+ and bindings = ref Ident.empty in
+ (* let rt = Ident.create "Root" in
+ and prefix = ref (Path.Pident rt) in *)
+ let it_path p = paths := PathSet.union (get_arg_paths p) !paths
+ and it_signature_item it si =
+ type_iterators.it_signature_item it si;
+ match si with
+ Sig_module (id, {md_type=Mty_alias p}, _) ->
+ bindings := Ident.add id p !bindings
+ | Sig_module (id, {md_type=Mty_signature sg}, _) ->
+ List.iter
+ (function Sig_module (id', _, _) ->
+ subst :=
+ PathMap.add (Pdot (Pident id, Ident.name id', -1)) id' !subst
+ | _ -> ())
+ sg
+ | _ -> ()
+ in
+ let it = {type_iterators with it_path; it_signature_item} in
+ it.it_module_type it mty;
+ PathSet.fold (fun p -> IdentSet.union (collect_ids !subst !bindings p))
+ !paths IdentSet.empty
+
+let rec remove_aliases env excl mty =
+ match mty with
+ Mty_signature sg ->
+ Mty_signature (remove_aliases_sig env excl sg)
+ | Mty_alias _ ->
+ remove_aliases env excl (Env.scrape_alias env mty)
+ | mty ->
+ mty
+
+and remove_aliases_sig env excl sg =
+ match sg with
+ [] -> []
+ | Sig_module(id, md, rs) :: rem ->
+ let mty =
+ match md.md_type with
+ Mty_alias _ when IdentSet.mem id excl ->
+ md.md_type
+ | mty ->
+ remove_aliases env excl mty
+ in
+ Sig_module(id, {md with md_type = mty} , rs) ::
+ remove_aliases_sig (Env.add_module id mty env) excl rem
+ | Sig_modtype(id, mtd) :: rem ->
+ Sig_modtype(id, mtd) ::
+ remove_aliases_sig (Env.add_modtype id mtd env) excl rem
+ | it :: rem ->
+ it :: remove_aliases_sig env excl rem
+
+let remove_aliases env sg =
+ let excl = collect_arg_paths sg in
+ (* PathSet.iter (fun p -> Format.eprintf "%a@ " Printtyp.path p) excl;
+ Format.eprintf "@."; *)
+ remove_aliases env excl sg