summaryrefslogtreecommitdiff
path: root/compiler/GHC/Tc/Gen/Splice.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/GHC/Tc/Gen/Splice.hs')
-rw-r--r--compiler/GHC/Tc/Gen/Splice.hs68
1 files changed, 64 insertions, 4 deletions
diff --git a/compiler/GHC/Tc/Gen/Splice.hs b/compiler/GHC/Tc/Gen/Splice.hs
index 589513af97..7124dcd52e 100644
--- a/compiler/GHC/Tc/Gen/Splice.hs
+++ b/compiler/GHC/Tc/Gen/Splice.hs
@@ -34,6 +34,7 @@ module GHC.Tc.Gen.Splice(
import GHC.Prelude
+import GHC.Driver.Errors
import GHC.Driver.Plugins
import GHC.Driver.Main
import GHC.Driver.Session
@@ -42,6 +43,7 @@ import GHC.Driver.Hooks
import GHC.Hs
+import GHC.Tc.Errors.Types
import GHC.Tc.Utils.Monad
import GHC.Tc.Utils.TcType
import GHC.Tc.Gen.Expr
@@ -917,6 +919,48 @@ runMetaD :: LHsExpr GhcTc -- Of type Q [Dec]
-> TcM [LHsDecl GhcPs]
runMetaD = runMeta metaRequestD
+{- Note [Errors in desugaring a splice]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+What should we do if there are errors when desugaring a splice? We should
+abort. There are several cases to consider:
+
+(a) The desugarer hits an unrecoverable error and fails in the monad.
+(b) The desugarer hits a recoverable error, reports it, and continues.
+(c) The desugarer reports a fatal warning (with -Werror), reports it, and continues.
+(d) The desugarer reports a non-fatal warning, and continues.
+
+Each case is tested in th/T19709[abcd].
+
+General principle: we wish to report all messages from dealing with a splice
+eagerly, as these messages arise during an earlier stage than type-checking
+generally. It's also likely that a compile-time warning from spliced code
+will be easier to understand then an error that arises from processing the
+code the splice produces. (Rationale: the warning will be about the code the
+user actually wrote, not what is generated.)
+
+Case (a): We have no choice but to abort here, but we must make sure that
+the messages are printed or logged before aborting. Logging them is annoying,
+because we're in the type-checker, and the messages are DsMessages, from the
+desugarer. So we report and then fail in the monad. This case is detected
+by the fact that initDsTc returns Nothing.
+
+Case (b): We detect this case by looking for errors in the messages returned
+from initDsTc and aborting if we spot any (after printing, of course). Note
+that initDsTc will return a Just ds_expr in this case, but we don't wish to
+use the (likely very bogus) expression.
+
+Case (c): This is functionally the same as (b), except that the expression
+isn't bogus. We still don't wish to use it, as the user's request for -Werror
+tells us not to.
+
+Case (d): We report the warnings and then carry on with the expression.
+This might result in warnings printed out of source order, but this is
+appropriate, as the warnings from the splice arise from an earlier stage
+of compilation.
+
+Previously, we failed to abort in cases (b) and (c), leading to #19709.
+-}
+
---------------
runMeta' :: Bool -- Whether code should be printed in the exception message
-> (hs_syn -> SDoc) -- how to print the code
@@ -932,11 +976,11 @@ runMeta' show_code ppr_hs run_and_convert expr
-- Check that we've had no errors of any sort so far.
-- For example, if we found an error in an earlier defn f, but
-- recovered giving it type f :: forall a.a, it'd be very dodgy
- -- to carry ont. Mind you, the staging restrictions mean we won't
+ -- to carry on. Mind you, the staging restrictions mean we won't
-- actually run f, but it still seems wrong. And, more concretely,
-- see #5358 for an example that fell over when trying to
-- reify a function with a "?" kind in it. (These don't occur
- -- in type-correct programs.
+ -- in type-correct programs.)
; failIfErrsM
-- run plugins
@@ -944,7 +988,23 @@ runMeta' show_code ppr_hs run_and_convert expr
; expr' <- withPlugins hsc_env spliceRunAction expr
-- Desugar
- ; ds_expr <- initDsTc (dsLExpr expr')
+ ; (ds_msgs, mb_ds_expr) <- initDsTc (dsLExpr expr')
+
+ -- Print any messages (even warnings) eagerly: they might be helpful if anything
+ -- goes wrong. See Note [Errors in desugaring a splice]. This happens in all
+ -- cases.
+ ; logger <- getLogger
+ ; dflags <- getDynFlags
+ ; liftIO $ printMessages logger dflags ds_msgs
+
+ ; ds_expr <- case mb_ds_expr of
+ Nothing -> failM -- Case (a) from Note [Errors in desugaring a splice]
+ Just ds_expr -> -- There still might be a fatal warning or recoverable
+ -- Cases (b) and (c) from Note [Errors in desugaring a splice]
+ do { when (errorsOrFatalWarningsFound ds_msgs)
+ failM
+ ; return ds_expr }
+
-- Compile and link it; might fail if linking fails
; src_span <- getSrcSpanM
; traceTc "About to run (desugared)" (ppr ds_expr)
@@ -1442,7 +1502,7 @@ runTH ty fhv = do
-- See Note [Remote Template Haskell] in libraries/ghci/GHCi/TH.hs.
runRemoteTH
:: IServInstance
- -> [Messages DiagnosticMessage] -- saved from nested calls to qRecover
+ -> [Messages TcRnMessage] -- saved from nested calls to qRecover
-> TcM ()
runRemoteTH iserv recovers = do
THMsg msg <- liftIO $ readIServ iserv getTHMessage