summaryrefslogtreecommitdiff
path: root/typing/typemod.ml
diff options
context:
space:
mode:
Diffstat (limited to 'typing/typemod.ml')
-rw-r--r--typing/typemod.ml361
1 files changed, 239 insertions, 122 deletions
diff --git a/typing/typemod.ml b/typing/typemod.ml
index 260ec22751..0f3170f60d 100644
--- a/typing/typemod.ml
+++ b/typing/typemod.ml
@@ -307,11 +307,18 @@ let iterator_with_env env =
env := env_before
);
Btype.it_module_type = (fun self -> function
- | Mty_functor (param, mty_arg, mty_body) ->
- Option.iter (self.Btype.it_module_type self) mty_arg;
+ | Mty_functor (param, mty_body) ->
let env_before = !env in
- env := lazy (Env.add_module ~arg:true param Mp_present
- (Btype.default_mty mty_arg) (Lazy.force env_before));
+ begin match param with
+ | Unit -> ()
+ | Named (param, mty_arg) ->
+ self.Btype.it_module_type self mty_arg;
+ match param with
+ | None -> ()
+ | Some id ->
+ env := lazy (Env.add_module ~arg:true id Mp_present
+ mty_arg (Lazy.force env_before))
+ end;
self.Btype.it_module_type self mty_body;
env := env_before;
| mty ->
@@ -324,7 +331,7 @@ let retype_applicative_functor_type ~loc env funct arg =
let mty_arg = (Env.find_module arg env).md_type in
let mty_param =
match Env.scrape_alias env mty_functor with
- | Mty_functor (_, Some mty_param, _) -> mty_param
+ | Mty_functor (Named (_, mty_param), _) -> mty_param
| _ -> assert false (* could trigger due to MPR#7611 *)
in
Includemod.check_modtype_inclusion ~loc env mty_arg arg mty_param
@@ -685,16 +692,24 @@ let rec approx_modtype env smty =
Mty_alias(path)
| Pmty_signature ssg ->
Mty_signature(approx_sig env ssg)
- | Pmty_functor(param, sarg, sres) ->
- let arg = Option.map (approx_modtype env) sarg in
- let rarg = Mtype.scrape_for_functor_arg env (Btype.default_mty arg) in
- let scope = Ctype.create_scope () in
- let (id, newenv) =
- Env.enter_module ~scope ~arg:true param.txt
- Mp_present rarg env
+ | Pmty_functor(param, sres) ->
+ let (param, newenv) =
+ match param with
+ | Unit -> Types.Unit, env
+ | Named (param, sarg) ->
+ let arg = approx_modtype env sarg in
+ match param.txt with
+ | None -> Types.Named (None, arg), env
+ | Some name ->
+ let rarg = Mtype.scrape_for_functor_arg env arg in
+ let scope = Ctype.create_scope () in
+ let (id, newenv) =
+ Env.enter_module ~scope ~arg:true name Mp_present rarg env
+ in
+ Types.Named (Some id, arg), newenv
in
let res = approx_modtype newenv sres in
- Mty_functor(id, arg, res)
+ Mty_functor(param, res)
| Pmty_with(sbody, constraints) ->
let body = approx_modtype env sbody in
List.iter
@@ -734,6 +749,8 @@ and approx_sig env ssg =
map_rec_type ~rec_flag
(fun rs (id, info) -> Sig_type(id, info, rs, Exported)) decls rem
| Psig_typesubst _ -> approx_sig env srem
+ | Psig_module { pmd_name = { txt = None; _ }; _ } ->
+ approx_sig env srem
| Psig_module pmd ->
let scope = Ctype.create_scope () in
let md = approx_module_declaration env pmd in
@@ -743,7 +760,8 @@ and approx_sig env ssg =
| _ -> Mp_present
in
let id, newenv =
- Env.enter_module_declaration ~scope pmd.pmd_name.txt pres md env
+ Env.enter_module_declaration ~scope (Option.get pmd.pmd_name.txt)
+ pres md env
in
Sig_module(id, pres, md, Trec_not, Exported) :: approx_sig newenv srem
| Psig_modsubst pms ->
@@ -764,10 +782,12 @@ and approx_sig env ssg =
| Psig_recmodule sdecls ->
let scope = Ctype.create_scope () in
let decls =
- List.map
+ List.filter_map
(fun pmd ->
- (Ident.create_scoped ~scope pmd.pmd_name.txt,
- approx_module_declaration env pmd)
+ Option.map (fun name ->
+ Ident.create_scoped ~scope name,
+ approx_module_declaration env pmd
+ ) pmd.pmd_name.txt
)
sdecls
in
@@ -1115,17 +1135,28 @@ and transl_modtype_aux env smty =
let sg = transl_signature env ssg in
mkmty (Tmty_signature sg) (Mty_signature sg.sig_type) env loc
smty.pmty_attributes
- | Pmty_functor(param, sarg, sres) ->
- let arg = Option.map (transl_modtype_functor_arg env) sarg in
- let ty_arg = Option.map (fun m -> m.mty_type) arg in
- let scope = Ctype.create_scope () in
- let (id, newenv) =
- Env.enter_module ~scope ~arg:true
- param.txt Mp_present (Btype.default_mty ty_arg) env
+ | Pmty_functor(sarg_opt, sres) ->
+ let t_arg, ty_arg, newenv =
+ match sarg_opt with
+ | Unit -> Unit, Types.Unit, env
+ | Named (param, sarg) ->
+ let arg = transl_modtype_functor_arg env sarg in
+ let (id, newenv) =
+ match param.txt with
+ | None -> None, env
+ | Some name ->
+ let scope = Ctype.create_scope () in
+ let id, newenv =
+ Env.enter_module ~scope ~arg:true name Mp_present arg.mty_type
+ env
+ in
+ Some id, newenv
+ in
+ Named (id, param, arg), Types.Named (id, arg.mty_type), newenv
in
let res = transl_modtype newenv sres in
- mkmty (Tmty_functor (id, param, arg, res))
- (Mty_functor(id, ty_arg, res.mty_type)) env loc
+ mkmty (Tmty_functor (t_arg, res))
+ (Mty_functor(ty_arg, res.mty_type)) env loc
smty.pmty_attributes
| Pmty_with(sbody, constraints) ->
let body = transl_modtype env sbody in
@@ -1254,16 +1285,24 @@ and transl_signature env sg =
}
in
let id, newenv =
- Env.enter_module_declaration ~scope pmd.pmd_name.txt pres md env
+ match pmd.pmd_name.txt with
+ | None -> None, env
+ | Some name ->
+ let id, newenv =
+ Env.enter_module_declaration ~scope name pres md env
+ in
+ Signature_names.check_module names pmd.pmd_name.loc id;
+ Some id, newenv
in
- Signature_names.check_module names pmd.pmd_name.loc id;
let (trem, rem, final_env) = transl_sig newenv srem in
mksig (Tsig_module {md_id=id; md_name=pmd.pmd_name;
md_presence=pres; md_type=tmty;
md_loc=pmd.pmd_loc;
md_attributes=pmd.pmd_attributes})
env loc :: trem,
- Sig_module(id, pres, md, Trec_not, Exported) :: rem,
+ (match id with
+ | None -> rem
+ | Some id -> Sig_module(id, pres, md, Trec_not, Exported) :: rem),
final_env
| Psig_modsubst pms ->
let scope = Ctype.create_scope () in
@@ -1301,19 +1340,26 @@ and transl_signature env sg =
rem,
final_env
| Psig_recmodule sdecls ->
- let (decls, newenv) =
+ let (tdecls, newenv) =
transl_recmodule_modtypes env sdecls in
+ let decls =
+ List.filter_map (fun md ->
+ match md.md_id with
+ | None -> None
+ | Some id -> Some (id, md)
+ ) tdecls
+ in
List.iter
- (fun md -> Signature_names.check_module names md.md_loc md.md_id)
+ (fun (id, md) -> Signature_names.check_module names md.md_loc id)
decls;
let (trem, rem, final_env) = transl_sig newenv srem in
- mksig (Tsig_recmodule decls) env loc :: trem,
- map_rec (fun rs md ->
+ mksig (Tsig_recmodule tdecls) env loc :: trem,
+ map_rec (fun rs (id, md) ->
let d = {Types.md_type = md.md_type.mty_type;
md_attributes = md.md_attributes;
md_loc = md.md_loc;
} in
- Sig_module(md.md_id, Mp_present, d, rs, Exported))
+ Sig_module(id, Mp_present, d, rs, Exported))
decls rem,
final_env
| Psig_modtype pmtd ->
@@ -1459,12 +1505,16 @@ and transl_recmodule_modtypes env sdecls =
let make_env curr =
List.fold_left
(fun env (id, _, mty) ->
- Env.add_module ~arg:true id Mp_present mty env)
+ Option.fold ~none:env
+ ~some:(fun id -> Env.add_module ~arg:true id Mp_present mty env) id)
env curr in
let make_env2 curr =
List.fold_left
(fun env (id, _, mty) ->
- Env.add_module ~arg:true id Mp_present mty.mty_type env)
+ Option.fold ~none:env
+ ~some:(fun id ->
+ Env.add_module ~arg:true id Mp_present mty.mty_type env
+ ) id)
env curr in
let transition env_c curr =
List.map2
@@ -1475,22 +1525,27 @@ and transl_recmodule_modtypes env sdecls =
in
(id, id_loc, tmty))
sdecls curr in
- let map_mtys = List.map
+ let map_mtys =
+ List.filter_map
(fun (id, _, mty) ->
- (id, Types.{md_type = mty.mty_type;
- md_loc = mty.mty_loc;
- md_attributes = mty.mty_attributes})) in
+ Option.map (fun id ->
+ (id, Types.{md_type = mty.mty_type;
+ md_loc = mty.mty_loc;
+ md_attributes = mty.mty_attributes})
+ ) id)
+ in
let scope = Ctype.create_scope () in
let ids =
- List.map (fun x -> Ident.create_scoped ~scope x.pmd_name.txt) sdecls
+ List.map (fun x -> Option.map (Ident.create_scoped ~scope) x.pmd_name.txt)
+ sdecls
in
let approx_env =
List.fold_left
- (fun env id ->
- (* cf #5965 *)
- Env.enter_unbound_module (Ident.name id)
- Mod_unbound_illegal_recursion env
- )
+ (fun env ->
+ Option.fold ~none:env ~some:(fun id -> (* cf #5965 *)
+ Env.enter_unbound_module (Ident.name id)
+ Mod_unbound_illegal_recursion env
+ ))
env ids
in
let init =
@@ -1550,9 +1605,13 @@ let rec closed_modtype env = function
| Mty_signature sg ->
let env = Env.add_signature sg env in
List.for_all (closed_signature_item env) sg
- | Mty_functor(id, param, body) ->
+ | Mty_functor(arg_opt, body) ->
let env =
- Env.add_module ~arg:true id Mp_present (Btype.default_mty param) env
+ match arg_opt with
+ | Unit
+ | Named (None, _) -> env
+ | Named (Some id, param) ->
+ Env.add_module ~arg:true id Mp_present param env
in
closed_modtype env body
@@ -1577,9 +1636,14 @@ let check_nongen_schemes env sg =
(* Helpers for typing recursive modules *)
let anchor_submodule name anchor =
- match anchor with None -> None | Some p -> Some(Pdot(p, name))
-let anchor_recmodule id =
- Some (Pident id)
+ match anchor, name with
+ | None, _
+ | _, None ->
+ None
+ | Some p, Some name ->
+ Some(Pdot(p, name))
+
+let anchor_recmodule = Option.map (fun id -> Pident id)
let enrich_type_decls anchor decls oldenv newenv =
match anchor with
@@ -1596,9 +1660,12 @@ let enrich_type_decls anchor decls oldenv newenv =
oldenv decls
let enrich_module_type anchor name mty env =
- match anchor with
- None -> mty
- | Some p -> Mtype.enrich_modtype env (Pdot(p, name)) mty
+ match anchor, name with
+ | None, _
+ | _, None ->
+ mty
+ | Some p, Some name ->
+ Mtype.enrich_modtype env (Pdot(p, name)) mty
let check_recmodule_inclusion env bindings =
(* PR#4450, PR#4470: consider
@@ -1622,8 +1689,13 @@ let check_recmodule_inclusion env bindings =
the number of mutually recursive declarations. *)
let subst_and_strengthen env scope s id mty =
- Mtype.strengthen ~aliasable:false env (Subst.modtype (Rescope scope) s mty)
- (Subst.module_path s (Pident id)) in
+ let mty = Subst.modtype (Rescope scope) s mty in
+ match id with
+ | None -> mty
+ | Some id ->
+ Mtype.strengthen ~aliasable:false env mty
+ (Subst.module_path s (Pident id))
+ in
let rec check_incl first_time n env s =
let scope = Ctype.create_scope () in
@@ -1631,32 +1703,42 @@ let check_recmodule_inclusion env bindings =
(* Generate fresh names Y_i for the rec. bound module idents X_i *)
let bindings1 =
List.map
- (fun (id, name, _mty_decl, _modl, mty_actual, _attrs, _loc) ->
- (id, Ident.create_scoped ~scope name.txt, mty_actual))
+ (fun (id, _name, _mty_decl, _modl, mty_actual, _attrs, _loc) ->
+ let ids =
+ Option.map
+ (fun id -> (id, Ident.create_scoped ~scope (Ident.name id))) id
+ in
+ (ids, mty_actual))
bindings in
(* Enter the Y_i in the environment with their actual types substituted
by the input substitution s *)
let env' =
List.fold_left
- (fun env (id, id', mty_actual) ->
- let mty_actual' =
- if first_time
- then mty_actual
- else subst_and_strengthen env scope s id mty_actual in
- Env.add_module ~arg:false id' Mp_present mty_actual' env)
+ (fun env (ids, mty_actual) ->
+ match ids with
+ | None -> env
+ | Some (id, id') ->
+ let mty_actual' =
+ if first_time
+ then mty_actual
+ else subst_and_strengthen env scope s (Some id) mty_actual
+ in
+ Env.add_module ~arg:false id' Mp_present mty_actual' env)
env bindings1 in
(* Build the output substitution Y_i <- X_i *)
let s' =
List.fold_left
- (fun s (id, id', _mty_actual) ->
- Subst.add_module id (Pident id') s)
+ (fun s (ids, _mty_actual) ->
+ match ids with
+ | None -> s
+ | Some (id, id') -> Subst.add_module id (Pident id') s)
Subst.identity bindings1 in
(* Recurse with env' and s' *)
check_incl false (n-1) env' s'
end else begin
(* Base case: check inclusion of s(mty_actual) in s(mty_decl)
and insert coercion if needed *)
- let check_inclusion (id, id_loc, mty_decl, modl, mty_actual, attrs, loc) =
+ let check_inclusion (id, name, mty_decl, modl, mty_actual, attrs, loc) =
let mty_decl' = Subst.modtype (Rescope scope) s mty_decl.mty_type
and mty_actual' = subst_and_strengthen env scope s id mty_actual in
let coercion =
@@ -1674,7 +1756,7 @@ let check_recmodule_inclusion env bindings =
} in
{
mb_id = id;
- mb_name = id_loc;
+ mb_name = name;
mb_presence = Mp_present;
mb_expr = modl';
mb_attributes = attrs;
@@ -1807,20 +1889,28 @@ and type_module_aux ~alias sttn funct_body anchor env smod =
if List.length sg' = List.length sg then md else
wrap_constraint env false md (Mty_signature sg')
Tmodtype_implicit
- | Pmod_functor(name, smty, sbody) ->
- let mty = Option.map (transl_modtype_functor_arg env) smty in
- let ty_arg = Option.map (fun m -> m.mty_type) mty in
- let scope = Ctype.create_scope () in
- let (id, newenv), funct_body =
- match ty_arg with
- | None -> (Ident.create_scoped ~scope "*", env), false
- | Some mty ->
- Env.enter_module ~scope ~arg:true name.txt Mp_present mty env,
- true
+ | Pmod_functor(arg_opt, sbody) ->
+ let t_arg, ty_arg, newenv, funct_body =
+ match arg_opt with
+ | Unit -> Unit, Types.Unit, env, false
+ | Named (name, smty) ->
+ let mty = transl_modtype_functor_arg env smty in
+ let scope = Ctype.create_scope () in
+ let (id, newenv) =
+ match name.txt with
+ | None -> None, env
+ | Some name ->
+ let id, newenv =
+ Env.enter_module ~scope ~arg:true name Mp_present mty.mty_type
+ env
+ in
+ Some id, newenv
+ in
+ Named (id, name, mty), Types.Named (id, mty.mty_type), newenv, true
in
let body = type_module sttn funct_body None newenv sbody in
- rm { mod_desc = Tmod_functor(id, name, mty, body);
- mod_type = Mty_functor(id, ty_arg, body.mod_type);
+ rm { mod_desc = Tmod_functor(t_arg, body);
+ mod_type = Mty_functor(ty_arg, body.mod_type);
mod_env = env;
mod_attributes = smod.pmod_attributes;
mod_loc = smod.pmod_loc }
@@ -1830,15 +1920,20 @@ and type_module_aux ~alias sttn funct_body anchor env smod =
let funct =
type_module (sttn && path <> None) funct_body None env sfunct in
begin match Env.scrape_alias env funct.mod_type with
- Mty_functor(param, mty_param, mty_res) as mty_functor ->
- let generative, mty_param =
- (mty_param = None, Btype.default_mty mty_param) in
- if generative then begin
- if sarg.pmod_desc <> Pmod_structure [] then
- raise (Error (sfunct.pmod_loc, env, Apply_generative));
- if funct_body && Mtype.contains_type env funct.mod_type then
- raise (Error (smod.pmod_loc, env, Not_allowed_in_functor_body));
- end;
+ | Mty_functor (Unit, mty_res) ->
+ if sarg.pmod_desc <> Pmod_structure [] then
+ raise (Error (sfunct.pmod_loc, env, Apply_generative));
+ if funct_body && Mtype.contains_type env funct.mod_type then
+ raise (Error (smod.pmod_loc, env, Not_allowed_in_functor_body));
+ (* FIXME: is this even needed? *)
+ check_well_formed_module env smod.pmod_loc
+ "the signature of this functor application" mty_res;
+ rm { mod_desc = Tmod_apply(funct, arg, Tcoerce_none);
+ mod_type = mty_res;
+ mod_env = env;
+ mod_attributes = smod.pmod_attributes;
+ mod_loc = smod.pmod_loc }
+ | Mty_functor (Named (param, mty_param), mty_res) as mty_functor ->
let coercion =
try
Includemod.modtypes ~loc:sarg.pmod_loc env arg.mod_type mty_param
@@ -1846,23 +1941,32 @@ and type_module_aux ~alias sttn funct_body anchor env smod =
raise(Error(sarg.pmod_loc, env, Not_included msg)) in
let mty_appl =
match path with
- Some path ->
+ | Some path ->
let scope = Ctype.create_scope () in
- Subst.modtype (Rescope scope)
- (Subst.add_module param path Subst.identity)
- mty_res
+ let subst =
+ match param with
+ | None -> Subst.identity
+ | Some p -> Subst.add_module p path Subst.identity
+ in
+ Subst.modtype (Rescope scope) subst mty_res
| None ->
- if generative then mty_res else
let env =
- Env.add_module ~arg:true param Mp_present arg.mod_type env
+ match param with
+ | None -> env
+ | Some param ->
+ Env.add_module ~arg:true param Mp_present arg.mod_type env
in
+ (* FIXME: I doubt the following is needed if param is None *)
check_well_formed_module env smod.pmod_loc
"the signature of this functor application" mty_res;
let nondep_mty =
- try Mtype.nondep_supertype env [param] mty_res
- with Ctype.Nondep_cannot_erase _ ->
- raise(Error(smod.pmod_loc, env,
- Cannot_eliminate_dependency mty_functor))
+ match param with
+ | None -> mty_res
+ | Some param ->
+ try Mtype.nondep_supertype env [param] mty_res
+ with Ctype.Nondep_cannot_erase _ ->
+ raise(Error(smod.pmod_loc, env,
+ Cannot_eliminate_dependency mty_functor))
in
begin match
Includemod.modtypes ~loc:smod.pmod_loc env mty_res nondep_mty
@@ -2096,17 +2200,22 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope =
in
(*prerr_endline (Ident.unique_toplevel_name id);*)
Mtype.lower_nongen outer_scope md.md_type;
- let id, newenv =
- Env.enter_module_declaration ~scope name.txt pres md env
+ let id, newenv, sg =
+ match name.txt with
+ | None -> None, env, []
+ | Some name ->
+ let id, e = Env.enter_module_declaration ~scope name pres md env in
+ Signature_names.check_module names pmb_loc id;
+ Some id, e,
+ [Sig_module(id, pres,
+ {md_type = modl.mod_type;
+ md_attributes = attrs;
+ md_loc = pmb_loc;
+ }, Trec_not, Exported)]
in
- Signature_names.check_module names pmb_loc id;
Tstr_module {mb_id=id; mb_name=name; mb_expr=modl;
mb_presence=pres; mb_attributes=attrs; mb_loc=pmb_loc; },
- [Sig_module(id, pres,
- {md_type = modl.mod_type;
- md_attributes = attrs;
- md_loc = pmb_loc;
- }, Trec_not, Exported)],
+ sg,
newenv
| Pstr_recmodule sbind ->
let sbind =
@@ -2131,7 +2240,8 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope =
pmd_attributes=attrs; pmd_loc=loc}) sbind
) in
List.iter
- Signature_names.(fun md -> check_module names md.md_loc md.md_id)
+ (fun md ->
+ Option.iter Signature_names.(check_module names md.md_loc) md.md_id)
decls;
let bindings1 =
List.map2
@@ -2144,35 +2254,42 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope =
)
in
let mty' =
- enrich_module_type anchor (Ident.name id) modl.mod_type newenv
+ enrich_module_type anchor name.txt modl.mod_type newenv
in
(id, name, mty, modl, mty', attrs, loc))
decls sbind in
let newenv = (* allow aliasing recursive modules from outside *)
List.fold_left
(fun env md ->
- let mdecl =
- {
- md_type = md.md_type.mty_type;
- md_attributes = md.md_attributes;
- md_loc = md.md_loc;
- }
- in
- Env.add_module_declaration ~check:true
- md.md_id Mp_present mdecl env
+ match md.md_id with
+ | None -> env
+ | Some id ->
+ let mdecl =
+ {
+ md_type = md.md_type.mty_type;
+ md_attributes = md.md_attributes;
+ md_loc = md.md_loc;
+ }
+ in
+ Env.add_module_declaration ~check:true
+ id Mp_present mdecl env
)
env decls
in
let bindings2 =
check_recmodule_inclusion newenv bindings1 in
+ let mbs =
+ List.filter_map (fun mb -> Option.map (fun id -> id, mb) mb.mb_id)
+ bindings2
+ in
Tstr_recmodule bindings2,
- map_rec (fun rs mb ->
- Sig_module(mb.mb_id, Mp_present, {
+ map_rec (fun rs (id, mb) ->
+ Sig_module(id, Mp_present, {
md_type=mb.mb_expr.mod_type;
md_attributes=mb.mb_attributes;
md_loc=mb.mb_loc;
}, rs, Exported))
- bindings2 [],
+ mbs [],
newenv
| Pstr_modtype pmtd ->
(* check that it is non-abstract *)
@@ -2313,7 +2430,7 @@ let rec normalize_modtype env = function
Mty_ident _
| Mty_alias _ -> ()
| Mty_signature sg -> normalize_signature env sg
- | Mty_functor(_id, _param, body) -> normalize_modtype env body
+ | Mty_functor(_param, body) -> normalize_modtype env body
and normalize_signature env = List.iter (normalize_signature_item env)