Add -fdefer-typed-holes flag which defers hole errors to runtime.
authorMerijn Verstraaten <merijn@inconsistent.nl>
Fri, 21 Nov 2014 21:32:38 +0000 (15:32 -0600)
committerAustin Seipp <austin@well-typed.com>
Fri, 21 Nov 2014 23:04:57 +0000 (17:04 -0600)
Summary:
As proposed by Richard on Trac. This patch adds a new flag -fdefer-typed-holes
and changes the semantics of the -fno-warn-typed-holes flag.

To summarise, by default GHC has typed holes enabled and produces a compile
error when it encounters a typed hole.

When -fdefer-type-errors OR -fdefer-typed-holes is enabled, hole errors are
converted to warnings and result in runtime errors when evaluated.

The warning flag -fwarn-typed-holes is on by default. Without -fdefer-type-errors
or -fdefer-typed-holes this flag is a no-op, since typed holes are an error
under these conditions. If either of the defer flags are enabled (converting
typed hole errors into warnings) the -fno-warn-typed-holes flag disables the
warnings. This means compilation silently succeeds and evaluating a hole will
produce a runtime error.

The rationale behind allowing typed holes warnings to be silenced is that tools
like Syntastic for vim highlight warnings and hole warnings may be undesirable.

Signed-off-by: Merijn Verstraaten <merijn@inconsistent.nl>
Test Plan: validate

Reviewers: austin, simonpj, thomie

Reviewed By: simonpj, thomie

Subscribers: Fuuzetsu, thomie, carter

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

GHC Trac Issues: #9497

Conflicts:
compiler/main/DynFlags.hs

27 files changed:
compiler/main/DynFlags.hs
compiler/rename/RnExpr.lhs
compiler/typecheck/TcDeriv.lhs
compiler/typecheck/TcErrors.lhs
compiler/typecheck/TcRnDriver.lhs
docs/users_guide/flags.xml
docs/users_guide/glasgow_exts.xml
docs/users_guide/using.xml
testsuite/tests/module/mod71.stderr
testsuite/tests/rename/should_fail/rnfail016.stderr
testsuite/tests/typecheck/should_compile/T9497a.hs [new file with mode: 0644]
testsuite/tests/typecheck/should_compile/T9497a.stderr [new file with mode: 0644]
testsuite/tests/typecheck/should_compile/T9497b.hs [new file with mode: 0644]
testsuite/tests/typecheck/should_compile/T9497b.stderr [new file with mode: 0644]
testsuite/tests/typecheck/should_compile/T9497c.hs [new file with mode: 0644]
testsuite/tests/typecheck/should_compile/T9497c.stderr [new file with mode: 0644]
testsuite/tests/typecheck/should_compile/all.T
testsuite/tests/typecheck/should_fail/T9497d.hs [new file with mode: 0644]
testsuite/tests/typecheck/should_fail/T9497d.stderr [new file with mode: 0644]
testsuite/tests/typecheck/should_fail/all.T
testsuite/tests/typecheck/should_run/T9497a-run.hs [new file with mode: 0644]
testsuite/tests/typecheck/should_run/T9497a-run.stderr [new file with mode: 0644]
testsuite/tests/typecheck/should_run/T9497b-run.hs [new file with mode: 0644]
testsuite/tests/typecheck/should_run/T9497b-run.stderr [new file with mode: 0644]
testsuite/tests/typecheck/should_run/T9497c-run.hs [new file with mode: 0644]
testsuite/tests/typecheck/should_run/T9497c-run.stderr [new file with mode: 0644]
testsuite/tests/typecheck/should_run/all.T

index 26662d5..5e3bda9 100644 (file)
@@ -396,6 +396,7 @@ data GeneralFlag
    | Opt_GhciHistory
    | Opt_HelpfulErrors
    | Opt_DeferTypeErrors
+   | Opt_DeferTypedHoles
    | Opt_Parallel
    | Opt_GranMacros
    | Opt_PIC
@@ -2769,6 +2770,7 @@ fFlags = [
   flagSpec ( "cmm-sink",                         Opt_CmmSink, nop ),
   flagSpec ( "cse",                              Opt_CSE, nop ),
   flagSpec ( "defer-type-errors",                Opt_DeferTypeErrors, nop ),
+  flagSpec ( "defer-typed-holes",                Opt_DeferTypedHoles, nop ),
   flagSpec ( "dicts-cheap",                      Opt_DictsCheap, nop ),
   flagSpec ( "dicts-strict",                     Opt_DictsStrict, nop ),
   flagSpec ( "dmd-tx-dict-sel",                  Opt_DmdTxDictSel, nop ),
@@ -3053,8 +3055,11 @@ default_PIC platform =
     (OSDarwin, ArchX86_64) -> [Opt_PIC]
     _                      -> []
 
-impliedFlags :: [(ExtensionFlag, TurnOnFlag, ExtensionFlag)]
-impliedFlags
+impliedGFlags :: [(GeneralFlag, TurnOnFlag, GeneralFlag)]
+impliedGFlags = [(Opt_DeferTypeErrors, turnOn, Opt_DeferTypedHoles)]
+
+impliedXFlags :: [(ExtensionFlag, TurnOnFlag, ExtensionFlag)]
+impliedXFlags
 -- See Note [Updating flag description in the User's Guide]
   = [ (Opt_RankNTypes,                turnOn, Opt_ExplicitForAll)
     , (Opt_ScopedTypeVariables,       turnOn, Opt_ExplicitForAll)
@@ -3399,9 +3404,18 @@ setGeneralFlag   f = upd (setGeneralFlag' f)
 unSetGeneralFlag f = upd (unSetGeneralFlag' f)
 
 setGeneralFlag' :: GeneralFlag -> DynFlags -> DynFlags
-setGeneralFlag' f dflags = gopt_set dflags f
+setGeneralFlag' f dflags = foldr ($) (gopt_set dflags f) deps
+  where
+    deps = [ if turn_on then setGeneralFlag'   d
+                        else unSetGeneralFlag' d
+           | (f', turn_on, d) <- impliedGFlags, f' == f ]
+        -- When you set f, set the ones it implies
+        -- NB: use setGeneralFlag recursively, in case the implied flags
+        --     implies further flags
+
 unSetGeneralFlag' :: GeneralFlag -> DynFlags -> DynFlags
 unSetGeneralFlag' f dflags = gopt_unset dflags f
+   -- When you un-set f, however, we don't un-set the things it implies
 
 --------------------------
 setWarningFlag, unSetWarningFlag :: WarningFlag -> DynP ()
@@ -3418,7 +3432,7 @@ setExtensionFlag' f dflags = foldr ($) (xopt_set dflags f) deps
   where
     deps = [ if turn_on then setExtensionFlag'   d
                         else unSetExtensionFlag' d
-           | (f', turn_on, d) <- impliedFlags, f' == f ]
+           | (f', turn_on, d) <- impliedXFlags, f' == f ]
         -- When you set f, set the ones it implies
         -- NB: use setExtensionFlag recursively, in case the implied flags
         --     implies further flags
index 30e7112..7ef815f 100644 (file)
@@ -88,8 +88,7 @@ finishHsVar name
 rnExpr (HsVar v)
   = do { mb_name <- lookupOccRn_maybe v
        ; case mb_name of {
-           Nothing -> do { opt_TypeHoles <- woptM Opt_WarnTypedHoles
-                         ; if opt_TypeHoles && startsWithUnderscore (rdrNameOcc v)
+           Nothing -> do { if startsWithUnderscore (rdrNameOcc v)
                            then return (HsUnboundVar v, emptyFVs)
                            else do { n <- reportUnboundName v; finishHsVar n } } ;
            Just name
@@ -300,11 +299,7 @@ Since all the symbols are reservedops we can simply reject them.
 We return a (bogus) EWildPat in each case.
 
 \begin{code}
-rnExpr e@EWildPat      = do { holes <- woptM Opt_WarnTypedHoles
-                            ; if holes
-                                then return (hsHoleExpr, emptyFVs)
-                                else patSynErr e
-                            }
+rnExpr EWildPat        = return (hsHoleExpr, emptyFVs)
 rnExpr e@(EAsPat {})   = patSynErr e
 rnExpr e@(EViewPat {}) = patSynErr e
 rnExpr e@(ELazyPat {}) = patSynErr e
index a10945a..161bb77 100644 (file)
@@ -1881,7 +1881,7 @@ simplifyDeriv pred tvs theta
                          where p = ctPred ct
 
        -- If we are deferring type errors, simply ignore any insoluble
-       -- constraints.  Tney'll come up again when we typecheck the
+       -- constraints.  They'll come up again when we typecheck the
        -- generated instance declaration
        ; defer <- goptM Opt_DeferTypeErrors
        ; unless defer (reportAllUnsolved (residual_wanted { wc_flat = bad }))
index 84a2c16..cd5879c 100644 (file)
@@ -43,6 +43,7 @@ import DynFlags
 import StaticFlags      ( opt_PprStyle_Debug )
 import ListSetOps       ( equivClasses )
 
+import Control.Monad    ( when )
 import Data.Maybe
 import Data.List        ( partition, mapAccumL, zip4, nub, sortBy )
 \end{code}
@@ -98,22 +99,29 @@ compilation. The errors are turned into warnings in `reportUnsolved`.
 reportUnsolved :: WantedConstraints -> TcM (Bag EvBind)
 reportUnsolved wanted
   = do { binds_var <- newTcEvBinds
-       ; defer <- goptM Opt_DeferTypeErrors
-       ; report_unsolved (Just binds_var) defer wanted
+       ; defer_errors <- goptM Opt_DeferTypeErrors
+       ; defer_holes <- goptM Opt_DeferTypedHoles
+       ; warn_holes <- woptM Opt_WarnTypedHoles
+       ; report_unsolved (Just binds_var) defer_errors defer_holes
+             warn_holes wanted
        ; getTcEvBinds binds_var }
 
 reportAllUnsolved :: WantedConstraints -> TcM ()
 -- Report all unsolved goals, even if -fdefer-type-errors is on
 -- See Note [Deferring coercion errors to runtime]
-reportAllUnsolved wanted = report_unsolved Nothing False wanted
+reportAllUnsolved wanted = do
+    warn_holes <- woptM Opt_WarnTypedHoles
+    report_unsolved Nothing False False warn_holes wanted
 
 report_unsolved :: Maybe EvBindsVar  -- cec_binds
-                -> Bool              -- cec_defer
+                -> Bool              -- cec_defer_type_errors
+                -> Bool              -- cec_defer_holes
+                -> Bool              -- cec_warn_holes
                 -> WantedConstraints -> TcM ()
 -- Important precondition:
 -- WantedConstraints are fully zonked and unflattened, that is,
 -- zonkWC has already been applied to these constraints.
-report_unsolved mb_binds_var defer wanted
+report_unsolved mb_binds_var defer_errors defer_holes  warn_holes wanted
   | isEmptyWC wanted
   = return ()
   | otherwise
@@ -127,7 +135,9 @@ report_unsolved mb_binds_var defer wanted
              free_tvs = tyVarsOfWC wanted
              err_ctxt = CEC { cec_encl  = []
                             , cec_tidy  = tidy_env
-                            , cec_defer    = defer
+                            , cec_defer_type_errors = defer_errors
+                            , cec_defer_holes = defer_holes
+                            , cec_warn_holes = warn_holes
                             , cec_suppress = False -- See Note [Suppressing error messages]
                             , cec_binds    = mb_binds_var }
 
@@ -152,8 +162,16 @@ data ReportErrCtxt
                          --              into warnings, and emit evidence bindings
                          --              into 'ev' for unsolved constraints
 
-          , cec_defer :: Bool       -- True <=> -fdefer-type-errors
-                                    -- Irrelevant if cec_binds = Nothing
+          , cec_defer_type_errors :: Bool -- True <=> -fdefer-type-errors
+                                          -- Defer type errors until runtime
+                                          -- Irrelevant if cec_binds = Nothing
+
+          , cec_defer_holes :: Bool     -- True <=> -fdefer-typed-holes
+                                        -- Turn typed holes into runtime errors
+                                        -- Irrelevant if cec_binds = Nothing
+
+          , cec_warn_holes :: Bool  -- True <=> -fwarn-typed-holes
+                                    -- Controls whether holes produce warnings
           , cec_suppress :: Bool    -- True <=> More important errors have occurred,
                                     --          so create bindings if need be, but
                                     --          don't issue any more errors/warnings
@@ -231,7 +249,7 @@ reportFlats ctxt flats    -- Here 'flats' includes insolble goals
         -- Like Int ~ Bool (incl nullary TyCons)
         -- or  Int ~ t a   (AppTy on one side)
         ("Utterly wrong",  utterly_wrong,   True, mkGroupReporter mkEqErr)
-      , ("Holes",          is_hole,         True, mkUniReporter mkHoleError)
+      , ("Holes",          is_hole,         True, mkHoleReporter mkHoleError)
 
         -- Report equalities of form (a~ty).  They are usually
         -- skolem-equalities, and they cause confusing knock-on
@@ -318,13 +336,13 @@ mkSkolReporter ctxt cts
            (EqPred ty1 _, EqPred ty2 _) -> ty1 `cmpType` ty2
            _ -> pprPanic "mkSkolReporter" (ppr ct1 $$ ppr ct2)
 
-mkUniReporter :: (ReportErrCtxt -> Ct -> TcM ErrMsg) -> Reporter
+mkHoleReporter :: (ReportErrCtxt -> Ct -> TcM ErrMsg) -> Reporter
 -- Reports errors one at a time
-mkUniReporter mk_err ctxt
+mkHoleReporter mk_err ctxt
   = mapM_ $ \ct ->
     do { err <- mk_err ctxt ct
-       ; maybeReportError ctxt err
-       ; maybeAddDeferredBinding ctxt err ct }
+       ; maybeReportHoleError ctxt err
+       ; maybeAddDeferredHoleBinding ctxt err ct }
 
 mkGroupReporter :: (ReportErrCtxt -> [Ct] -> TcM ErrMsg)
                              -- Make error message for a group
@@ -345,22 +363,30 @@ reportGroup mk_err ctxt cts
                -- Add deferred bindings for all
                -- But see Note [Always warn with -fdefer-type-errors]
 
+maybeReportHoleError :: ReportErrCtxt -> ErrMsg -> TcM ()
+maybeReportHoleError ctxt err
+  | cec_defer_holes ctxt
+  = when (cec_warn_holes ctxt)
+            (reportWarning (makeIntoWarning err))
+  | otherwise
+  = reportError err
+
 maybeReportError :: ReportErrCtxt -> ErrMsg -> TcM ()
 -- Report the error and/or make a deferred binding for it
 maybeReportError ctxt err
-  | cec_defer ctxt  -- See Note [Always warn with -fdefer-type-errors]
+  -- See Note [Always warn with -fdefer-type-errors]
+  | cec_defer_type_errors ctxt
   = reportWarning (makeIntoWarning err)
   | cec_suppress ctxt
   = return ()
   | otherwise
   = reportError err
 
-maybeAddDeferredBinding :: ReportErrCtxt -> ErrMsg -> Ct -> TcM ()
+addDeferredBinding :: ReportErrCtxt -> ErrMsg -> Ct -> TcM ()
 -- See Note [Deferring coercion errors to runtime]
-maybeAddDeferredBinding ctxt err ct
+addDeferredBinding ctxt err ct
   | CtWanted { ctev_pred = pred, ctev_evar = ev_id } <- ctEvidence ct
     -- Only add deferred bindings for Wanted constraints
-  , isHoleCt ct || cec_defer ctxt  -- And it's a hole or we have -fdefer-type-errors
   , Just ev_binds_var <- cec_binds ctxt  -- We have somewhere to put the bindings
   = do { dflags <- getDynFlags
        ; let err_msg = pprLocErrMsg err
@@ -373,6 +399,20 @@ maybeAddDeferredBinding ctxt err ct
   | otherwise   -- Do not set any evidence for Given/Derived
   = return ()
 
+maybeAddDeferredHoleBinding :: ReportErrCtxt -> ErrMsg -> Ct -> TcM ()
+maybeAddDeferredHoleBinding ctxt err ct
+    | cec_defer_holes ctxt
+    = addDeferredBinding ctxt err ct
+    | otherwise
+    = return ()
+
+maybeAddDeferredBinding :: ReportErrCtxt -> ErrMsg -> Ct -> TcM ()
+maybeAddDeferredBinding ctxt err ct
+    | cec_defer_type_errors ctxt
+    = addDeferredBinding ctxt err ct
+    | otherwise
+    = return ()
+
 tryReporters :: [ReporterSpec] -> Reporter -> Reporter
 -- Use the first reporter in the list whose predicate says True
 tryReporters reporters deflt ctxt cts
index d2e9115..2bc64c5 100644 (file)
@@ -1535,7 +1535,7 @@ runPlans [p]    = p
 runPlans (p:ps) = tryTcLIE_ (runPlans ps) p
 
 -- | Typecheck (and 'lift') a stmt entered by the user in GHCi into the
--- GHCi 'environemnt'.
+-- GHCi 'environment'.
 --
 -- By 'lift' and 'environment we mean that the code is changed to
 -- execute properly in an IO monad. See Note [Interactively-bound Ids
index 4aebe5b..56ebcd3 100644 (file)
 
           <row>
             <entry><option>-fdefer-type-errors</option></entry>
-            <entry>Defer as many type errors as possible until runtime.</entry>
+            <entry>
+                Turn type errors into warnings, <link linkend="defer-type-errors">
+                deferring the error until runtime</link>. Implies
+                <option>-fdefer-typed-holes</option>.
+            </entry>
             <entry>dynamic</entry>
             <entry><option>-fno-defer-type-errors</option></entry>
           </row>
 
           <row>
+            <entry><option>-fdefer-typed-holes</option></entry>
+            <entry>
+                Convert <link linkend="typed-holes">typed hole</link> errors
+                into warnings, <link linkend="defer-type-errors">deferring the
+                error until runtime</link>. Implied by
+                <option>-fdefer-type-errors</option>. See also
+                <option>-fwarn-typed-holes</option>.
+            </entry>
+            <entry>dynamic</entry>
+            <entry><option>-fno-defer-typed-holes</option></entry>
+          </row>
+
+          <row>
             <entry><option>-fhelpful-errors</option></entry>
             <entry>Make suggestions for mis-spelled names.</entry>
             <entry>dynamic</entry>
 
           <row>
             <entry><option>-fwarn-typed-holes</option></entry>
-            <entry>Enable <link linkend="typed-holes">holes</link> in expressions.</entry>
+            <entry>
+                Report warnings when <link linkend="typed-holes">typed hole</link>
+                errors are <link linkend="defer-type-errors">deferred until
+                runtime</link>. See <option>-fdefer-typed-holes</option>.
+            </entry>
             <entry>dynamic</entry>
             <entry><option>-fno-warn-typed-holes</option></entry>
           </row>
index f73a1d9..3d9e45c 100644 (file)
@@ -3,7 +3,7 @@
 <indexterm><primary>language, GHC</primary></indexterm>
 <indexterm><primary>extensions, GHC</primary></indexterm>
 As with all known Haskell systems, GHC implements some extensions to
-the language.  They can all be enabled or disabled by commandline flags
+the language.  They can all be enabled or disabled by command line flags
 or language pragmas. By default GHC understands the most recent Haskell
 version it supports, plus a handful of extensions.
 </para>
@@ -8423,31 +8423,37 @@ with <option>-XNoMonoLocalBinds</option> but type inference becomes less predica
 <sect1 id="typed-holes">
 <title>Typed Holes</title>
 
-<para>Typed hole support is enabled with the option
-<option>-fwarn-typed-holes</option>, which is enabled by default.</para>
-
 <para>
-This option allows special placeholders, written with a leading underscore (e.g. "<literal>_</literal>",
-"<literal>_foo</literal>", "<literal>_bar</literal>"), to be used as an expression.
-During compilation these holes will generate an error message describing what type is expected there,
-information about the origin of any free type variables, and a list of local bindings
-that might help fill the hole with actual code.
+Typed holes are a feature of GHC that allows special placeholders written with
+a leading underscore (e.g., "<literal>_</literal>", "<literal>_foo</literal>",
+"<literal>_bar</literal>"), to be used as expressions. During compilation these
+holes will generate an error message that describes which type is expected at
+the hole's location, information about the origin of any free type variables,
+and a list of local bindings that might help fill the hole with actual code.
+Typed holes are always enabled in GHC.
 </para>
 
 <para>
-The goal of the typed holes warning is not to change the type system, but to help with writing Haskell
-code. Typed holes can be used to obtain extra information from the type checker, which might otherwise be hard
-to get.
-Normally, using GHCi, users can inspect the (inferred) type signatures of all top-level bindings.
-However, this method is less convenient with terms which are not defined on top-level or
-inside complex expressions. Holes allow to check the type of the term you're about to write.
+The goal of typed holes is to help with writing Haskell code rather than to
+change the type system. Typed holes can be used to obtain extra information
+from the type checker, which might otherwise be hard to get. Normally, using
+GHCi, users can inspect the (inferred) type signatures of all top-level
+bindings. However, this method is less convenient with terms that are not
+defined on top-level or inside complex expressions. Holes allow the user to
+check the type of the term they are about to write.
 </para>
 
 <para>
-Holes work together well with <link linkend="defer-type-errors">deferring type errors to runtime</link>:
-with <literal>-fdefer-type-errors</literal>, the error from a hole is also deferred, effctively making the hole
-typecheck just like <literal>undefined</literal>, but with the added benefit that it will show its warning message
-if it gets evaluated. This way, other parts of the code can still be executed and tested.
+To run and test a piece of code containing holes, use the
+<literal>-fdefer-typed-holes</literal> flag. This flag defers errors
+produced by typed holes and converts them into warnings. The result is that
+typed hole errors are converted into warnings (controlled by
+<literal>-fwarn-typed-holes</literal>). The result is that a hole will behave
+like <literal>undefined</literal>, but with the added benefits that it shows a
+warning at compile time and will show another warning message if it gets
+evaluated. This behaviour follows that of the
+<literal>-fdefer-type-errors</literal> option, which implies
+<literal>-fdefer-typed-holes</literal>. See <xref linkend="defer-type-errors"/>.
 </para>
 
 <para>
@@ -8558,6 +8564,15 @@ main = print "b"
     warnings, but will not prevent compilation.
   </para>
   <para>
+    This flag implies the <literal>-fdefer-typed-holes</literal> flag,
+    which enables this behaviour for <link linkend="typed-holes">typed holes
+    </link>. Should you so wish, it is possible to enable
+    <literal>-fdefer-type-errors</literal> without enabling
+    <literal>-fdefer-typed-holes</literal>, by explicitly specifying
+    <literal>-fno-defer-typed-holes</literal> on the commandline after the
+    <literal>-fdefer-type-errors</literal> flag.
+  </para>
+  <para>
     At runtime, whenever a term containing a type error would need to be
     evaluated, the error is converted into a runtime exception.
     Note that type errors are deferred as much as possible during runtime, but
index a3b3d05..309be8c 100644 (file)
@@ -1131,14 +1131,11 @@ test.hs:(5,4)-(6,7):
           <indexterm><primary><option>-fwarn-typed-holes</option></primary>
           </indexterm>
           <indexterm><primary>warnings</primary></indexterm>
-            <para>When the compiler encounters an unbound local
-            variable prefixed with <literal>_</literal>, or encounters
-            the literal <literal>_</literal> on the right-hand side of
-            an expression, the error message for the unbound term
-            includes the type it needs to type check. It works
-            particularly well with <link
-            linkend="defer-type-errors">deferred type errors</link>.
-            See <xref linkend="typed-holes"/></para>
+          <para>
+              Determines whether the compiler reports typed holes warnings. Has
+              no effect unless typed holes errors are deferred until runtime.
+              See <xref linkend="typed-holes"/> and <xref linkend="defer-type-errors"/>
+            </para>
 
             <para>This warning is on by default.</para>
         </listitem>
@@ -1160,6 +1157,27 @@ test.hs:(5,4)-(6,7):
       </varlistentry>
 
       <varlistentry>
+        <term><option>-fdefer-typed-holes</option>:</term>
+        <listitem>
+          <indexterm><primary><option>-fdefer-typed-holes</option></primary>
+          </indexterm>
+          <indexterm><primary>warnings</primary></indexterm>
+          <para>
+              Defer typed holes errors until runtime. This will turn the errors
+              produced by <link linked="typed-holes">typed holes</link> into
+              warnings. Using a value that depends on a typed hole produces a
+              runtime error, the same as <option>-fdefer-type-errors</option>
+              (which implies this option). See <xref linkend="typed-holes"/>
+              and <xref linkend="defer-type-errors"/>.
+          </para>
+          <para>
+              Implied by <option>-fdefer-type-errors</option>. See also
+              <option>-fwarn-typed-holes</option>.
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
         <term><option>-fhelpful-errors</option>:</term>
         <listitem>
           <indexterm><primary><option>-fhelpful-errors</option></primary>
index f42d17d..7cf7e0b 100644 (file)
@@ -1,2 +1,11 @@
 
-mod71.hs:4:9: Pattern syntax in expression context: _
+mod71.hs:4:9:
+    Found hole ‘_’ with type: t1
+    Where: ‘t1’ is a rigid type variable bound by
+                the inferred type of f :: (t1 -> a -> t) -> t at mod71.hs:4:1
+    Relevant bindings include
+      x :: t1 -> a -> t (bound at mod71.hs:4:3)
+      f :: (t1 -> a -> t) -> t (bound at mod71.hs:4:1)
+    In the first argument of ‘x’, namely ‘_’
+    In the expression: x _ 1
+    In an equation for ‘f’: f x = x _ 1
index b24db3c..eeeddfa 100644 (file)
@@ -2,5 +2,3 @@
 rnfail016.hs:6:7: Pattern syntax in expression context: x@x
 
 rnfail016.hs:7:7: Pattern syntax in expression context: ~x
-
-rnfail016.hs:8:7: Pattern syntax in expression context: _
diff --git a/testsuite/tests/typecheck/should_compile/T9497a.hs b/testsuite/tests/typecheck/should_compile/T9497a.hs
new file mode 100644 (file)
index 0000000..fa30912
--- /dev/null
@@ -0,0 +1,2 @@
+main :: IO ()
+main = _main
diff --git a/testsuite/tests/typecheck/should_compile/T9497a.stderr b/testsuite/tests/typecheck/should_compile/T9497a.stderr
new file mode 100644 (file)
index 0000000..763fbae
--- /dev/null
@@ -0,0 +1,6 @@
+
+T9497a.hs:2:8: Warning:
+    Found hole ‘_main’ with type: IO ()
+    Relevant bindings include main :: IO () (bound at T9497a.hs:2:1)
+    In the expression: _main
+    In an equation for ‘main’: main = _main
diff --git a/testsuite/tests/typecheck/should_compile/T9497b.hs b/testsuite/tests/typecheck/should_compile/T9497b.hs
new file mode 100644 (file)
index 0000000..fa30912
--- /dev/null
@@ -0,0 +1,2 @@
+main :: IO ()
+main = _main
diff --git a/testsuite/tests/typecheck/should_compile/T9497b.stderr b/testsuite/tests/typecheck/should_compile/T9497b.stderr
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/testsuite/tests/typecheck/should_compile/T9497c.hs b/testsuite/tests/typecheck/should_compile/T9497c.hs
new file mode 100644 (file)
index 0000000..fa30912
--- /dev/null
@@ -0,0 +1,2 @@
+main :: IO ()
+main = _main
diff --git a/testsuite/tests/typecheck/should_compile/T9497c.stderr b/testsuite/tests/typecheck/should_compile/T9497c.stderr
new file mode 100644 (file)
index 0000000..e69de29
index 8acfa4a..b16ff43 100644 (file)
@@ -428,3 +428,6 @@ test('T9404b', normal, compile, [''])
 test('T7220', normal, compile, [''])
 test('T7220a', normal, compile_fail, [''])
 test('T9151', normal, compile, [''])
+test('T9497a', normal, compile, ['-fdefer-typed-holes'])
+test('T9497b', normal, compile, ['-fdefer-typed-holes -fno-warn-typed-holes'])
+test('T9497c', normal, compile, ['-fdefer-type-errors -fno-warn-typed-holes'])
diff --git a/testsuite/tests/typecheck/should_fail/T9497d.hs b/testsuite/tests/typecheck/should_fail/T9497d.hs
new file mode 100644 (file)
index 0000000..fa30912
--- /dev/null
@@ -0,0 +1,2 @@
+main :: IO ()
+main = _main
diff --git a/testsuite/tests/typecheck/should_fail/T9497d.stderr b/testsuite/tests/typecheck/should_fail/T9497d.stderr
new file mode 100644 (file)
index 0000000..4f18ce9
--- /dev/null
@@ -0,0 +1,6 @@
+
+T9497d.hs:2:8:
+    Found hole ‘_main’ with type: IO ()
+    Relevant bindings include main :: IO () (bound at T9497d.hs:2:1)
+    In the expression: _main
+    In an equation for ‘main’: main = _main
index 96396d2..81ea3d2 100644 (file)
@@ -343,3 +343,4 @@ test('T9774', normal, compile_fail, [''])
 test('T9318', normal, compile_fail, [''])
 test('T9201', normal, compile_fail, [''])
 test('T9109', normal, compile_fail, [''])
+test('T9497d', normal, compile_fail, ['-fdefer-type-errors -fno-defer-typed-holes'])
diff --git a/testsuite/tests/typecheck/should_run/T9497a-run.hs b/testsuite/tests/typecheck/should_run/T9497a-run.hs
new file mode 100644 (file)
index 0000000..fa30912
--- /dev/null
@@ -0,0 +1,2 @@
+main :: IO ()
+main = _main
diff --git a/testsuite/tests/typecheck/should_run/T9497a-run.stderr b/testsuite/tests/typecheck/should_run/T9497a-run.stderr
new file mode 100644 (file)
index 0000000..aae24cf
--- /dev/null
@@ -0,0 +1,7 @@
+T9497a-run: T9497a-run.hs:2:8:
+    Found hole ‘_main’ with type: IO ()
+    Relevant bindings include
+      main :: IO () (bound at T9497a-run.hs:2:1)
+    In the expression: _main
+    In an equation for ‘main’: main = _main
+(deferred type error)
diff --git a/testsuite/tests/typecheck/should_run/T9497b-run.hs b/testsuite/tests/typecheck/should_run/T9497b-run.hs
new file mode 100644 (file)
index 0000000..fa30912
--- /dev/null
@@ -0,0 +1,2 @@
+main :: IO ()
+main = _main
diff --git a/testsuite/tests/typecheck/should_run/T9497b-run.stderr b/testsuite/tests/typecheck/should_run/T9497b-run.stderr
new file mode 100644 (file)
index 0000000..62d858f
--- /dev/null
@@ -0,0 +1,7 @@
+T9497b-run: T9497b-run.hs:2:8:
+    Found hole ‘_main’ with type: IO ()
+    Relevant bindings include
+      main :: IO () (bound at T9497b-run.hs:2:1)
+    In the expression: _main
+    In an equation for ‘main’: main = _main
+(deferred type error)
diff --git a/testsuite/tests/typecheck/should_run/T9497c-run.hs b/testsuite/tests/typecheck/should_run/T9497c-run.hs
new file mode 100644 (file)
index 0000000..fa30912
--- /dev/null
@@ -0,0 +1,2 @@
+main :: IO ()
+main = _main
diff --git a/testsuite/tests/typecheck/should_run/T9497c-run.stderr b/testsuite/tests/typecheck/should_run/T9497c-run.stderr
new file mode 100644 (file)
index 0000000..be5d947
--- /dev/null
@@ -0,0 +1,7 @@
+T9497c-run: T9497c-run.hs:2:8:
+    Found hole ‘_main’ with type: IO ()
+    Relevant bindings include
+      main :: IO () (bound at T9497c-run.hs:2:1)
+    In the expression: _main
+    In an equation for ‘main’: main = _main
+(deferred type error)
index 5da7c8b..53c97ea 100755 (executable)
@@ -112,3 +112,6 @@ test('TcTypeNatSimpleRun', normal, compile_and_run, [''])
 test('T8119', normal, ghci_script, ['T8119.script'])
 test('T8492', normal, compile_and_run, [''])
 test('T8739', normal, compile_and_run, [''])
+test('T9497a-run', [exit_code(1)], compile_and_run, ['-fdefer-typed-holes'])
+test('T9497b-run', [exit_code(1)], compile_and_run, ['-fdefer-typed-holes -fno-warn-typed-holes'])
+test('T9497c-run', [exit_code(1)], compile_and_run, ['-fdefer-type-errors -fno-warn-typed-holes'])