[Git][ghc/ghc][wip/pm-no-ewildpat] Stop misusing EWildPat in pattern match coverage checking

Vladislav Zavialov gitlab at gitlab.haskell.org
Fri Apr 19 15:56:32 UTC 2019



Vladislav Zavialov pushed to branch wip/pm-no-ewildpat at Glasgow Haskell Compiler / GHC


Commits:
6835f0fe by Vladislav Zavialov at 2019-04-19T15:55:23Z
Stop misusing EWildPat in pattern match coverage checking

EWildPat is a constructor of HsExpr used in the parser to represent
wildcards in ambiguous positions:

* in expression context, EWildPat is turned into hsHoleExpr (see rnExpr)
* in pattern context, EWildPat is turned into WildPat (see checkPattern)

Since EWildPat exists solely for the needs of the parser, we could
remove it by improving the parser.

However, EWildPat has also been used for a different purpose since
8a50610: to represent patterns that the coverage checker cannot handle.
Not only this is a misuse of EWildPat, it also stymies the removal of
EWildPat.

- - - - -


1 changed file:

- compiler/deSugar/Check.hs


Changes:

=====================================
compiler/deSugar/Check.hs
=====================================
@@ -157,7 +157,8 @@ data PmPat :: PatTy -> * where
   PmNLit :: { pm_lit_id   :: Id
             , pm_lit_not  :: [PmLit] } -> PmPat 'VA
   PmGrd  :: { pm_grd_pv   :: PatVec
-            , pm_grd_expr :: PmExpr  } -> PmPat 'PAT
+            , pm_grd_expr :: PmExpr } -> PmPat 'PAT
+  PmFake :: PmPat 'PAT
 
 instance Outputable (PmPat a) where
   ppr = pprPmPatDebug
@@ -930,17 +931,9 @@ truePattern = nullaryConPattern (RealDataCon trueDataCon)
 
 -- | A fake guard pattern (True <- _) used to represent cases we cannot handle
 fake_pat :: Pattern
-fake_pat = PmGrd { pm_grd_pv   = [truePattern]
-                 , pm_grd_expr = PmExprOther (EWildPat noExt) }
+fake_pat = PmFake
 {-# INLINE fake_pat #-}
 
--- | Check whether a guard pattern is generated by the checker (unhandled)
-isFakeGuard :: [Pattern] -> PmExpr -> Bool
-isFakeGuard [PmCon { pm_con_con = RealDataCon c }] (PmExprOther (EWildPat _))
-  | c == trueDataCon = True
-  | otherwise        = False
-isFakeGuard _pats _e = False
-
 -- | Generate a `canFail` pattern vector of a specific type
 mkCanFailPmPat :: Type -> DsM PatVec
 mkCanFailPmPat ty = do
@@ -1457,6 +1450,7 @@ pmPatType (PmNLit { pm_lit_id  = x }) = idType x
 pmPatType (PmGrd  { pm_grd_pv  = pv })
   = ASSERT(patVecArity pv == 1) (pmPatType p)
   where Just p = find ((==1) . patternArity) pv
+pmPatType PmFake = pmPatType truePattern
 
 -- | Information about a conlike that is relevant to coverage checking.
 -- It is called an \"inhabitation candidate\" since it is a value which may
@@ -1753,6 +1747,7 @@ coercePmPat (PmCon { pm_con_con = con, pm_con_arg_tys = arg_tys
            , pm_con_tvs  = tvs, pm_con_dicts = dicts
            , pm_con_args = coercePatVec args }]
 coercePmPat (PmGrd {}) = [] -- drop the guards
+coercePmPat PmFake     = [] -- drop the guards
 
 -- | Check whether a 'ConLike' has the /single match/ property, i.e. whether
 -- it is the only possible match in the given context. See also
@@ -2023,13 +2018,15 @@ pmcheck [] guards vva@(ValVec [] _)
   | otherwise   = pmcheckGuardsI guards vva
 
 -- Guard
-pmcheck (p@(PmGrd pv e) : ps) guards vva@(ValVec vas delta)
-    -- short-circuit if the guard pattern is useless.
-    -- we just have two possible outcomes: fail here or match and recurse
-    -- none of the two contains any useful information about the failure
-    -- though. So just have these two cases but do not do all the boilerplate
-  | isFakeGuard pv e = forces . mkCons vva <$> pmcheckI ps guards vva
-  | otherwise = do
+pmcheck (PmFake : ps) guards vva =
+  -- short-circuit if the guard pattern is useless.
+  -- we just have two possible outcomes: fail here or match and recurse
+  -- none of the two contains any useful information about the failure
+  -- though. So just have these two cases but do not do all the boilerplate
+  forces . mkCons vva <$> pmcheckI ps guards vva
+pmcheck (p : ps) guards (ValVec vas delta)
+  | PmGrd { pm_grd_pv = pv, pm_grd_expr = e } <- p
+  = do
       y <- liftD $ mkPmId (pmPatType p)
       let tm_state = extendSubst y e (delta_tm_cs delta)
           delta'   = delta { delta_tm_cs = tm_state }
@@ -2182,6 +2179,7 @@ pmcheckHd (p@(PmCon {})) ps guards (PmNLit { pm_lit_id = x }) vva
   = pmcheckHdI p ps guards (PmVar x) vva
 
 -- Impossible: handled by pmcheck
+pmcheckHd PmFake     _ _ _ _ = panic "pmcheckHd: Fake"
 pmcheckHd (PmGrd {}) _ _ _ _ = panic "pmcheckHd: Guard"
 
 {-
@@ -2742,6 +2740,7 @@ pprPmPatDebug (PmLit li)  = text "PmLit" <+> ppr li
 pprPmPatDebug (PmNLit i nl) = text "PmNLit" <+> ppr i <+> ppr nl
 pprPmPatDebug (PmGrd pv ge) = text "PmGrd" <+> hsep (map pprPmPatDebug pv)
                                            <+> ppr ge
+pprPmPatDebug PmFake = text "PmFake"
 
 pprPatVec :: PatVec -> SDoc
 pprPatVec ps = hang (text "Pattern:") 2



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/commit/6835f0fe79db21fb0afa36a6a198f332f7255672

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/commit/6835f0fe79db21fb0afa36a6a198f332f7255672
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20190419/1a6b794f/attachment-0001.html>


More information about the ghc-commits mailing list