diff options
-rw-r--r-- | experimental/garrigue/generative-functors.diff | 1008 |
1 files changed, 1008 insertions, 0 deletions
diff --git a/experimental/garrigue/generative-functors.diff b/experimental/garrigue/generative-functors.diff new file mode 100644 index 000000000..c7786d11b --- /dev/null +++ b/experimental/garrigue/generative-functors.diff @@ -0,0 +1,1008 @@ +Index: boot/ocamlc +=================================================================== +Cannot display: file marked as a binary type. +svn:mime-type = application/octet-stream +Index: boot/ocamldep +=================================================================== +Cannot display: file marked as a binary type. +svn:mime-type = application/octet-stream +Index: boot/ocamllex +=================================================================== +Cannot display: file marked as a binary type. +svn:mime-type = application/octet-stream +Index: camlp4/Camlp4/Struct/Camlp4Ast2OCamlAst.ml +=================================================================== +--- camlp4/Camlp4/Struct/Camlp4Ast2OCamlAst.ml (revision 14301) ++++ camlp4/Camlp4/Struct/Camlp4Ast2OCamlAst.ml (working copy) +@@ -979,7 +979,7 @@ + [ <:module_type@loc<>> -> error loc "abstract/nil module type not allowed here" + | <:module_type@loc< $id:i$ >> -> mkmty loc (Pmty_ident (long_uident i)) + | <:module_type@loc< functor ($n$ : $nt$) -> $mt$ >> -> +- mkmty loc (Pmty_functor (with_loc n loc) (module_type nt) (module_type mt)) ++ mkmty loc (Pmty_functor (with_loc n loc) (Some (module_type nt)) (module_type mt)) + | <:module_type@loc< '$_$ >> -> error loc "module type variable not allowed here" + | <:module_type@loc< sig $sl$ end >> -> + mkmty loc (Pmty_signature (sig_item sl [])) +@@ -1051,7 +1051,7 @@ + | <:module_expr@loc< $me1$ $me2$ >> -> + mkmod loc (Pmod_apply (module_expr me1) (module_expr me2)) + | <:module_expr@loc< functor ($n$ : $mt$) -> $me$ >> -> +- mkmod loc (Pmod_functor (with_loc n loc) (module_type mt) (module_expr me)) ++ mkmod loc (Pmod_functor (with_loc n loc) (Some (module_type mt)) (module_expr me)) + | <:module_expr@loc< struct $sl$ end >> -> + mkmod loc (Pmod_structure (str_item sl [])) + | <:module_expr@loc< ($me$ : $mt$) >> -> +Index: camlp4/Camlp4Top/Rprint.ml +=================================================================== +--- camlp4/Camlp4Top/Rprint.ml (revision 14301) ++++ camlp4/Camlp4Top/Rprint.ml (working copy) +@@ -362,7 +362,10 @@ + | Omty_signature sg -> + fprintf ppf "@[<hv 2>sig@ %a@;<1 -2>end@]" + Toploop.print_out_signature.val sg +- | Omty_functor name mty_arg mty_res -> ++ | Omty_functor _ None mty_res -> ++ fprintf ppf "@[<2>functor@ () ->@ %a@]" ++ print_out_module_type mty_res ++ | Omty_functor name (Some mty_arg) mty_res -> + fprintf ppf "@[<2>functor@ (%s : %a) ->@ %a@]" name + print_out_module_type mty_arg print_out_module_type mty_res + | Omty_abstract -> () ] +Index: camlp4/boot/Camlp4.ml +=================================================================== +--- camlp4/boot/Camlp4.ml (revision 14301) ++++ camlp4/boot/Camlp4.ml (working copy) +@@ -15633,7 +15633,7 @@ + | Ast.MtId (loc, i) -> mkmty loc (Pmty_ident (long_uident i)) + | Ast.MtFun (loc, n, nt, mt) -> + mkmty loc +- (Pmty_functor ((with_loc n loc), (module_type nt), ++ (Pmty_functor ((with_loc n loc), Some (module_type nt), + (module_type mt))) + | Ast.MtQuo (loc, _) -> + error loc "module type variable not allowed here" +@@ -15775,7 +15775,7 @@ + (Pmod_apply ((module_expr me1), (module_expr me2))) + | Ast.MeFun (loc, n, mt, me) -> + mkmod loc +- (Pmod_functor ((with_loc n loc), (module_type mt), ++ (Pmod_functor ((with_loc n loc), Some (module_type mt), + (module_expr me))) + | Ast.MeStr (loc, sl) -> + mkmod loc (Pmod_structure (str_item sl [])) +Index: ocamldoc/odoc_ast.ml +=================================================================== +--- ocamldoc/odoc_ast.ml (revision 14301) ++++ ocamldoc/odoc_ast.ml (working copy) +@@ -1606,18 +1606,25 @@ + + | (Parsetree.Pmod_functor (_, pmodule_type, p_module_expr2), + Typedtree.Tmod_functor (ident, _, mtyp, tt_module_expr2)) -> +- let loc_start = pmodule_type.Parsetree.pmty_loc.Location.loc_start.Lexing.pos_cnum in +- let loc_end = pmodule_type.Parsetree.pmty_loc.Location.loc_end.Lexing.pos_cnum in ++ let loc = match pmodule_type with None -> Location.none ++ | Some pmty -> pmty.Parsetree.pmty_loc in ++ let loc_start = loc.Location.loc_start.Lexing.pos_cnum in ++ let loc_end = loc.Location.loc_end.Lexing.pos_cnum in + let mp_type_code = get_string_of_file loc_start loc_end in + print_DEBUG (Printf.sprintf "mp_type_code=%s" mp_type_code); + let mp_name = Name.from_ident ident in +- let mp_kind = Sig.analyse_module_type_kind env +- current_module_name pmodule_type mtyp.mty_type ++ let mp_kind = ++ match pmodule_type, mtyp with ++ Some pmty, Some mty -> ++ Sig.analyse_module_type_kind env current_module_name pmty ++ mty.mty_type ++ | _ -> Module_type_struct [] + in + let param = + { + mp_name = mp_name ; +- mp_type = Odoc_env.subst_module_type env mtyp.mty_type ; ++ mp_type = Misc.may_map ++ (fun m -> Odoc_env.subst_module_type env m.mty_type) mtyp ; + mp_type_code = mp_type_code ; + mp_kind = mp_kind ; + } +Index: ocamldoc/odoc_env.ml +=================================================================== +--- ocamldoc/odoc_env.ml (revision 14301) ++++ ocamldoc/odoc_env.ml (working copy) +@@ -223,7 +223,7 @@ + | Types.Mty_signature _ -> + t + | Types.Mty_functor (id, mt1, mt2) -> +- Types.Mty_functor (id, iter mt1, iter mt2) ++ Types.Mty_functor (id, Misc.may_map iter mt1, iter mt2) + in + iter t + +Index: ocamldoc/odoc_html.ml +=================================================================== +--- ocamldoc/odoc_html.ml (revision 14301) ++++ ocamldoc/odoc_html.ml (working copy) +@@ -1384,7 +1384,8 @@ + + (** Print html code to display the type of a module parameter.. *) + method html_of_module_parameter_type b m_name p = +- self#html_of_module_type b m_name ~code: p.mp_type_code p.mp_type ++ match p.mp_type with None -> bs b "<code>()</code>" ++ | Some mty -> self#html_of_module_type b m_name ~code: p.mp_type_code mty + + (** Generate a file containing the module type in the given file name. *) + method output_module_type in_title file mtyp = +Index: ocamldoc/odoc_info.mli +=================================================================== +--- ocamldoc/odoc_info.mli (revision 14301) ++++ ocamldoc/odoc_info.mli (working copy) +@@ -434,7 +434,7 @@ + + and module_parameter = Odoc_module.module_parameter = { + mp_name : string ; (** the name *) +- mp_type : Types.module_type ; (** the type *) ++ mp_type : Types.module_type option ; (** the type *) + mp_type_code : string ; (** the original code *) + mp_kind : module_type_kind ; (** the way the parameter was built *) + } +Index: ocamldoc/odoc_man.ml +=================================================================== +--- ocamldoc/odoc_man.ml (revision 14301) ++++ ocamldoc/odoc_man.ml (working copy) +@@ -612,7 +612,7 @@ + (fun (p, desc_opt) -> + bs b ".sp\n"; + bs b ("\""^p.mp_name^"\"\n"); +- self#man_of_module_type b m_name p.mp_type; ++ Misc.may (self#man_of_module_type b m_name) p.mp_type; + bs b "\n"; + ( + match desc_opt with +Index: ocamldoc/odoc_module.ml +=================================================================== +--- ocamldoc/odoc_module.ml (revision 14301) ++++ ocamldoc/odoc_module.ml (working copy) +@@ -46,7 +46,7 @@ + + and module_parameter = { + mp_name : string ; (** the name *) +- mp_type : Types.module_type ; (** the type *) ++ mp_type : Types.module_type option ; (** the type *) + mp_type_code : string ; (** the original code *) + mp_kind : module_type_kind ; (** the way the parameter was built *) + } +Index: ocamldoc/odoc_print.ml +=================================================================== +--- ocamldoc/odoc_print.ml (revision 14301) ++++ ocamldoc/odoc_print.ml (working copy) +@@ -62,7 +62,7 @@ + | Some s -> raise (Use_code s) + ) + | Types.Mty_functor (id, mt1, mt2) -> +- Types.Mty_functor (id, iter mt1, iter mt2) ++ Types.Mty_functor (id, Misc.may_map iter mt1, iter mt2) + in + iter t + +Index: ocamldoc/odoc_sig.ml +=================================================================== +--- ocamldoc/odoc_sig.ml (revision 14301) ++++ ocamldoc/odoc_sig.ml (working copy) +@@ -1082,19 +1082,26 @@ + + | Parsetree.Pmty_functor (_, pmodule_type2, module_type2) -> + ( +- let loc_start = pmodule_type2.Parsetree.pmty_loc.Location.loc_start.Lexing.pos_cnum in +- let loc_end = pmodule_type2.Parsetree.pmty_loc.Location.loc_end.Lexing.pos_cnum in ++ let loc = match pmodule_type2 with None -> Location.none ++ | Some pmty -> pmty.Parsetree.pmty_loc in ++ let loc_start = loc.Location.loc_start.Lexing.pos_cnum in ++ let loc_end = loc.Location.loc_end.Lexing.pos_cnum in + let mp_type_code = get_string_of_file loc_start loc_end in + print_DEBUG (Printf.sprintf "mp_type_code=%s" mp_type_code); + match sig_module_type with + Types.Mty_functor (ident, param_module_type, body_module_type) -> +- let mp_kind = analyse_module_type_kind env +- current_module_name pmodule_type2 param_module_type ++ let mp_kind = ++ match pmodule_type2, param_module_type with ++ Some pmty, Some mty -> ++ analyse_module_type_kind env current_module_name pmty mty ++ | _ -> Module_type_struct [] + in + let param = + { + mp_name = Name.from_ident ident ; +- mp_type = Odoc_env.subst_module_type env param_module_type ; ++ mp_type = ++ Misc.may_map (Odoc_env.subst_module_type env) ++ param_module_type; + mp_type_code = mp_type_code ; + mp_kind = mp_kind ; + } +@@ -1161,17 +1168,23 @@ + ( + match sig_module_type with + Types.Mty_functor (ident, param_module_type, body_module_type) -> +- let loc_start = pmodule_type2.Parsetree.pmty_loc.Location.loc_start.Lexing.pos_cnum in +- let loc_end = pmodule_type2.Parsetree.pmty_loc.Location.loc_end.Lexing.pos_cnum in ++ let loc = match pmodule_type2 with None -> Location.none ++ | Some pmty -> pmty.Parsetree.pmty_loc in ++ let loc_start = loc.Location.loc_start.Lexing.pos_cnum in ++ let loc_end = loc.Location.loc_end.Lexing.pos_cnum in + let mp_type_code = get_string_of_file loc_start loc_end in + print_DEBUG (Printf.sprintf "mp_type_code=%s" mp_type_code); +- let mp_kind = analyse_module_type_kind env +- current_module_name pmodule_type2 param_module_type ++ let mp_kind = ++ match pmodule_type2, param_module_type with ++ Some pmty, Some mty -> ++ analyse_module_type_kind env current_module_name pmty mty ++ | _ -> Module_type_struct [] + in + let param = + { + mp_name = Name.from_ident ident ; +- mp_type = Odoc_env.subst_module_type env param_module_type ; ++ mp_type = Misc.may_map ++ (Odoc_env.subst_module_type env) param_module_type ; + mp_type_code = mp_type_code ; + mp_kind = mp_kind ; + } +Index: ocamldoc/odoc_to_text.ml +=================================================================== +--- ocamldoc/odoc_to_text.ml (revision 14301) ++++ ocamldoc/odoc_to_text.ml (working copy) +@@ -428,8 +428,11 @@ + List + (List.map + (fun (p, desc_opt) -> +- [Code (p.mp_name^" : ")] @ +- (self#text_of_module_type p.mp_type) @ ++ begin match p.mp_type with None -> [Raw ""] ++ | Some mty -> ++ [Code (p.mp_name^" : ")] @ ++ (self#text_of_module_type mty) ++ end @ + (match desc_opt with + None -> [] + | Some t -> (Raw " ") :: t) +Index: parsing/ast_helper.mli +=================================================================== +--- parsing/ast_helper.mli (revision 14301) ++++ parsing/ast_helper.mli (working copy) +@@ -145,7 +145,8 @@ + + val ident: ?loc:loc -> ?attrs:attrs -> lid -> module_type + val signature: ?loc:loc -> ?attrs:attrs -> signature -> module_type +- val functor_: ?loc:loc -> ?attrs:attrs -> str -> module_type -> module_type -> module_type ++ val functor_: ?loc:loc -> ?attrs:attrs -> ++ str -> module_type option -> module_type -> module_type + val with_: ?loc:loc -> ?attrs:attrs -> module_type -> with_constraint list -> module_type + val typeof_: ?loc:loc -> ?attrs:attrs -> module_expr -> module_type + val extension: ?loc:loc -> ?attrs:attrs -> extension -> module_type +@@ -159,7 +160,8 @@ + + val ident: ?loc:loc -> ?attrs:attrs -> lid -> module_expr + val structure: ?loc:loc -> ?attrs:attrs -> structure -> module_expr +- val functor_: ?loc:loc -> ?attrs:attrs -> str -> module_type -> module_expr -> module_expr ++ val functor_: ?loc:loc -> ?attrs:attrs -> ++ str -> module_type option -> module_expr -> module_expr + val apply: ?loc:loc -> ?attrs:attrs -> module_expr -> module_expr -> module_expr + val constraint_: ?loc:loc -> ?attrs:attrs -> module_expr -> module_type -> module_expr + val unpack: ?loc:loc -> ?attrs:attrs -> expression -> module_expr +Index: parsing/ast_mapper.ml +=================================================================== +--- parsing/ast_mapper.ml (revision 14301) ++++ parsing/ast_mapper.ml (working copy) +@@ -161,7 +161,8 @@ + | Pmty_ident s -> ident ~loc ~attrs (map_loc sub s) + | Pmty_signature sg -> signature ~loc ~attrs (sub.signature sub sg) + | Pmty_functor (s, mt1, mt2) -> +- functor_ ~loc ~attrs (map_loc sub s) (sub.module_type sub mt1) ++ functor_ ~loc ~attrs (map_loc sub s) ++ (Misc.may_map (sub.module_type sub) mt1) + (sub.module_type sub mt2) + | Pmty_with (mt, l) -> + with_ ~loc ~attrs (sub.module_type sub mt) +@@ -213,7 +214,8 @@ + | Pmod_ident x -> ident ~loc ~attrs (map_loc sub x) + | Pmod_structure str -> structure ~loc ~attrs (sub.structure sub str) + | Pmod_functor (arg, arg_ty, body) -> +- functor_ ~loc ~attrs (map_loc sub arg) (sub.module_type sub arg_ty) ++ functor_ ~loc ~attrs (map_loc sub arg) ++ (Misc.may_map (sub.module_type sub) arg_ty) + (sub.module_expr sub body) + | Pmod_apply (m1, m2) -> + apply ~loc ~attrs (sub.module_expr sub m1) (sub.module_expr sub m2) +Index: parsing/parser.mly +=================================================================== +--- parsing/parser.mly (revision 14301) ++++ parsing/parser.mly (working copy) +@@ -541,9 +541,13 @@ + | STRUCT structure error + { unclosed "struct" 1 "end" 3 } + | FUNCTOR LPAREN UIDENT COLON module_type RPAREN MINUSGREATER module_expr +- { mkmod(Pmod_functor(mkrhs $3 3, $5, $8)) } ++ { mkmod(Pmod_functor(mkrhs $3 3, Some $5, $8)) } ++ | FUNCTOR LPAREN RPAREN MINUSGREATER module_expr ++ { mkmod(Pmod_functor(mkrhs "()" 3, None, $5)) } + | module_expr LPAREN module_expr RPAREN + { mkmod(Pmod_apply($1, $3)) } ++ | module_expr LPAREN RPAREN ++ { mkmod(Pmod_apply($1, mkmod (Pmod_structure []))) } + | module_expr LPAREN module_expr error + { unclosed "(" 2 ")" 4 } + | LPAREN module_expr COLON module_type RPAREN +@@ -640,7 +644,9 @@ + | COLON module_type EQUAL module_expr + { mkmod(Pmod_constraint($4, $2)) } + | LPAREN UIDENT COLON module_type RPAREN module_binding_body +- { mkmod(Pmod_functor(mkrhs $2 2, $4, $6)) } ++ { mkmod(Pmod_functor(mkrhs $2 2, Some $4, $6)) } ++ | LPAREN RPAREN module_binding_body ++ { mkmod(Pmod_functor(mkrhs "()" 1, None, $3)) } + ; + module_bindings: + module_binding { [$1] } +@@ -662,7 +668,10 @@ + { unclosed "sig" 1 "end" 3 } + | FUNCTOR LPAREN UIDENT COLON module_type RPAREN MINUSGREATER module_type + %prec below_WITH +- { mkmty(Pmty_functor(mkrhs $3 3, $5, $8)) } ++ { mkmty(Pmty_functor(mkrhs $3 3, Some $5, $8)) } ++ | FUNCTOR LPAREN RPAREN MINUSGREATER module_type ++ %prec below_WITH ++ { mkmty(Pmty_functor(mkrhs "()" 2, None, $5)) } + | module_type WITH with_constraints + { mkmty(Pmty_with($1, List.rev $3)) } + | MODULE TYPE OF module_expr %prec below_LBRACKETAT +@@ -724,7 +733,9 @@ + COLON module_type + { $2 } + | LPAREN UIDENT COLON module_type RPAREN module_declaration +- { mkmty(Pmty_functor(mkrhs $2 2, $4, $6)) } ++ { mkmty(Pmty_functor(mkrhs $2 2, Some $4, $6)) } ++ | LPAREN RPAREN module_declaration ++ { mkmty(Pmty_functor(mkrhs "()" 1, None, $3)) } + ; + module_rec_declarations: + module_rec_declaration { [$1] } +Index: parsing/parsetree.mli +=================================================================== +--- parsing/parsetree.mli (revision 14301) ++++ parsing/parsetree.mli (working copy) +@@ -543,7 +543,7 @@ + (* S *) + | Pmty_signature of signature + (* sig ... end *) +- | Pmty_functor of string loc * module_type * module_type ++ | Pmty_functor of string loc * module_type option * module_type + (* functor(X : MT1) -> MT2 *) + | Pmty_with of module_type * with_constraint list + (* MT with ... *) +@@ -637,7 +637,7 @@ + (* X *) + | Pmod_structure of structure + (* struct ... end *) +- | Pmod_functor of string loc * module_type * module_expr ++ | Pmod_functor of string loc * module_type option * module_expr + (* functor(X : MT1) -> ME *) + | Pmod_apply of module_expr * module_expr + (* ME1(ME2) *) +Index: parsing/pprintast.ml +=================================================================== +--- parsing/pprintast.ml (revision 14301) ++++ parsing/pprintast.ml (working copy) +@@ -834,7 +834,9 @@ + | Pmty_signature (s) -> + pp f "@[<hv0>@[<hv2>sig@ %a@]@ end@]" (* "@[<hov>sig@ %a@ end@]" *) + (self#list self#signature_item ) s (* FIXME wrong indentation*) +- | Pmty_functor (s, mt1, mt2) -> ++ | Pmty_functor (_, None, mt2) -> ++ pp f "@[<hov2>functor () ->@ %a@]" self#module_type mt2 ++ | Pmty_functor (s, Some mt1, mt2) -> + pp f "@[<hov2>functor@ (%s@ :@ %a)@ ->@ %a@]" s.txt + self#module_type mt1 self#module_type mt2 + | Pmty_with (mt, l) -> +@@ -940,7 +942,9 @@ + self#module_type mt + | Pmod_ident (li) -> + pp f "%a" self#longident_loc li; +- | Pmod_functor (s, mt, me) -> ++ | Pmod_functor (_, None, me) -> ++ pp f "functor ()@;->@;%a" self#module_expr me ++ | Pmod_functor (s, Some mt, me) -> + pp f "functor@ (%s@ :@ %a)@;->@;%a" + s.txt self#module_type mt self#module_expr me + | Pmod_apply (me1, me2) -> +@@ -1025,7 +1029,8 @@ + | Pstr_module x -> + let rec module_helper me = match me.pmod_desc with + | Pmod_functor(s,mt,me) -> +- pp f "(%s:%a)" s.txt self#module_type mt ; ++ if mt = None then pp f "()" ++ else Misc.may (pp f "(%s:%a)" s.txt self#module_type) mt; + module_helper me + | _ -> me in + pp f "@[<hov2>module %s%a@]" +Index: parsing/printast.ml +=================================================================== +--- parsing/printast.ml (revision 14301) ++++ parsing/printast.ml (working copy) +@@ -576,7 +576,7 @@ + signature i ppf s; + | Pmty_functor (s, mt1, mt2) -> + line i ppf "Pmty_functor %a\n" fmt_string_loc s; +- module_type i ppf mt1; ++ Misc.may (module_type i ppf) mt1; + module_type i ppf mt2; + | Pmty_with (mt, l) -> + line i ppf "Pmty_with\n"; +@@ -670,7 +670,7 @@ + structure i ppf s; + | Pmod_functor (s, mt, me) -> + line i ppf "Pmod_functor %a\n" fmt_string_loc s; +- module_type i ppf mt; ++ Misc.may (module_type i ppf) mt; + module_expr i ppf me; + | Pmod_apply (me1, me2) -> + line i ppf "Pmod_apply\n"; +Index: tools/depend.ml +=================================================================== +--- tools/depend.ml (revision 14301) ++++ tools/depend.ml (working copy) +@@ -201,7 +201,8 @@ + Pmty_ident l -> add bv l + | Pmty_signature s -> add_signature bv s + | Pmty_functor(id, mty1, mty2) -> +- add_modtype bv mty1; add_modtype (StringSet.add id.txt bv) mty2 ++ Misc.may (add_modtype bv) mty1; ++ add_modtype (StringSet.add id.txt bv) mty2 + | Pmty_with(mty, cstrl) -> + add_modtype bv mty; + List.iter +@@ -258,7 +259,7 @@ + Pmod_ident l -> addmodule bv l + | Pmod_structure s -> ignore (add_structure bv s) + | Pmod_functor(id, mty, modl) -> +- add_modtype bv mty; ++ Misc.may (add_modtype bv) mty; + add_module (StringSet.add id.txt bv) modl + | Pmod_apply(mod1, mod2) -> + add_module bv mod1; add_module bv mod2 +Index: tools/tast_iter.ml +=================================================================== +--- tools/tast_iter.ml (revision 14301) ++++ tools/tast_iter.ml (working copy) +@@ -193,7 +193,7 @@ + | Tmty_ident (_path, _) -> () + | Tmty_signature sg -> sub # signature sg + | Tmty_functor (_id, _, mtype1, mtype2) -> +- sub # module_type mtype1; sub # module_type mtype2 ++ Misc.may (sub # module_type) mtype1; sub # module_type mtype2 + | Tmty_with (mtype, list) -> + sub # module_type mtype; + List.iter (fun (_, _, withc) -> sub # with_constraint withc) list +@@ -212,7 +212,7 @@ + | Tmod_ident (_p, _) -> () + | Tmod_structure st -> sub # structure st + | Tmod_functor (_id, _, mtype, mexpr) -> +- sub # module_type mtype; ++ Misc.may (sub # module_type) mtype; + sub # module_expr mexpr + | Tmod_apply (mexp1, mexp2, _) -> + sub # module_expr mexp1; +Index: tools/untypeast.ml +=================================================================== +--- tools/untypeast.ml (revision 14301) ++++ tools/untypeast.ml (working copy) +@@ -376,7 +376,7 @@ + Tmty_ident (_path, lid) -> Pmty_ident (lid) + | Tmty_signature sg -> Pmty_signature (untype_signature sg) + | Tmty_functor (_id, name, mtype1, mtype2) -> +- Pmty_functor (name, untype_module_type mtype1, ++ Pmty_functor (name, Misc.may_map untype_module_type mtype1, + untype_module_type mtype2) + | Tmty_with (mtype, list) -> + Pmty_with (untype_module_type mtype, +@@ -405,7 +405,7 @@ + Tmod_ident (_p, lid) -> Pmod_ident (lid) + | Tmod_structure st -> Pmod_structure (untype_structure st) + | Tmod_functor (_id, name, mtype, mexpr) -> +- Pmod_functor (name, untype_module_type mtype, ++ Pmod_functor (name, Misc.may_map untype_module_type mtype, + untype_module_expr mexpr) + | Tmod_apply (mexp1, mexp2, _) -> + Pmod_apply (untype_module_expr mexp1, untype_module_expr mexp2) +Index: typing/btype.ml +=================================================================== +--- typing/btype.ml (revision 14301) ++++ typing/btype.ml (working copy) +@@ -56,6 +56,9 @@ + let is_Tunivar = function {desc=Tunivar _} -> true | _ -> false + + let dummy_method = "*dummy method*" ++let default_mty = function ++ Some mty -> mty ++ | None -> Mty_signature [] + + (**** Representative of a type ****) + +Index: typing/btype.mli +=================================================================== +--- typing/btype.mli (revision 14301) ++++ typing/btype.mli (working copy) +@@ -39,9 +39,12 @@ + (* Return a fresh marked generic variable *) + *) + ++(**** Types ****) ++ + val is_Tvar: type_expr -> bool + val is_Tunivar: type_expr -> bool + val dummy_method: label ++val default_mty: module_type option -> module_type + + val repr: type_expr -> type_expr + (* Return the canonical representative of a type. *) +Index: typing/env.ml +=================================================================== +--- typing/env.ml (revision 14301) ++++ typing/env.ml (working copy) +@@ -201,7 +201,7 @@ + + and functor_components = { + fcomp_param: Ident.t; (* Formal parameter *) +- fcomp_arg: module_type; (* Argument signature *) ++ fcomp_arg: module_type option; (* Argument signature *) + fcomp_res: module_type; (* Result signature *) + fcomp_env: t; (* Environment in which the result signature makes sense *) + fcomp_subst: Subst.t; (* Prefixing substitution for the result signature *) +@@ -522,7 +522,7 @@ + let (p2, {md_type=mty2}) = lookup_module l2 env in + begin match EnvLazy.force !components_of_module_maker' desc1 with + Functor_comps f -> +- !check_modtype_inclusion env mty2 p2 f.fcomp_arg; ++ Misc.may (!check_modtype_inclusion env mty2 p2) f.fcomp_arg; + (Papply(p1, p2), !components_of_functor_appl' f p1 p2) + | Structure_comps c -> + raise Not_found +@@ -562,7 +562,7 @@ + let p = Papply(p1, p2) in + begin match EnvLazy.force !components_of_module_maker' desc1 with + Functor_comps f -> +- !check_modtype_inclusion env mty2 p2 f.fcomp_arg; ++ Misc.may (!check_modtype_inclusion env mty2 p2) f.fcomp_arg; + let mty = + Subst.modtype (Subst.add_module f.fcomp_param p2 f.fcomp_subst) + f.fcomp_res in +@@ -1120,7 +1120,7 @@ + fcomp_param = param; + (* fcomp_arg must be prefixed eagerly, because it is interpreted + in the outer environment, not in env *) +- fcomp_arg = Subst.modtype sub ty_arg; ++ fcomp_arg = may_map (Subst.modtype sub) ty_arg; + (* fcomp_res is prefixed lazily, because it is interpreted in env *) + fcomp_res = ty_res; + fcomp_env = env; +Index: typing/includemod.ml +=================================================================== +--- typing/includemod.ml (revision 14301) ++++ typing/includemod.ml (working copy) +@@ -168,7 +168,13 @@ + try_modtypes2 env cxt mty1 (Subst.modtype subst mty2) + | (Mty_signature sig1, Mty_signature sig2) -> + signatures env cxt subst sig1 sig2 +- | (Mty_functor(param1, arg1, res1), Mty_functor(param2, arg2, res2)) -> ++ | (Mty_functor(param1, None, res1), Mty_functor(param2, None, res2)) -> ++ begin match modtypes env (Body param1::cxt) subst res1 res2 with ++ Tcoerce_none -> Tcoerce_none ++ | cc -> Tcoerce_functor (Tcoerce_none, cc) ++ end ++ | (Mty_functor(param1, Some arg1, res1), ++ Mty_functor(param2, Some arg2, res2)) -> + let arg2' = Subst.modtype subst arg2 in + let cc_arg = modtypes env (Arg param1::cxt) Subst.identity arg2' arg1 in + let cc_res = +Index: typing/mtype.ml +=================================================================== +--- typing/mtype.ml (revision 14301) ++++ typing/mtype.ml (working copy) +@@ -34,7 +34,8 @@ + 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 +@@ -105,8 +106,9 @@ + | 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 param (Btype.default_mty arg) env) va res) + + and nondep_sig env va = function + [] -> [] +@@ -228,3 +230,34 @@ + 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 ++ ++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 +Index: typing/mtype.mli +=================================================================== +--- typing/mtype.mli (revision 14301) ++++ typing/mtype.mli (working copy) +@@ -36,3 +36,4 @@ + val enrich_modtype: Env.t -> Path.t -> module_type -> module_type + val enrich_typedecl: Env.t -> Path.t -> type_declaration -> type_declaration + val type_paths: Env.t -> Path.t -> module_type -> Path.t list ++val contains_type: Env.t -> module_type -> bool +Index: typing/oprint.ml +=================================================================== +--- typing/oprint.ml (revision 14301) ++++ typing/oprint.ml (working copy) +@@ -344,7 +344,9 @@ + let rec print_out_module_type ppf = + function + Omty_abstract -> () +- | Omty_functor (name, mty_arg, mty_res) -> ++ | Omty_functor (_, None, mty_res) -> ++ fprintf ppf "@[<2>functor@ () ->@ %a@]" print_out_module_type mty_res ++ | Omty_functor (name, Some mty_arg, mty_res) -> + fprintf ppf "@[<2>functor@ (%s : %a) ->@ %a@]" name + print_out_module_type mty_arg print_out_module_type mty_res + | Omty_ident id -> fprintf ppf "%a" print_ident id +Index: typing/outcometree.mli +=================================================================== +--- typing/outcometree.mli (revision 14301) ++++ typing/outcometree.mli (working copy) +@@ -75,7 +75,7 @@ + + type out_module_type = + | Omty_abstract +- | Omty_functor of string * out_module_type * out_module_type ++ | Omty_functor of string * out_module_type option * out_module_type + | Omty_ident of out_ident + | Omty_signature of out_sig_item list + and out_sig_item = +Index: typing/printtyp.ml +=================================================================== +--- typing/printtyp.ml (revision 14301) ++++ typing/printtyp.ml (working copy) +@@ -1116,9 +1116,12 @@ + | Mty_signature sg -> + Omty_signature (tree_of_signature sg) + | Mty_functor(param, ty_arg, ty_res) -> +- Omty_functor +- (Ident.name param, tree_of_modtype ty_arg, +- wrap_env (Env.add_module param ty_arg) tree_of_modtype ty_res) ++ let res = ++ match ty_arg with None -> tree_of_modtype ty_res ++ | Some mty -> ++ wrap_env (Env.add_module param mty) tree_of_modtype ty_res ++ in ++ Omty_functor (Ident.name param, may_map tree_of_modtype ty_arg, res) + + and tree_of_signature sg = + wrap_env (fun env -> env) (tree_of_signature_rec !printing_env) sg +Index: typing/printtyped.ml +=================================================================== +--- typing/printtyped.ml (revision 14301) ++++ typing/printtyped.ml (working copy) +@@ -562,7 +562,7 @@ + signature i ppf s; + | Tmty_functor (s, _, mt1, mt2) -> + line i ppf "Pmty_functor \"%a\"\n" fmt_ident s; +- module_type i ppf mt1; ++ Misc.may (module_type i ppf) mt1; + module_type i ppf mt2; + | Tmty_with (mt, l) -> + line i ppf "Pmty_with\n"; +@@ -651,7 +651,7 @@ + structure i ppf s; + | Tmod_functor (s, _, mt, me) -> + line i ppf "Pmod_functor \"%a\"\n" fmt_ident s; +- module_type i ppf mt; ++ Misc.may (module_type i ppf) mt; + module_expr i ppf me; + | Tmod_apply (me1, me2, _) -> + line i ppf "Pmod_apply\n"; +Index: typing/subst.ml +=================================================================== +--- typing/subst.ml (revision 14301) ++++ typing/subst.ml (working copy) +@@ -327,8 +327,8 @@ + Mty_signature(signature s sg) + | Mty_functor(id, arg, res) -> + let id' = Ident.rename id in +- Mty_functor(id', modtype s arg, +- modtype (add_module id (Pident id') s) res) ++ Mty_functor(id', may_map (modtype s) arg, ++ modtype (add_module id (Pident id') s) res) + + and signature s sg = + (* Components of signature may be mutually recursive (e.g. type declarations +Index: typing/typedtree.ml +=================================================================== +--- typing/typedtree.ml (revision 14301) ++++ typing/typedtree.ml (working copy) +@@ -187,7 +187,7 @@ + and module_expr_desc = + Tmod_ident of Path.t * Longident.t loc + | Tmod_structure of structure +- | Tmod_functor of Ident.t * string loc * module_type * module_expr ++ | Tmod_functor of Ident.t * string loc * module_type option * module_expr + | Tmod_apply of module_expr * module_expr * module_coercion + | Tmod_constraint of + module_expr * Types.module_type * module_type_constraint * module_coercion +@@ -253,7 +253,7 @@ + and module_type_desc = + Tmty_ident of Path.t * Longident.t loc + | Tmty_signature of signature +- | Tmty_functor of Ident.t * string loc * module_type * module_type ++ | Tmty_functor of Ident.t * string loc * module_type option * module_type + | Tmty_with of module_type * (Path.t * Longident.t loc * with_constraint) list + | Tmty_typeof of module_expr + +Index: typing/typedtree.mli +=================================================================== +--- typing/typedtree.mli (revision 14301) ++++ typing/typedtree.mli (working copy) +@@ -186,7 +186,7 @@ + and module_expr_desc = + Tmod_ident of Path.t * Longident.t loc + | Tmod_structure of structure +- | Tmod_functor of Ident.t * string loc * module_type * module_expr ++ | Tmod_functor of Ident.t * string loc * module_type option * module_expr + | Tmod_apply of module_expr * module_expr * module_coercion + | Tmod_constraint of + module_expr * Types.module_type * module_type_constraint * module_coercion +@@ -252,7 +252,7 @@ + and module_type_desc = + Tmty_ident of Path.t * Longident.t loc + | Tmty_signature of signature +- | Tmty_functor of Ident.t * string loc * module_type * module_type ++ | Tmty_functor of Ident.t * string loc * module_type option * module_type + | Tmty_with of module_type * (Path.t * Longident.t loc * with_constraint) list + | Tmty_typeof of module_expr + +Index: typing/typedtreeIter.ml +=================================================================== +--- typing/typedtreeIter.ml (revision 14301) ++++ typing/typedtreeIter.ml (working copy) +@@ -383,7 +383,7 @@ + Tmty_ident (path, _) -> () + | Tmty_signature sg -> iter_signature sg + | Tmty_functor (id, _, mtype1, mtype2) -> +- iter_module_type mtype1; iter_module_type mtype2 ++ Misc.may iter_module_type mtype1; iter_module_type mtype2 + | Tmty_with (mtype, list) -> + iter_module_type mtype; + List.iter (fun (path, _, withc) -> +@@ -412,7 +412,7 @@ + Tmod_ident (p, _) -> () + | Tmod_structure st -> iter_structure st + | Tmod_functor (id, _, mtype, mexpr) -> +- iter_module_type mtype; ++ Misc.may iter_module_type mtype; + iter_module_expr mexpr + | Tmod_apply (mexp1, mexp2, _) -> + iter_module_expr mexp1; +Index: typing/typedtreeMap.ml +=================================================================== +--- typing/typedtreeMap.ml (revision 14301) ++++ typing/typedtreeMap.ml (working copy) +@@ -426,7 +426,7 @@ + Tmty_ident (path, lid) -> mty.mty_desc + | Tmty_signature sg -> Tmty_signature (map_signature sg) + | Tmty_functor (id, name, mtype1, mtype2) -> +- Tmty_functor (id, name, map_module_type mtype1, ++ Tmty_functor (id, name, Misc.may_map map_module_type mtype1, + map_module_type mtype2) + | Tmty_with (mtype, list) -> + Tmty_with (map_module_type mtype, +@@ -456,7 +456,7 @@ + Tmod_ident (p, lid) -> mexpr.mod_desc + | Tmod_structure st -> Tmod_structure (map_structure st) + | Tmod_functor (id, name, mtype, mexpr) -> +- Tmod_functor (id, name, map_module_type mtype, ++ Tmod_functor (id, name, Misc.may_map map_module_type mtype, + map_module_expr mexpr) + | Tmod_apply (mexp1, mexp2, coercion) -> + Tmod_apply (map_module_expr mexp1, map_module_expr mexp2, coercion) +Index: typing/typemod.ml +=================================================================== +--- typing/typemod.ml (revision 14301) ++++ typing/typemod.ml (working copy) +@@ -39,6 +39,7 @@ + | Scoping_pack of Longident.t * type_expr + | Extension of string + | Recursive_module_require_explicit_type ++ | Apply_generative + + exception Error of Location.t * Env.t * error + +@@ -299,8 +300,9 @@ + | Pmty_signature ssg -> + Mty_signature(approx_sig env ssg) + | Pmty_functor(param, sarg, sres) -> +- let arg = approx_modtype env sarg in +- let (id, newenv) = Env.enter_module param.txt arg env in ++ let arg = may_map (approx_modtype env) sarg in ++ let (id, newenv) = ++ Env.enter_module param.txt (Btype.default_mty arg) env in + let res = approx_modtype newenv sres in + Mty_functor(id, arg, res) + | Pmty_with(sbody, constraints) -> +@@ -472,11 +474,13 @@ + mkmty (Tmty_signature sg) (Mty_signature sg.sig_type) env loc + smty.pmty_attributes + | Pmty_functor(param, sarg, sres) -> +- let arg = transl_modtype env sarg in +- let (id, newenv) = Env.enter_module param.txt arg.mty_type env in ++ let arg = Misc.may_map (transl_modtype env) sarg in ++ let ty_arg = Misc.may_map (fun m -> m.mty_type) arg in ++ let (id, newenv) = ++ Env.enter_module param.txt (Btype.default_mty ty_arg) env in + let res = transl_modtype newenv sres in + mkmty (Tmty_functor (id, param, arg, res)) +- (Mty_functor(id, arg.mty_type, res.mty_type)) env loc ++ (Mty_functor(id, ty_arg, res.mty_type)) env loc + smty.pmty_attributes + | Pmty_with(sbody, constraints) -> + let body = transl_modtype env sbody in +@@ -949,11 +953,14 @@ + mod_attributes = smod.pmod_attributes; + mod_loc = smod.pmod_loc } + | Pmod_functor(name, smty, sbody) -> +- let mty = transl_modtype env smty in +- let (id, newenv) = Env.enter_module name.txt mty.mty_type env in +- let body = type_module sttn true None newenv sbody in ++ let mty = may_map (transl_modtype env) smty in ++ let ty_arg = may_map (fun m -> m.mty_type) mty in ++ let (id, newenv), funct_body = ++ match ty_arg with None -> (Ident.create "*", env), false ++ | Some mty -> Env.enter_module name.txt mty env, 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, mty.mty_type, body.mod_type); ++ mod_type = Mty_functor(id, ty_arg, body.mod_type); + mod_env = env; + mod_attributes = smod.pmod_attributes; + mod_loc = smod.pmod_loc } +@@ -964,6 +971,14 @@ + type_module (sttn && path <> None) funct_body None env sfunct in + begin match Mtype.scrape 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; + let coercion = + try + Includemod.modtypes env arg.mod_type mty_param +@@ -975,6 +990,7 @@ + Subst.modtype (Subst.add_module param path Subst.identity) + mty_res + | None -> ++ if generative then mty_res else + try + Mtype.nondep_supertype + (Env.add_module param arg.mod_type env) param mty_res +@@ -999,8 +1015,6 @@ + } + + | Pmod_unpack sexp -> +- if funct_body then +- raise (Error (smod.pmod_loc, env, Not_allowed_in_functor_body)); + if !Clflags.principal then Ctype.begin_def (); + let exp = Typecore.type_exp env sexp in + if !Clflags.principal then begin +@@ -1025,6 +1039,8 @@ + | _ -> + raise (Error(smod.pmod_loc, env, Not_a_packed_module exp.exp_type)) + in ++ if funct_body && Mtype.contains_type env mty then ++ raise (Error (smod.pmod_loc, env, Not_allowed_in_functor_body)); + rm { mod_desc = Tmod_unpack(exp, mty); + mod_type = mty; + mod_env = env; +@@ -1549,7 +1565,8 @@ + Location.print_filename intf_name + | Not_allowed_in_functor_body -> + fprintf ppf +- "This kind of expression is not allowed within the body of a functor." ++ "@[This expression creates fresh types.@ %s@]" ++ "It is not allowed inside applicative functors." + | With_need_typeconstr -> + fprintf ppf + "Only type constructors with identical parameters can be substituted." +@@ -1570,6 +1587,8 @@ + fprintf ppf "Uninterpreted extension '%s'." s + | Recursive_module_require_explicit_type -> + fprintf ppf "Recursive modules require an explicit module type." ++ | Apply_generative -> ++ fprintf ppf "This is a generative functor. It can only be applied to ()" + + let report_error env ppf err = + Printtyp.wrap_printing_env env (fun () -> report_error ppf err) +Index: typing/typemod.mli +=================================================================== +--- typing/typemod.mli (revision 14301) ++++ typing/typemod.mli (working copy) +@@ -60,6 +60,7 @@ + | Scoping_pack of Longident.t * type_expr + | Extension of string + | Recursive_module_require_explicit_type ++ | Apply_generative + + exception Error of Location.t * Env.t * error + +Index: typing/types.ml +=================================================================== +--- typing/types.ml (revision 14301) ++++ typing/types.ml (working copy) +@@ -264,7 +264,7 @@ + type module_type = + Mty_ident of Path.t + | Mty_signature of signature +- | Mty_functor of Ident.t * module_type * module_type ++ | Mty_functor of Ident.t * module_type option * module_type + + and signature = signature_item list + +Index: typing/types.mli +=================================================================== +--- typing/types.mli (revision 14301) ++++ typing/types.mli (working copy) +@@ -251,7 +251,7 @@ + type module_type = + Mty_ident of Path.t + | Mty_signature of signature +- | Mty_functor of Ident.t * module_type * module_type ++ | Mty_functor of Ident.t * module_type option * module_type + + and signature = signature_item list + |