Commits

camlspotter  committed 4685ed2

cleaned up

  • Participants
  • Parent commits 2d6735c
  • Branches redundant_open_warning

Comments (0)

Files changed (23)

 
 CAMLC=boot/ocamlrun boot/ocamlc -nostdlib -I boot
 CAMLOPT=boot/ocamlrun ./ocamlopt -nostdlib -I stdlib -I otherlibs/dynlink
-COMPFLAGS=-strict-sequence -warn-error A $(INCLUDES)
+COMPFLAGS=-strict-sequence -warn-error A-31 $(INCLUDES)
 LINKFLAGS=
 
 CAMLYACC=boot/ocamlyacc
 
 CAMLC=boot/ocamlrun boot/ocamlc -nostdlib -I boot
 CAMLOPT=boot/ocamlrun ./ocamlopt -nostdlib -I stdlib -I otherlibs/dynlink
-COMPFLAGS=-strict-sequence -warn-error A $(INCLUDES)
+COMPFLAGS=-strict-sequence -warn-error A-31 $(INCLUDES)
 LINKFLAGS=
 CAMLYACC=boot/ocamlyacc
 YACCFLAGS=
 # The stdlib neither requires the stdlib nor debug information
 <stdlib/**>: -use_stdlib, -debug
 
-<**/*.ml*>: warn_error_A
+<**/*.ml*>: warn_error_A-31
 
 <{bytecomp,driver,stdlib,tools,asmcomp,toplevel,typing,utils,lex,parsing}/**>: strict_sequence
 

File boot/ocamlc

Binary file modified.

File boot/ocamldep

Binary file modified.

File boot/ocamllex

Binary file modified.

File debugger/Makefile.shared

 include ../config/Makefile
 
 CAMLC=../ocamlcomp.sh
-COMPFLAGS=-warn-error A $(INCLUDES)
+COMPFLAGS=-warn-error A-31 $(INCLUDES)
 LINKFLAGS=-linkall -I $(UNIXDIR)
 CAMLYACC=../boot/ocamlyacc
 YACCFLAGS=
 OTHEROBJS=\
   $(UNIXDIR)/unix.cma \
   ../utils/misc.cmo ../utils/config.cmo \
-  ../utils/tbl.cmo ../utils/clflags.cmo ../utils/consistbl.cmo \
-  ../parsing/longident.cmo \
+  ../utils/tbl.cmo ../utils/clflags.cmo ../utils/consistbl.cmo ../utils/warnings.cmo \
+  ../parsing/longident.cmo ../parsing/linenum.cmo ../parsing/location.cmo \
   ../typing/ident.cmo ../typing/path.cmo ../typing/types.cmo \
   ../typing/btype.cmo ../typing/primitive.cmo ../typing/typedtree.cmo \
   ../typing/subst.cmo ../typing/predef.cmo \

File debugger/envaux.ml

             with Not_found ->
               raise (Error (Module_not_found path'))
           in
-          Env.open_signature path' (extract_sig env mty) env
+          Env.open_signature Location.none path' (extract_sig env mty) env
     in
       Hashtbl.add env_cache (sum, subst) env;
       env

File driver/compile.ml

       Pparse.file ppf inputfile Parse.interface ast_intf_magic_number in
     if !Clflags.dump_parsetree then fprintf ppf "%a@." Printast.interface ast;
     let sg = Typemod.transl_signature (initial_env()) ast in
+    Env.check_modules_opened_but_not_used_yet ();
     if !Clflags.print_types then
       fprintf std_formatter "%a@." Printtyp.signature
                                    (Typemod.simplify_signature sg);

File driver/optcompile.ml

       Pparse.file ppf inputfile Parse.interface ast_intf_magic_number in
     if !Clflags.dump_parsetree then fprintf ppf "%a@." Printast.interface ast;
     let sg = Typemod.transl_signature (initial_env()) ast in
+    Env.check_modules_opened_but_not_used_yet ();
     if !Clflags.print_types then
       fprintf std_formatter "%a@." Printtyp.signature
                                    (Typemod.simplify_signature sg);

File lex/Makefile

 # The lexer generator
 CAMLC=../boot/ocamlrun ../boot/ocamlc -strict-sequence -nostdlib -I ../boot
 CAMLOPT=../boot/ocamlrun ../ocamlopt -nostdlib -I ../stdlib
-COMPFLAGS=-warn-error A
+COMPFLAGS=-warn-error A-31
 CAMLYACC=../boot/ocamlyacc
 YACCFLAGS=-v
 CAMLLEX=../boot/ocamlrun ../boot/ocamllex

File ocamldoc/Makefile

 
 INCLUDES=$(INCLUDES_DEP) $(INCLUDES_NODEP)
 
-COMPFLAGS=$(INCLUDES) -warn-error A
+COMPFLAGS=$(INCLUDES) -warn-error A-31
 LINKFLAGS=$(INCLUDES) -nostdlib
 
 CMOFILES= odoc_config.cmo \

File otherlibs/dynlink/Makefile

 CAMLC=../../boot/ocamlrun ../../ocamlc
 CAMLOPT=../../ocamlcompopt.sh
 INCLUDES=-I ../../utils -I ../../typing -I ../../bytecomp -I ../../asmcomp
-COMPFLAGS=-warn-error A -I ../../stdlib $(INCLUDES)
+COMPFLAGS=-warn-error A-31 -I ../../stdlib $(INCLUDES)
 
 OBJS=dynlinkaux.cmo dynlink.cmo
 

File parsing/parser.mly

       { mkmod(Pmod_structure($2)) }
   | STRUCT structure error
       { unclosed "struct" 1 "end" 3 }
+  | LBRACE structure RBRACE
+      { mkmod(Pmod_structure($2)) }
+  | LBRACE structure error
+      { unclosed "{" 1 "end" 3 }
   | FUNCTOR LPAREN UIDENT COLON module_type RPAREN MINUSGREATER module_expr
       { mkmod(Pmod_functor($3, $5, $8)) }
   | module_expr LPAREN module_expr RPAREN
       { mkmty(Pmty_signature(List.rev $2)) }
   | SIG signature error
       { unclosed "sig" 1 "end" 3 }
+  | LBRACE signature RBRACE
+      { mkmty(Pmty_signature(List.rev $2)) }
+  | LBRACE signature error
+      { unclosed "{" 1 "end" 3 }
   | FUNCTOR LPAREN UIDENT COLON module_type RPAREN MINUSGREATER module_type
       %prec below_WITH
       { mkmty(Pmty_functor($3, $5, $8)) }
       { bigarray_get $1 $4 }
   | simple_expr DOT LBRACE expr_comma_list error
       { unclosed "{" 3 "}" 5 }
-  | LBRACE record_expr RBRACE
-      { let (exten, fields) = $2 in mkexp(Pexp_record(fields, exten)) }
-  | LBRACE record_expr error
-      { unclosed "{" 1 "}" 3 }
+  | LBRACE opt_semi record_expr RBRACE
+      { let (exten, fields) = $3 in mkexp(Pexp_record(fields, exten)) }
+  | LBRACE opt_semi record_expr error
+      { unclosed "{" 1 "}" 4 }
   | LBRACKETBAR expr_semi_list opt_semi BARRBRACKET
       { mkexp(Pexp_array(List.rev $2)) }
   | LBRACKETBAR expr_semi_list opt_semi error
       { mkexp(Pexp_apply(mkoperator "!" 1, ["",$2])) }
   | NEW class_longident
       { mkexp(Pexp_new($2)) }
-  | LBRACELESS field_expr_list opt_semi GREATERRBRACE
-      { mkexp(Pexp_override(List.rev $2)) }
-  | LBRACELESS field_expr_list opt_semi error
-      { unclosed "{<" 1 ">}" 4 }
+  | LBRACELESS opt_semi field_expr_list opt_semi GREATERRBRACE
+      { mkexp(Pexp_override(List.rev $3)) }
+  | LBRACELESS opt_semi field_expr_list opt_semi error
+      { unclosed "{<" 1 ">}" 5 }
   | LBRACELESS GREATERRBRACE
       { mkexp(Pexp_override []) }
   | simple_expr SHARP label
   | expr COMMA expr                             { [$3; $1] }
 ;
 record_expr:
-    simple_expr WITH lbl_expr_list opt_semi     { (Some $1, List.rev $3) }
+    simple_expr WITH opt_semi lbl_expr_list opt_semi     { (Some $1, List.rev $4) }
   | lbl_expr_list opt_semi                      { (None, List.rev $1) }
 ;
 lbl_expr_list:
       { mkpat(Ppat_variant($1, None)) }
   | SHARP type_longident
       { mkpat(Ppat_type $2) }
-  | LBRACE lbl_pattern_list record_pattern_end RBRACE
-      { mkpat(Ppat_record(List.rev $2, $3)) }
-  | LBRACE lbl_pattern_list opt_semi error
+  | LBRACE opt_semi lbl_pattern_list record_pattern_end RBRACE
+      { mkpat(Ppat_record(List.rev $3, $4)) }
+  | LBRACE opt_semi lbl_pattern_list opt_semi error
       { unclosed "{" 1 "}" 4 }
   | LBRACKET pattern_semi_list opt_semi RBRACKET
       { reloc_pat (mktailpat (List.rev $2)) }
       { (Ptype_variant(List.rev $3), Private, None) }
   | EQUAL private_flag BAR constructor_declarations
       { (Ptype_variant(List.rev $4), $2, None) }
-  | EQUAL private_flag LBRACE label_declarations opt_semi RBRACE
-      { (Ptype_record(List.rev $4), $2, None) }
+  | EQUAL private_flag LBRACE opt_semi label_declarations opt_semi RBRACE
+      { (Ptype_record(List.rev $5), $2, None) }
   | EQUAL core_type EQUAL private_flag opt_bar constructor_declarations
       { (Ptype_variant(List.rev $6), $4, Some $2) }
-  | EQUAL core_type EQUAL private_flag LBRACE label_declarations opt_semi RBRACE
-      { (Ptype_record(List.rev $6), $4, Some $2) }
+  | EQUAL core_type EQUAL private_flag LBRACE opt_semi label_declarations opt_semi RBRACE
+      { (Ptype_record(List.rev $7), $4, Some $2) }
 ;
 type_parameters:
     /*empty*/                                   { [] }
 constructor_arguments:
     /*empty*/                                   { [] }
   | OF core_type_list                           { List.rev $2 }
+  | LPAREN core_type_comma_list RPAREN          { List.rev $2 }
 ;
 label_declarations:
     label_declaration                           { [$1] }
 tag_field:
     name_tag OF opt_ampersand amper_type_list
       { Rtag ($1, $3, List.rev $4) }
+  | name_tag LPAREN opt_ampersand amper_type_list RPAREN
+      { Rtag ($1, $3, List.rev $4) }
   | name_tag
       { Rtag ($1, true, []) }
 ;

File stdlib/Makefile.shared

 RUNTIME=../boot/ocamlrun
 COMPILER=../ocamlc
 CAMLC=$(RUNTIME) $(COMPILER)
-COMPFLAGS=-strict-sequence -g -warn-error A -nostdlib
+COMPFLAGS=-strict-sequence -g -warn-error A-31 -nostdlib
 OPTCOMPILER=../ocamlopt
 CAMLOPT=$(RUNTIME) $(OPTCOMPILER)
-OPTCOMPFLAGS=-warn-error A -nostdlib -g
+OPTCOMPFLAGS=-warn-error A-31 -nostdlib -g
 CAMLDEP=../boot/ocamlrun ../tools/ocamldep
 
 OBJS=pervasives.cmo $(OTHERS)

File tools/Makefile.shared

 CAMLLEX=$(CAMLRUN) ../boot/ocamllex
 INCLUDES=-I ../utils -I ../parsing -I ../typing -I ../bytecomp -I ../asmcomp \
 	 -I ../driver
-COMPFLAGS= -warn-error A $(INCLUDES)
+COMPFLAGS= -warn-error A-31 $(INCLUDES)
 LINKFLAGS=$(INCLUDES)
 
 all: ocamldep ocamlprof ocamlcp ocamlmktop ocamlmklib dumpobj objinfo

File typing/env.ml

   | Env_cltype of summary * Ident.t * cltype_declaration
   | Env_open of summary * Path.t
 
+type 'a with_open = 'a * Path.t option
+
 type t = {
-  values: (Path.t * value_description) Ident.tbl;
-  annotations: (Path.t * Annot.ident) Ident.tbl;
-  constrs: constructor_description Ident.tbl;
-  labels: label_description Ident.tbl;
-  types: (Path.t * type_declaration) Ident.tbl;
-  modules: (Path.t * module_type) Ident.tbl;
-  modtypes: (Path.t * modtype_declaration) Ident.tbl;
-  components: (Path.t * module_components) Ident.tbl;
-  classes: (Path.t * class_declaration) Ident.tbl;
-  cltypes: (Path.t * cltype_declaration) Ident.tbl;
+  values: (Path.t * value_description) with_open Ident.tbl;
+  annotations: (Path.t * Annot.ident) with_open Ident.tbl;
+  constrs: constructor_description with_open Ident.tbl;
+  labels: label_description with_open Ident.tbl;
+  types: (Path.t * type_declaration) with_open Ident.tbl;
+  modules: (Path.t * module_type) with_open Ident.tbl;
+  modtypes: (Path.t * modtype_declaration) with_open Ident.tbl;
+  components: (Path.t * module_components) with_open Ident.tbl;
+  classes: (Path.t * class_declaration) with_open Ident.tbl;
+  cltypes: (Path.t * cltype_declaration) with_open Ident.tbl;
   summary: summary
 }
 
     Pident _ -> true
   | Pdot _ | Papply _ -> false
 
-let is_local (p, _) = is_ident p
+let is_local ((p, _),_) = is_ident p
 
 let is_local_exn = function
-    {cstr_tag = Cstr_exception p} -> is_ident p
+    ({cstr_tag = Cstr_exception p}, _) -> is_ident p
   | _ -> false
 
 let diff env1 env2 =
   match path with
     Pident id ->
       begin try
-        let (p, desc) = Ident.find_same id env.components
+        let (p, desc),_ = Ident.find_same id env.components
         in desc
       with Not_found ->
         if Ident.persistent id
 let find proj1 proj2 path env =
   match path with
     Pident id ->
-      let (p, data) = Ident.find_same id (proj1 env)
+      let (p, data),_ = Ident.find_same id (proj1 env)
       in data
   | Pdot(p, s, pos) ->
       begin match Lazy.force(find_module_descr p env) with
   match path with
     Pident id ->
       begin try
-        let (p, data) = Ident.find_same id env.modules
+        let (p, data),_ = Ident.find_same id env.modules
         in data
       with Not_found ->
         if Ident.persistent id then
 
 (* Lookup by name *)
 
+let modules_opened_but_not_used_yet = Hashtbl.create 103
+
+(* CR jfuruse: not sure about the place. debugger/Makefile.shared required additional modules for this *)
+let check_modules_opened_but_not_used_yet () =
+  let loc_paths = 
+    List.sort (fun (l1, _) (l2, _) -> compare l1 l2)
+      (Hashtbl.fold (fun k locs st -> List.map (fun loc -> loc, k) locs @ st) modules_opened_but_not_used_yet [])
+  in
+  Hashtbl.clear modules_opened_but_not_used_yet;
+  List.iter (fun (loc, path) ->
+    match path with
+    | Pident id when Ident.name id = "Pervasives" -> () (* CR jfuruse: this is not precise *)
+    | _ -> 
+        Location.prerr_warning loc (Warnings.Opened_module_is_never_used (Path.name path)))
+    loc_paths
+
+let add_opened_module loc p =
+  let locs = loc :: try Hashtbl.find modules_opened_but_not_used_yet p with Not_found -> [] in
+  Hashtbl.replace modules_opened_but_not_used_yet p locs
+
+let mark_opened_module (v, open_info) =
+  begin match open_info with
+  | None -> ()
+  | Some p -> Hashtbl.remove modules_opened_but_not_used_yet p
+  end;
+  v
+
 let rec lookup_module_descr lid env =
   match lid with
     Lident s ->
       begin try
-        Ident.find_name s env.components
+        mark_opened_module (Ident.find_name s env.components)
       with Not_found ->
         if s = !current_unit then raise Not_found;
         let ps = find_pers_struct s in
   match lid with
     Lident s ->
       begin try
-        Ident.find_name s env.modules
+        mark_opened_module (Ident.find_name s env.modules)
       with Not_found ->
         if s = !current_unit then raise Not_found;
         let ps = find_pers_struct s in
           raise Not_found
       end
 
+(* CR jfuruse: copied from Printtyp.longident *)
+let format_longident ppf lid = 
+  let open Format in
+  let rec longident ppf = function
+    | Lident s -> fprintf ppf "%s" s
+    | Ldot(p, s) -> fprintf ppf "%a.%s" longident p s
+    | Lapply(p1, p2) -> fprintf ppf "%a(%a)" longident p1 longident p2
+  in
+  longident ppf lid
+
 let lookup proj1 proj2 lid env =
   match lid with
-    Lident s ->
-      Ident.find_name s (proj1 env)
+    Lident s -> mark_opened_module (Ident.find_name s (proj1 env))
   | Ldot(l, s) ->
       let (p, desc) = lookup_module_descr l env in
       begin match Lazy.force desc with
 let lookup_simple proj1 proj2 lid env =
   match lid with
     Lident s ->
-      Ident.find_name s (proj1 env)
+      mark_opened_module (Ident.find_name s (proj1 env))
   | Ldot(l, s) ->
       let (p, desc) = lookup_module_descr l env in
       begin match Lazy.force desc with
 
 (* Insertion of bindings by identifier + path *)
 
-and store_value id path decl env =
+and store_value ?opened id path decl env =
   { env with
-    values = Ident.add id (path, decl) env.values;
+    values = Ident.add id ((path, decl), opened) env.values;
     summary = Env_value(env.summary, id, decl) }
 
-and store_annot id path annot env =
+and store_annot ?opened id path annot env =
   if !Clflags.annotations then
     { env with
-      annotations = Ident.add id (path, annot) env.annotations }
+      annotations = Ident.add id ((path, annot), opened) env.annotations }
   else env
 
-and store_type id path info env =
+and store_type ?opened id path info env =
   { env with
     constrs =
       List.fold_right
         (fun (name, descr) constrs ->
-          Ident.add (Ident.create name) descr constrs)
+          Ident.add (Ident.create name) (descr, opened) constrs)
         (constructors_of_type path info)
         env.constrs;
     labels =
       List.fold_right
         (fun (name, descr) labels ->
-          Ident.add (Ident.create name) descr labels)
+          Ident.add (Ident.create name) (descr, opened) labels)
         (labels_of_type path info)
         env.labels;
-    types = Ident.add id (path, info) env.types;
+    types = Ident.add id ((path, info), opened) env.types;
     summary = Env_type(env.summary, id, info) }
 
-and store_type_infos id path info env =
+and store_type_infos ?opened id path info env =
   (* Simplified version of store_type that doesn't compute and store
      constructor and label infos, but simply record the arity and
      manifest-ness of the type.  Used in components_of_module to
      keep track of type abbreviations (e.g. type t = float) in the
      computation of label representations. *)
   { env with
-    types = Ident.add id (path, info) env.types;
+    types = Ident.add id ((path, info), opened) env.types;
     summary = Env_type(env.summary, id, info) }
 
-and store_exception id path decl env =
+and store_exception ?opened id path decl env =
   { env with
-    constrs = Ident.add id (Datarepr.exception_descr path decl) env.constrs;
+    constrs = Ident.add id (Datarepr.exception_descr path decl, opened) env.constrs;
     summary = Env_exception(env.summary, id, decl) }
 
-and store_module id path mty env =
+and store_module ?opened id path mty env =
   { env with
-    modules = Ident.add id (path, mty) env.modules;
+    modules = Ident.add id ((path, mty), opened) env.modules;
     components =
-      Ident.add id (path, components_of_module env Subst.identity path mty)
+      Ident.add id ((path, components_of_module env Subst.identity path mty), opened)
                    env.components;
     summary = Env_module(env.summary, id, mty) }
 
-and store_modtype id path info env =
+and store_modtype ?opened id path info env =
   { env with
-    modtypes = Ident.add id (path, info) env.modtypes;
+    modtypes = Ident.add id ((path, info), opened) env.modtypes;
     summary = Env_modtype(env.summary, id, info) }
 
-and store_class id path desc env =
+and store_class ?opened id path desc env =
   { env with
-    classes = Ident.add id (path, desc) env.classes;
+    classes = Ident.add id ((path, desc), opened) env.classes;
     summary = Env_class(env.summary, id, desc) }
 
-and store_cltype id path desc env =
+and store_cltype ?opened id path desc env =
   { env with
-    cltypes = Ident.add id (path, desc) env.cltypes;
+    cltypes = Ident.add id ((path, desc), opened) env.cltypes;
     summary = Env_cltype(env.summary, id, desc) }
 
 (* Compute the components of a functor application in a path. *)
 
 (* Open a signature path *)
 
-let open_signature root sg env =
+let open_signature loc root sg env =
+  (* Format.eprintf "%a %s@." format_longident lid (Path.unique_name p); *)
+  (* jfuruse Format.eprintf "open %s@." (Path.unique_name root); *)
+  add_opened_module loc root;
+
   (* First build the paths and substitution *)
   let (pl, sub) = prefix_idents root 0 Subst.identity sg in
   (* Then enter the components in the environment after substitution *)
       (fun env item p ->
         match item with
           Tsig_value(id, decl) ->
-            let e1 = store_value (Ident.hide id) p
+            let e1 = store_value ~opened:root (Ident.hide id) p
                         (Subst.value_description sub decl) env
             in store_annot (Ident.hide id) p (Annot.Iref_external) e1
         | Tsig_type(id, decl, _) ->
-            store_type (Ident.hide id) p
+            store_type ~opened:root (Ident.hide id) p
                        (Subst.type_declaration sub decl) env
         | Tsig_exception(id, decl) ->
-            store_exception (Ident.hide id) p
+            store_exception ~opened:root (Ident.hide id) p
                             (Subst.exception_declaration sub decl) env
         | Tsig_module(id, mty, _) ->
-            store_module (Ident.hide id) p (Subst.modtype sub mty) env
+            store_module ~opened:root (Ident.hide id) p (Subst.modtype sub mty) env
         | Tsig_modtype(id, decl) ->
-            store_modtype (Ident.hide id) p
+            store_modtype ~opened:root (Ident.hide id) p
                           (Subst.modtype_declaration sub decl) env
         | Tsig_class(id, decl, _) ->
-            store_class (Ident.hide id) p
+            store_class ~opened:root (Ident.hide id) p
                         (Subst.class_declaration sub decl) env
         | Tsig_cltype(id, decl, _) ->
-            store_cltype (Ident.hide id) p
+            store_cltype ~opened:root (Ident.hide id) p
                          (Subst.cltype_declaration sub decl) env)
       env sg pl in
   { newenv with summary = Env_open(env.summary, root) }
 
 let open_pers_signature name env =
   let ps = find_pers_struct name in
-  open_signature (Pident(Ident.create_persistent name)) ps.ps_sig env
+  open_signature Location.none (Pident(Ident.create_persistent name)) ps.ps_sig env
 
 (* Read a signature from a file *)
 

File typing/env.mli

    of the compiler's type-based optimisations. *)
 val find_modtype_expansion: Path.t -> t -> Types.module_type
 
+val check_modules_opened_but_not_used_yet : unit -> unit
+
 (* Lookup by long identifiers *)
 
 val lookup_value: Longident.t -> t -> Path.t * value_description
 (* Insertion of all fields of a signature, relative to the given path.
    Used to implement open. *)
 
-val open_signature: Path.t -> signature -> t -> t
+val open_signature: Location.t -> Path.t -> signature -> t -> t
 val open_pers_signature: string -> t -> t
 
 (* Insertion by name *)

File typing/path.ml

     Pident id -> id
   | Pdot(p, s, pos) -> head p
   | Papply(p1, p2) -> assert false
+
+let rec unique_name = function
+    Pident id -> Ident.unique_name id
+  | Pdot(p, s, pos) -> unique_name p ^ "." ^ s ^ "/" ^ string_of_int pos
+  | Papply(p1, p2) -> unique_name p1 ^ "(" ^ unique_name p2 ^ ")"
+

File typing/path.mli

 val nopos: int
 
 val name: t -> string
+val unique_name : t -> string
 val head: t -> Ident.t

File typing/typemod.ml

 let type_open env loc lid =
   let (path, mty) = Typetexp.find_module env loc lid in
   let sg = extract_sig_open env loc mty in
-  Env.open_signature path sg env
+  Env.open_signature loc path sg env
 
 (* Record a module type *)
 let rm node =
   let (str, sg, finalenv) = type_structure initial_env ast Location.none in
   let simple_sg = simplify_signature sg in
   Typecore.force_delayed_checks ();
+  Env.check_modules_opened_but_not_used_yet ();
   if !Clflags.print_types then begin
     fprintf std_formatter "%a@." Printtyp.signature simple_sg;
     (str, Tcoerce_none)   (* result is ignored by Compile.implementation *)

File utils/warnings.ml

   | Wildcard_arg_to_constant_constr         (* 28 *)
   | Eol_in_string                           (* 29 *)
   | Duplicate_definitions of string * string * string * string (*30 *)
+  | Opened_module_is_never_used of string (* 31 *)
 ;;
 
 (* If you remove a warning, leave a hole in the numbering.  NEVER change
   | Wildcard_arg_to_constant_constr -> 28
   | Eol_in_string -> 29
   | Duplicate_definitions _ -> 30
+  | Opened_module_is_never_used _ -> 31
 ;;
 
-let last_warning_number = 30;;
+let last_warning_number = 31;;
 (* Must be the max number returned by the [number] function. *)
 
 let letter = function
   | Duplicate_definitions (kind, cname, tc1, tc2) ->
       Printf.sprintf "the %s %s is defined in both types %s and %s."
         kind cname tc1 tc2
+  | Opened_module_is_never_used mname ->
+      Printf.sprintf "open %s is redundant."
+        mname
 ;;
 
 let nerrors = ref 0;;
    29, "Unescaped end-of-line in a string constant (non-portable code).";
    30, "Two labels or constructors of the same name are defined in two\n\
    \    mutually recursive types.";
+   31, "a module is opened, but not required.";
   ]
 
 let help_warnings () =

File utils/warnings.mli

   | Wildcard_arg_to_constant_constr         (* 28 *)
   | Eol_in_string                           (* 29 *)
   | Duplicate_definitions of string * string * string * string (*30 *)
+  | Opened_module_is_never_used of string (* 31 *)
 ;;
 
 val parse_options : bool -> string -> unit;;