summaryrefslogtreecommitdiff
path: root/compiler/GHC/HsToCore/PmCheck.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/GHC/HsToCore/PmCheck.hs')
-rw-r--r--compiler/GHC/HsToCore/PmCheck.hs75
1 files changed, 41 insertions, 34 deletions
diff --git a/compiler/GHC/HsToCore/PmCheck.hs b/compiler/GHC/HsToCore/PmCheck.hs
index 31ac10f0a0..6ba760369b 100644
--- a/compiler/GHC/HsToCore/PmCheck.hs
+++ b/compiler/GHC/HsToCore/PmCheck.hs
@@ -14,11 +14,11 @@ Pattern Matching Coverage Checking.
module GHC.HsToCore.PmCheck (
-- Checking and printing
- checkSingle, checkMatches, checkGRHSs,
+ covCheckPatBind, covCheckMatchGroup, covCheckGRHSs,
isMatchContextPmChecked,
-- See Note [Type and Term Equality Propagation]
- addTyCsDs, addScrutTmCs
+ addTyCsDs, addCoreScrutTmCs, addHsScrutTmCs
) where
#include "HsVersions.h"
@@ -283,37 +283,38 @@ instance Outputable CheckResult where
{-
%************************************************************************
%* *
- Entry points to the checker: checkSingle and checkMatches
+ Entry points to the checker: covCheckPatBind and covCheckMatchGroup
%* *
%************************************************************************
-}
--- | Check a single pattern binding (let) for exhaustiveness.
-checkSingle :: DynFlags -> DsMatchContext -> Id -> Pat GhcTc -> DsM ()
-checkSingle dflags ctxt@(DsMatchContext kind locn) var p = do
- tracePm "checkSingle" (vcat [ppr ctxt, ppr var, ppr p])
+-- | Check a pattern binding (let, where) for exhaustiveness.
+covCheckPatBind :: DynFlags -> DsMatchContext -> Id -> Pat GhcTc -> DsM ()
+covCheckPatBind dflags ctxt@(DsMatchContext _ locn) var p = do
-- We only ever need to run this in a context where we need exhaustivity
-- warnings (so not in pattern guards or comprehensions, for example, because
-- they are perfectly fine to fail).
-- Omitting checking this flag emits redundancy warnings twice in obscure
-- cases like #17646.
- when (exhaustive dflags kind) $ do
- -- TODO: This could probably call checkMatches, like checkGRHSs.
- missing <- getPmDeltas
- tracePm "checkSingle: missing" (ppr missing)
- fam_insts <- dsGetFamInstEnvs
- grd_tree <- mkGrdTreeRhs (L locn $ ppr p) <$> translatePat fam_insts var p
- res <- checkGrdTree grd_tree missing
- dsPmWarn dflags ctxt [var] res
+ -- Given the context in which this function is called, it will only ever do
+ -- something for
+ -- * PatBindRhs, -Wincomplete-uni-patterns: @let True = False@
+ -- * PatBindGuards, -Wincomplete-patterns: @Just x | False = Just 42@
+ missing <- getPmDeltas
+ tracePm "covCheckPatBind" (vcat [ppr ctxt, ppr var, ppr p, ppr missing])
+ fam_insts <- dsGetFamInstEnvs
+ grd_tree <- mkGrdTreeRhs (L locn $ ppr p) <$> translatePat fam_insts var p
+ res <- checkGrdTree grd_tree missing
+ dsPmWarn dflags ctxt [var] res
-- | Exhaustive for guard matches, is used for guards in pattern bindings and
-- in @MultiIf@ expressions. Returns the 'Deltas' covered by the RHSs.
-checkGRHSs
+covCheckGRHSs
:: HsMatchContext GhcRn -- ^ Match context, for warning messages
-> GRHSs GhcTc (LHsExpr GhcTc) -- ^ The GRHSs to check
-> DsM (NonEmpty Deltas) -- ^ Covered 'Deltas' for each RHS, for long
-- distance info
-checkGRHSs hs_ctx guards@(GRHSs _ grhss _) = do
+covCheckGRHSs hs_ctx guards@(GRHSs _ grhss _) = do
let combinedLoc = foldl1 combineSrcSpans (map getLoc grhss)
dsMatchContext = DsMatchContext hs_ctx combinedLoc
match = L combinedLoc $
@@ -321,7 +322,7 @@ checkGRHSs hs_ctx guards@(GRHSs _ grhss _) = do
, m_ctxt = hs_ctx
, m_pats = []
, m_grhss = guards }
- [(_, deltas)] <- checkMatches dsMatchContext [] [match]
+ [(_, deltas)] <- covCheckMatchGroup dsMatchContext [] [match]
pure deltas
-- | Check a list of syntactic /match/es (part of case, functions, etc.), each
@@ -337,14 +338,14 @@ checkGRHSs hs_ctx guards@(GRHSs _ grhss _) = do
-- incoming uncovered 'Deltas' (from 'getPmDeltas') if the GRHS is inaccessible.
-- Since there is at least one /grhs/ per /match/, the list of 'Deltas' is at
-- least as long as the list of matches.
-checkMatches
+covCheckMatchGroup
:: DsMatchContext -- ^ Match context, for warnings messages
-> [Id] -- ^ Match variables, i.e. x and y above
-> [LMatch GhcTc (LHsExpr GhcTc)] -- ^ List of matches
-> DsM [(Deltas, NonEmpty Deltas)] -- ^ One covered 'Deltas' per RHS, for long
-- distance info.
-checkMatches ctxt vars matches = do
- tracePm "checkMatches" (hang (vcat [ppr ctxt
+covCheckMatchGroup ctxt vars matches = do
+ tracePm "covCheckMatchGroup" (hang (vcat [ppr ctxt
, ppr vars
, text "Matches:"])
2
@@ -1112,7 +1113,7 @@ f x = case x of
(_:_) -> True
[] -> False -- can't happen
-Functions `addScrutTmCs' is responsible for generating
+Functions `add*ScrutTmCs' is responsible for generating
these constraints.
-}
@@ -1141,17 +1142,24 @@ addTyCsDs origin ev_vars m = do
(locallyExtendPmDelta (\deltas -> addPmCtsDeltas deltas (PmTyCt . evVarPred <$> ev_vars)))
m
--- | Add equalities for the scrutinee to the local 'DsM' environment when
--- checking a case expression:
+-- | Add equalities for the 'CoreExpr' scrutinee to the local 'DsM' environment
+-- when checking a case expression:
-- case e of x { matches }
-- When checking matches we record that (x ~ e) where x is the initial
-- uncovered. All matches will have to satisfy this equality.
-addScrutTmCs :: Maybe (LHsExpr GhcTc) -> [Id] -> DsM a -> DsM a
-addScrutTmCs Nothing _ k = k
-addScrutTmCs (Just scr) [x] k = do
+addCoreScrutTmCs :: Maybe CoreExpr -> [Id] -> DsM a -> DsM a
+addCoreScrutTmCs Nothing _ k = k
+addCoreScrutTmCs (Just scr) [x] k =
+ flip locallyExtendPmDelta k $ \deltas ->
+ addPmCtsDeltas deltas (unitBag (PmCoreCt x scr))
+addCoreScrutTmCs _ _ _ = panic "addCoreScrutTmCs: scrutinee, but more than one match id"
+
+-- | 'addCoreScrutTmCs', but desugars the 'LHsExpr' first.
+addHsScrutTmCs :: Maybe (LHsExpr GhcTc) -> [Id] -> DsM a -> DsM a
+addHsScrutTmCs Nothing _ k = k
+addHsScrutTmCs (Just scr) vars k = do
scr_e <- dsLExpr scr
- locallyExtendPmDelta (\deltas -> addPmCtsDeltas deltas (unitBag (PmCoreCt x scr_e))) k
-addScrutTmCs _ _ _ = panic "addScrutTmCs: HsCase with more than one case binder"
+ addCoreScrutTmCs (Just scr_e) vars k
{-
%************************************************************************
@@ -1169,7 +1177,7 @@ isMatchContextPmChecked dflags origin kind
| isGenerated origin
= False
| otherwise
- = wopt Opt_WarnOverlappingPatterns dflags || exhaustive dflags kind
+ = overlapping dflags kind || exhaustive dflags kind
-- | Return True when any of the pattern match warnings ('allPmCheckWarnings')
-- are enabled, in which case we need to run the pattern match checker.
@@ -1399,10 +1407,9 @@ exhaustiveWarningFlag RecUpd = Just Opt_WarnIncompletePatternsRecUpd
exhaustiveWarningFlag ThPatSplice = Nothing
exhaustiveWarningFlag PatSyn = Nothing
exhaustiveWarningFlag ThPatQuote = Nothing
-exhaustiveWarningFlag (StmtCtxt {}) = Nothing -- Don't warn about incomplete patterns
- -- in list comprehensions, pattern guards
- -- etc. They are often *supposed* to be
- -- incomplete
+-- Don't warn about incomplete patterns in list comprehensions, pattern guards
+-- etc. They are often *supposed* to be incomplete
+exhaustiveWarningFlag (StmtCtxt {}) = Nothing
-- True <==> singular
pprContext :: Bool -> DsMatchContext -> SDoc -> ((SDoc -> SDoc) -> SDoc) -> SDoc