summaryrefslogtreecommitdiff
path: root/compiler/simplCore/SimplUtils.hs
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2018-07-25 16:41:16 +0100
committerSimon Peyton Jones <simonpj@microsoft.com>2018-07-25 16:41:16 +0100
commit9897f6783a58265d5eaef5fb06f04320c7737e87 (patch)
tree0997b497d930f01a3ba93f23a44211a9007fb5e0 /compiler/simplCore/SimplUtils.hs
parent0f5a63e3d763f18c683f076e0e96396166863f56 (diff)
downloadhaskell-9897f6783a58265d5eaef5fb06f04320c7737e87.tar.gz
Fix PrelRules.caseRules to account for out-of-range tags
As Trac #15436 points out, it is possible to get case dataToTag# (x :: T) of DEFAULT -> blah1 -1# -> blah2 0 -> blah3 The (-1#) alterantive is unreachable, because dataToTag# returns tags in the range [0..n-1] where n is the number of data constructors in type T. This actually made GHC crash; now we simply discard the unreachable alterantive. See Note [Unreachable caseRules alternatives] in PrelRules
Diffstat (limited to 'compiler/simplCore/SimplUtils.hs')
-rw-r--r--compiler/simplCore/SimplUtils.hs33
1 files changed, 21 insertions, 12 deletions
diff --git a/compiler/simplCore/SimplUtils.hs b/compiler/simplCore/SimplUtils.hs
index e5d9d33899..83ad059171 100644
--- a/compiler/simplCore/SimplUtils.hs
+++ b/compiler/simplCore/SimplUtils.hs
@@ -2146,7 +2146,12 @@ mkCase2 dflags scrut bndr alts_ty alts
, gopt Opt_CaseFolding dflags
, Just (scrut', tx_con, mk_orig) <- caseRules dflags scrut
= do { bndr' <- newId (fsLit "lwild") (exprType scrut')
- ; alts' <- mapM (tx_alt tx_con mk_orig bndr') alts
+
+ ; alts' <- mapMaybeM (tx_alt tx_con mk_orig bndr') alts
+ -- mapMaybeM: discard unreachable alternatives
+ -- See Note [Unreachable caseRules alternatives]
+ -- in PrelRules
+
; mkCase3 dflags scrut' bndr' alts_ty $
add_default (re_sort alts')
}
@@ -2170,19 +2175,14 @@ mkCase2 dflags scrut bndr alts_ty alts
-- to construct an expression equivalent to the original one, for use
-- in the DEFAULT case
+ tx_alt :: (AltCon -> Maybe AltCon) -> (Id -> CoreExpr) -> Id
+ -> CoreAlt -> SimplM (Maybe CoreAlt)
tx_alt tx_con mk_orig new_bndr (con, bs, rhs)
- | DataAlt dc <- con', not (isNullaryRepDataCon dc)
- = -- For non-nullary data cons we must invent some fake binders
- -- See Note [caseRules for dataToTag] in PrelRules
- do { us <- getUniquesM
- ; let (ex_tvs, arg_ids) = dataConRepInstPat us dc
- (tyConAppArgs (idType new_bndr))
- ; return (con', ex_tvs ++ arg_ids, rhs') }
- | otherwise
- = return (con', [], rhs')
+ = case tx_con con of
+ Nothing -> return Nothing
+ Just con' -> do { bs' <- mk_new_bndrs new_bndr con'
+ ; return (Just (con', bs', rhs')) }
where
- con' = tx_con con
-
rhs' | isDeadBinder bndr = rhs
| otherwise = bindNonRec bndr orig_val rhs
@@ -2191,6 +2191,15 @@ mkCase2 dflags scrut bndr alts_ty alts
LitAlt l -> Lit l
DataAlt dc -> mkConApp2 dc (tyConAppArgs (idType bndr)) bs
+ mk_new_bndrs new_bndr (DataAlt dc)
+ | not (isNullaryRepDataCon dc)
+ = -- For non-nullary data cons we must invent some fake binders
+ -- See Note [caseRules for dataToTag] in PrelRules
+ do { us <- getUniquesM
+ ; let (ex_tvs, arg_ids) = dataConRepInstPat us dc
+ (tyConAppArgs (idType new_bndr))
+ ; return (ex_tvs ++ arg_ids) }
+ mk_new_bndrs _ _ = return []
re_sort :: [CoreAlt] -> [CoreAlt] -- Re-sort the alternatives to
re_sort alts = sortBy cmpAlt alts -- preserve the #case_invariants#