summaryrefslogtreecommitdiff
path: root/compiler/GHC/Rename/Bind.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/GHC/Rename/Bind.hs')
-rw-r--r--compiler/GHC/Rename/Bind.hs59
1 files changed, 49 insertions, 10 deletions
diff --git a/compiler/GHC/Rename/Bind.hs b/compiler/GHC/Rename/Bind.hs
index adfceeef96..0239bf759b 100644
--- a/compiler/GHC/Rename/Bind.hs
+++ b/compiler/GHC/Rename/Bind.hs
@@ -1189,15 +1189,43 @@ type AnnoBody body
, Outputable (body GhcPs)
)
+-- Note [Empty MatchGroups]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~
+-- In some cases, MatchGroups are allowed to be empty. Firstly, the
+-- prerequisite is that -XEmptyCase is enabled. Then you have an empty
+-- MatchGroup resulting either from a case-expression:
+--
+-- case e of {}
+--
+-- or from a \case-expression:
+--
+-- \case {}
+--
+-- NB: \cases {} is not allowed, since it's not clear how many patterns this
+-- should match on.
+--
+-- The same applies in arrow notation commands: With -XEmptyCases, it is
+-- allowed in case- and \case-commands, but not \cases.
+--
+-- Since the lambda expressions and empty function definitions are already
+-- disallowed elsewhere, here, we only need to make sure we don't accept empty
+-- \cases expressions or commands. In that case, or if we encounter an empty
+-- MatchGroup but -XEmptyCases is disabled, we add an error.
+
rnMatchGroup :: (Outputable (body GhcPs), AnnoBody body) => HsMatchContext GhcRn
-> (LocatedA (body GhcPs) -> RnM (LocatedA (body GhcRn), FreeVars))
-> MatchGroup GhcPs (LocatedA (body GhcPs))
-> RnM (MatchGroup GhcRn (LocatedA (body GhcRn)), FreeVars)
rnMatchGroup ctxt rnBody (MG { mg_alts = L lm ms, mg_origin = origin })
- = do { empty_case_ok <- xoptM LangExt.EmptyCase
- ; when (null ms && not empty_case_ok) (addErr (emptyCaseErr ctxt))
+ -- see Note [Empty MatchGroups]
+ = do { whenM ((null ms &&) <$> mustn't_be_empty) (addErr (emptyCaseErr ctxt))
; (new_ms, ms_fvs) <- mapFvRn (rnMatch ctxt rnBody) ms
; return (mkMatchGroup origin (L lm new_ms), ms_fvs) }
+ where
+ mustn't_be_empty = case ctxt of
+ LamCaseAlt LamCases -> return True
+ ArrowMatchCtxt (ArrowLamCaseAlt LamCases) -> return True
+ _ -> not <$> xoptM LangExt.EmptyCase
rnMatch :: AnnoBody body
=> HsMatchContext GhcRn
@@ -1222,17 +1250,28 @@ rnMatch' ctxt rnBody (Match { m_ctxt = mf, m_pats = pats, m_grhss = grhss })
, m_grhss = grhss'}, grhss_fvs ) }
emptyCaseErr :: HsMatchContext GhcRn -> TcRnMessage
-emptyCaseErr ctxt = TcRnUnknownMessage $ mkPlainError noHints $
- hang (text "Empty list of alternatives in" <+> pp_ctxt ctxt)
- 2 (text "Use EmptyCase to allow this")
+emptyCaseErr ctxt = TcRnUnknownMessage $ mkPlainError noHints $ message ctxt
where
pp_ctxt :: HsMatchContext GhcRn -> SDoc
pp_ctxt c = case c of
- CaseAlt -> text "case expression"
- LambdaExpr -> text "\\case expression"
- ArrowMatchCtxt ArrowCaseAlt -> text "case expression"
- ArrowMatchCtxt KappaExpr -> text "kappa abstraction"
- _ -> text "(unexpected)" <+> pprMatchContextNoun c
+ CaseAlt -> text "case expression"
+ LamCaseAlt LamCase -> text "\\case expression"
+ ArrowMatchCtxt (ArrowLamCaseAlt LamCase) -> text "\\case command"
+ ArrowMatchCtxt ArrowCaseAlt -> text "case command"
+ ArrowMatchCtxt KappaExpr -> text "kappa abstraction"
+ _ -> text "(unexpected)"
+ <+> pprMatchContextNoun c
+
+ message :: HsMatchContext GhcRn -> SDoc
+ message (LamCaseAlt LamCases) = lcases_msg <+> text "expression"
+ message (ArrowMatchCtxt (ArrowLamCaseAlt LamCases)) =
+ lcases_msg <+> text "command"
+ message ctxt =
+ hang (text "Empty list of alternatives in" <+> pp_ctxt ctxt)
+ 2 (text "Use EmptyCase to allow this")
+
+ lcases_msg =
+ text "Empty list of alternatives is not allowed in \\cases"
{-
************************************************************************