Add flag `-fwarn-missing-exported-sigs`
authorEric Seidel <gridaphobe@gmail.com>
Fri, 21 Nov 2014 04:39:32 +0000 (22:39 -0600)
committerAustin Seipp <austin@well-typed.com>
Fri, 21 Nov 2014 04:39:55 +0000 (22:39 -0600)
Summary: add `-fwarn-missing-exported-sigs` to only warn about missing signatures if the name is exported

Test Plan: validate, see testsuite/tests/warnings/should_compile/T2526.hs

Reviewers: ezyang, austin, thomie

Reviewed By: austin, thomie

Subscribers: ezyang, thomie, carter

Differential Revision: https://phabricator.haskell.org/D482

GHC Trac Issues: #2526

Conflicts:
docs/users_guide/7.10.1-notes.xml

compiler/main/DynFlags.hs
compiler/typecheck/TcHsSyn.lhs
compiler/typecheck/TcRnDriver.lhs
docs/users_guide/7.10.1-notes.xml
docs/users_guide/flags.xml
docs/users_guide/using.xml
testsuite/tests/warnings/should_compile/T2526.hs [new file with mode: 0644]
testsuite/tests/warnings/should_compile/T2526.stderr [new file with mode: 0644]
testsuite/tests/warnings/should_compile/all.T

index 7aaebfa..3fa2c5f 100644 (file)
@@ -488,6 +488,7 @@ data WarningFlag =
    | Opt_WarnUnsupportedLlvmVersion
    | Opt_WarnInlineRuleShadowing
    | Opt_WarnTypedHoles
+   | Opt_WarnMissingExportedSigs
    deriving (Eq, Show, Enum)
 
 data Language = Haskell98 | Haskell2010
@@ -2664,6 +2665,7 @@ fWarningFlags = [
   ( "warn-missing-local-sigs",          Opt_WarnMissingLocalSigs, nop ),
   ( "warn-missing-methods",             Opt_WarnMissingMethods, nop ),
   ( "warn-missing-signatures",          Opt_WarnMissingSigs, nop ),
+  ( "warn-missing-exported-sigs",       Opt_WarnMissingExportedSigs, nop ),
   ( "warn-monomorphism-restriction",    Opt_WarnMonomorphism, nop ),
   ( "warn-name-shadowing",              Opt_WarnNameShadowing, nop ),
   ( "warn-orphans",                     Opt_WarnOrphans, nop ),
index 1a91f10..27d2648 100644 (file)
@@ -300,7 +300,7 @@ zonkTopLExpr :: LHsExpr TcId -> TcM (LHsExpr Id)
 zonkTopLExpr e = zonkLExpr emptyZonkEnv e
 
 zonkTopDecls :: Bag EvBind
-             -> LHsBinds TcId -> NameSet
+             -> LHsBinds TcId -> Bag OccName -> NameSet
              -> [LRuleDecl TcId] -> [LVectDecl TcId] -> [LTcSpecPrag] -> [LForeignDecl TcId]
              -> TcM ([Id],
                      Bag EvBind,
@@ -309,14 +309,17 @@ zonkTopDecls :: Bag EvBind
                      [LTcSpecPrag],
                      [LRuleDecl    Id],
                      [LVectDecl    Id])
-zonkTopDecls ev_binds binds sig_ns rules vects imp_specs fords
+zonkTopDecls ev_binds binds exports sig_ns rules vects imp_specs fords
   = do  { (env1, ev_binds') <- zonkEvBinds emptyZonkEnv ev_binds
 
          -- Warn about missing signatures
          -- Do this only when we we have a type to offer
         ; warn_missing_sigs <- woptM Opt_WarnMissingSigs
-        ; let sig_warn | warn_missing_sigs = topSigWarn sig_ns
-                       | otherwise         = noSigWarn
+        ; warn_only_exported <- woptM Opt_WarnMissingExportedSigs
+        ; let sig_warn
+                | warn_only_exported = topSigWarnIfExported exports sig_ns
+                | warn_missing_sigs  = topSigWarn sig_ns
+                | otherwise          = noSigWarn
 
         ; (env2, binds') <- zonkRecMonoBinds env1 sig_warn binds
                         -- Top level is implicitly recursive
@@ -377,6 +380,17 @@ type SigWarn = Bool -> [Id] -> TcM ()
 noSigWarn :: SigWarn
 noSigWarn _ _ = return ()
 
+topSigWarnIfExported :: Bag OccName -> NameSet -> SigWarn
+topSigWarnIfExported exported sig_ns _ ids
+  = mapM_ (topSigWarnIdIfExported exported sig_ns) ids
+
+topSigWarnIdIfExported :: Bag OccName -> NameSet -> Id -> TcM ()
+topSigWarnIdIfExported exported sig_ns id
+  | getOccName id `elemBag` exported
+  = topSigWarnId sig_ns id
+  | otherwise
+  = return ()
+
 topSigWarn :: NameSet -> SigWarn
 topSigWarn sig_ns _ ids = mapM_ (topSigWarnId sig_ns) ids
 
index ca6df13..d2bfd25 100644 (file)
@@ -297,7 +297,7 @@ tcRnModuleTcRnM hsc_env hsc_src
                          Just txt -> tcg_env { tcg_warns = WarnAll txt } 
                          Nothing  -> tcg_env 
             } ;
+
         setGblEnv tcg_env1 $ do {
 
                 -- Load the hi-boot interface for this module, if any
@@ -310,13 +310,18 @@ tcRnModuleTcRnM hsc_env hsc_src
                 -- look for a hi-boot file
         boot_iface <- tcHiBootIface hsc_src this_mod ;
 
+        let { exports_occs =
+                 maybe emptyBag (listToBag . map (rdrNameOcc . ieName . unLoc))
+                       export_ies
+            } ;
+
                 -- Rename and type check the declarations
         traceRn (text "rn1a") ;
         tcg_env <- if isHsBootOrSig hsc_src then
                         tcRnHsBootDecls hsc_src local_decls
                    else
                         {-# SCC "tcRnSrcDecls" #-}
-                        tcRnSrcDecls boot_iface local_decls ;
+                        tcRnSrcDecls boot_iface exports_occs local_decls ;
         setGblEnv tcg_env               $ do {
 
                 -- Process the export list
@@ -450,10 +455,10 @@ tcRnImports hsc_env import_decls
 %************************************************************************
 
 \begin{code}
-tcRnSrcDecls :: ModDetails -> [LHsDecl RdrName] -> TcM TcGblEnv
+tcRnSrcDecls :: ModDetails -> Bag OccName -> [LHsDecl RdrName] -> TcM TcGblEnv
         -- Returns the variables free in the decls
         -- Reason: solely to report unused imports and bindings
-tcRnSrcDecls boot_iface decls
+tcRnSrcDecls boot_iface exports decls
  = do {         -- Do all the declarations
         ((tcg_env, tcl_env), lie) <- captureConstraints $ tc_rn_src_decls boot_iface decls ;
       ; traceTc "Tc8" empty ;
@@ -497,7 +502,8 @@ tcRnSrcDecls boot_iface decls
 
         (bind_ids, ev_binds', binds', fords', imp_specs', rules', vects')
             <- {-# SCC "zonkTopDecls" #-}
-               zonkTopDecls all_ev_binds binds sig_ns rules vects imp_specs fords ;
+               zonkTopDecls all_ev_binds binds exports sig_ns rules vects
+                            imp_specs fords ;
 
         let { final_type_env = extendTypeEnvWithIds type_env bind_ids
             ; tcg_env' = tcg_env { tcg_binds    = binds',
@@ -1837,7 +1843,8 @@ tcRnDeclsi hsc_env local_decls =
         all_ev_binds = cur_ev_binds `unionBags` new_ev_binds
 
     (bind_ids, ev_binds', binds', fords', imp_specs', rules', vects')
-        <- zonkTopDecls all_ev_binds binds sig_ns rules vects imp_specs fords
+        <- zonkTopDecls all_ev_binds binds emptyBag sig_ns rules vects
+                        imp_specs fords
 
     let --global_ids = map globaliseAndTidyId bind_ids
         final_type_env = extendTypeEnvWithIds type_env bind_ids --global_ids
index 5eb9bae..4b82329 100644 (file)
              </para>
            </listitem>
            <listitem>
+<<<<<<< HEAD
                 <para>
                     Many more options have learned to respect the <option>-ddump-to-file</option>.
                     For example you can use <option>-ddump-to-file</option> with <option>-ddump-splices</option>
                solver, to add new functionality to GHC's
                typechecker. See <xref linkend="typechecker-plugins"/>
                for more details.
+=======
+             <para>
+               A new warning flag, <option>-fwarn-missing-exported-sigs</option>
+               has been added. The behavior is similar to
+               <option>-fwarn-missing-signatures</option> but GHC will only
+               flag exported values. This flag takes precedence over
+               <option>-fwarn-missing-signatures</option> so it can be used
+               in conjunction with <option>-Wall</option>.
+>>>>>>> 0551cf1... Add flag `-fwarn-missing-exported-sigs`
              </para>
            </listitem>
        </itemizedlist>
index e8218f7..5c5e05e 100644 (file)
           </row>
 
           <row>
+            <entry><option>-fwarn-missing-exported-sigs</option></entry>
+            <entry>warn about top-level functions without signatures, only if they are exported. takes precedence over -fwarn-missing-signatures</entry>
+            <entry>dynamic</entry>
+            <entry><option>-fno-warn-missing-exported-sigs</option></entry>
+          </row>
+
+          <row>
             <entry><option>-fwarn-missing-local-sigs</option></entry>
             <entry>warn about polymorphic local bindings without signatures</entry>
             <entry>dynamic</entry>
index 1f0c029..3820f89 100644 (file)
@@ -1611,6 +1611,21 @@ module M where
       </varlistentry>
 
       <varlistentry>
+        <term><option>-fwarn-missing-exported-sigs</option>:</term>
+        <listitem>
+          <indexterm><primary><option>-fwarn-missing-exported-sigs</option></primary></indexterm>
+          <indexterm><primary>type signatures, missing</primary></indexterm>
+
+          <para>If you would like GHC to check that every exported top-level
+          function/value has a type signature, but not check unexported values, use the
+          <option>-fwarn-missing-exported-sigs</option> option.  This option
+          takes precedence over <option>-fwarn-missing-signatures</option>.
+          As part of the warning GHC also reports the inferred type.  The
+          option is off by default.</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
         <term><option>-fwarn-missing-local-sigs</option>:</term>
         <listitem>
           <indexterm><primary><option>-fwarn-missing-local-sigs</option></primary></indexterm>
diff --git a/testsuite/tests/warnings/should_compile/T2526.hs b/testsuite/tests/warnings/should_compile/T2526.hs
new file mode 100644 (file)
index 0000000..c77168c
--- /dev/null
@@ -0,0 +1,7 @@
+module T2526 (foo) where
+
+-- This should generate a warning
+foo = 1
+
+-- This should not
+bar = 2
diff --git a/testsuite/tests/warnings/should_compile/T2526.stderr b/testsuite/tests/warnings/should_compile/T2526.stderr
new file mode 100644 (file)
index 0000000..585c22d
--- /dev/null
@@ -0,0 +1,3 @@
+
+T2526.hs:4:1: Warning:
+    Top-level binding with no type signature: foo :: Integer
index 903ab69..7fa8caf 100644 (file)
@@ -1,3 +1,5 @@
+# -fwarn-missing-exported-sigs should take precedence over -fwarn-missing-signatures
+test('T2526', normal, compile, ['-fwarn-missing-signatures -fwarn-missing-exported-sigs'])
 test('T9178', extra_clean(['T9178.o', 'T9178DataType.o',
                           'T9178.hi', 'T9178DataType.hi']),
              multimod_compile, ['T9178', '-Wall'])