(F)SLIT -> (f)sLit in SimplUtils
[ghc-hetmet.git] / compiler / simplCore / SimplUtils.lhs
index cff659d..4ddcfb8 100644 (file)
@@ -20,10 +20,10 @@ module SimplUtils (
        activeInline, activeRule, inlineMode,
 
        -- The continuation type
-       SimplCont(..), DupFlag(..), LetRhsFlag(..), 
+       SimplCont(..), DupFlag(..), ArgInfo(..),
        contIsDupable, contResultType, contIsTrivial, contArgs, dropArgs, 
        countValArgs, countArgs, splitInlineCont,
-       mkBoringStop, mkLazyArgStop, mkRhsStop, contIsRhsOrArg,
+       mkBoringStop, mkLazyArgStop, contIsRhsOrArg,
        interestingCallContext, interestingArgContext,
 
        interestingArg, mkArgInfo,
@@ -50,13 +50,17 @@ import Var  ( isCoVar )
 import NewDemand
 import SimplMonad
 import Type    hiding( substTy )
+import Coercion ( coercionKind )
 import TyCon
 import DataCon
 import Unify   ( dataConCannotMatch )
 import VarSet
 import BasicTypes
 import Util
+import MonadUtils
 import Outputable
+import FastString
+
 import List( nub )
 \end{code}
 
@@ -90,15 +94,11 @@ Key points:
 \begin{code}
 data SimplCont 
   = Stop               -- An empty context, or hole, []     
-       OutType         -- Type of the result
-       LetRhsFlag
-       Bool            -- True <=> There is something interesting about
+       CallCtxt        -- True <=> There is something interesting about
                        --          the context, and hence the inliner
                        --          should be a bit keener (see interestingCallContext)
-                       -- Two cases:
-                       -- (a) This is the RHS of a thunk whose type suggests
-                       --     that update-in-place would be possible
-                       -- (b) This is an argument of a function that has RULES
+                       -- Specifically:
+                       --     This is an argument of a function that has RULES
                        --     Inlining the call might allow the rule to fire
 
   | CoerceIt           -- C `cast` co
@@ -122,44 +122,47 @@ data SimplCont
        SimplCont       
 
   | StrictArg          -- e C
-       OutExpr OutType         -- e and its type
-       (Bool,[Bool])           -- Whether the function at the head of e has rules,
-       SimplCont               --     plus strictness flags for further args
-
-data LetRhsFlag = AnArg                -- It's just an argument not a let RHS
-               | AnRhs         -- It's the RHS of a let (so please float lets out of big lambdas)
-
-instance Outputable LetRhsFlag where
-  ppr AnArg = ptext SLIT("arg")
-  ppr AnRhs = ptext SLIT("rhs")
+       OutExpr                 -- e 
+       CallCtxt                -- Whether *this* argument position is interesting
+       ArgInfo                 -- Whether the function at the head of e has rules, etc
+       SimplCont               --     plus strictness flags for *further* args
+
+data ArgInfo 
+  = ArgInfo {
+       ai_rules :: Bool,       -- Function has rules (recursively)
+                               --      => be keener to inline in all args
+       ai_strs :: [Bool],      -- Strictness of arguments
+                               --   Usually infinite, but if it is finite it guarantees
+                               --   that the function diverges after being given
+                               --   that number of args
+       ai_discs :: [Int]       -- Discounts for arguments; non-zero => be keener to inline
+                               --   Always infinite
+    }
 
 instance Outputable SimplCont where
-  ppr (Stop ty is_rhs _)            = ptext SLIT("Stop") <> brackets (ppr is_rhs) <+> ppr ty
-  ppr (ApplyTo dup arg se cont)      = ((ptext SLIT("ApplyTo") <+> ppr dup <+> pprParendExpr arg)
+  ppr (Stop interesting)            = ptext (sLit "Stop") <> brackets (ppr interesting)
+  ppr (ApplyTo dup arg se cont)      = ((ptext (sLit "ApplyTo") <+> ppr dup <+> pprParendExpr arg)
                                          {-  $$ nest 2 (pprSimplEnv se) -}) $$ ppr cont
-  ppr (StrictBind b _ _ _ cont)      = (ptext SLIT("StrictBind") <+> ppr b) $$ ppr cont
-  ppr (StrictArg f _ _ cont)         = (ptext SLIT("StrictArg") <+> ppr f) $$ ppr cont
-  ppr (Select dup bndr alts se cont) = (ptext SLIT("Select") <+> ppr dup <+> ppr bndr) $$ 
+  ppr (StrictBind b _ _ _ cont)      = (ptext (sLit "StrictBind") <+> ppr b) $$ ppr cont
+  ppr (StrictArg f _ _ cont)         = (ptext (sLit "StrictArg") <+> ppr f) $$ ppr cont
+  ppr (Select dup bndr alts se cont) = (ptext (sLit "Select") <+> ppr dup <+> ppr bndr) $$ 
                                       (nest 4 (ppr alts)) $$ ppr cont 
-  ppr (CoerceIt co cont)            = (ptext SLIT("CoerceIt") <+> ppr co) $$ ppr cont
+  ppr (CoerceIt co cont)            = (ptext (sLit "CoerceIt") <+> ppr co) $$ ppr cont
 
 data DupFlag = OkToDup | NoDup
 
 instance Outputable DupFlag where
-  ppr OkToDup = ptext SLIT("ok")
-  ppr NoDup   = ptext SLIT("nodup")
+  ppr OkToDup = ptext (sLit "ok")
+  ppr NoDup   = ptext (sLit "nodup")
 
 
 
 -------------------
-mkBoringStop :: OutType -> SimplCont
-mkBoringStop ty = Stop ty AnArg False
+mkBoringStop :: SimplCont
+mkBoringStop = Stop BoringCtxt
 
-mkLazyArgStop :: OutType -> Bool -> SimplCont
-mkLazyArgStop ty has_rules = Stop ty AnArg (canUpdateInPlace ty || has_rules)
-
-mkRhsStop :: OutType -> SimplCont
-mkRhsStop ty = Stop ty AnRhs (canUpdateInPlace ty)
+mkLazyArgStop :: CallCtxt -> SimplCont
+mkLazyArgStop cci = Stop cci
 
 -------------------
 contIsRhsOrArg (Stop {})                = True
@@ -183,13 +186,21 @@ contIsTrivial (CoerceIt _ cont)     = contIsTrivial cont
 contIsTrivial other                      = False
 
 -------------------
-contResultType :: SimplCont -> OutType
-contResultType (Stop to_ty _ _)                 = to_ty
-contResultType (StrictArg _ _ _ cont)   = contResultType cont
-contResultType (StrictBind _ _ _ _ cont) = contResultType cont
-contResultType (ApplyTo _ _ _ cont)     = contResultType cont
-contResultType (CoerceIt _ cont)        = contResultType cont
-contResultType (Select _ _ _ _ cont)    = contResultType cont
+contResultType :: SimplEnv -> OutType -> SimplCont -> OutType
+contResultType env ty cont
+  = go cont ty
+  where
+    subst_ty se ty = substTy (se `setInScope` env) ty
+
+    go (Stop {})                     ty = ty
+    go (CoerceIt co cont)            ty = go cont (snd (coercionKind co))
+    go (StrictBind _ bs body se cont) ty = go cont (subst_ty se (exprType (mkLams bs body)))
+    go (StrictArg fn _ _ cont)        ty = go cont (funResultTy (exprType fn))
+    go (Select _ _ alts se cont)      ty = go cont (subst_ty se (coreAltsType alts))
+    go (ApplyTo _ arg se cont)        ty = go cont (apply_to_arg ty arg se)
+
+    apply_to_arg ty (Type ty_arg) se = applyTy ty (subst_ty se ty_arg)
+    apply_to_arg ty other        se = funResultTy ty
 
 -------------------
 countValArgs :: SimplCont -> Int
@@ -225,13 +236,11 @@ splitInlineCont :: SimplCont -> Maybe (SimplCont, SimplCont)
 -- See test simpl017 (and Trac #1627) for a good example of why this is important
 
 splitInlineCont (ApplyTo dup (Type ty) se c)
-  | Just (c1, c2) <- splitInlineCont c                 = Just (ApplyTo dup (Type ty) se c1, c2)
-splitInlineCont cont@(Stop ty _ _)             = Just (mkBoringStop ty, cont)
-splitInlineCont cont@(StrictBind bndr _ _ se _) = Just (mkBoringStop (substTy se (idType bndr)), cont)
-splitInlineCont cont@(StrictArg _ fun_ty _ _)   = Just (mkBoringStop (funArgTy fun_ty), cont)
+  | Just (c1, c2) <- splitInlineCont c = Just (ApplyTo dup (Type ty) se c1, c2)
+splitInlineCont cont@(Stop {})         = Just (mkBoringStop, cont)
+splitInlineCont cont@(StrictBind {})   = Just (mkBoringStop, cont)
+splitInlineCont cont@(StrictArg  {})   = Just (mkBoringStop, cont)
 splitInlineCont other                          = Nothing
-       -- NB: the calculation of the type for mkBoringStop is an annoying
-       --     duplication of the same calucation in mkDupableCont
 \end{code}
 
 
@@ -304,23 +313,26 @@ default case.
 
 
 \begin{code}
-interestingCallContext :: SimplCont -> CallContInfo
+interestingCallContext :: SimplCont -> CallCtxt
 interestingCallContext cont
   = interesting cont
   where
+    interestingCtxt = ArgCtxt False 2  -- Give *some* incentive!
+
     interesting (Select _ bndr _ _ _)
-       | isDeadBinder bndr       = CaseCont
-       | otherwise               = InterestingCont
+       | isDeadBinder bndr       = CaseCtxt
+       | otherwise               = interestingCtxt
                
-    interesting (ApplyTo {})      = InterestingCont
-                                               -- Can happen if we have (coerce t (f x)) y
-                                               -- Perhaps True is a bit over-keen, but I've
-                                               -- seen (coerce f) x, where f has an INLINE prag,
-                                               -- So we have to give some motivation for inlining it
-    interesting (StrictArg {})   = InterestingCont
-    interesting (StrictBind {})          = InterestingCont
-    interesting (Stop ty _ yes)   = if yes then InterestingCont else BoringCont
-    interesting (CoerceIt _ cont) = interesting cont
+    interesting (ApplyTo {})      = interestingCtxt
+                               -- Can happen if we have (coerce t (f x)) y
+                               -- Perhaps interestingCtxt is a bit over-keen, but I've
+                               -- seen (coerce f) x, where f has an INLINE prag,
+                               -- So we have to give some motivation for inlining it
+
+    interesting (StrictArg _ cci _ _)  = cci
+    interesting (StrictBind {})                = BoringCtxt
+    interesting (Stop cci)             = cci
+    interesting (CoerceIt _ cont)      = interesting cont
        -- If this call is the arg of a strict function, the context
        -- is a bit interesting.  If we inline here, we may get useful
        -- evaluation information to avoid repeated evals: e.g.
@@ -341,21 +353,29 @@ interestingCallContext cont
 mkArgInfo :: Id
          -> Int        -- Number of value args
          -> SimplCont  -- Context of the cal
-         -> (Bool, [Bool])     -- Arg info
--- The arg info consists of
---  * A Bool indicating if the function has rules (recursively)
---  * A [Bool] indicating strictness for each arg
--- The [Bool] is usually infinite, but if it is finite it 
--- guarantees that the function diverges after being given
--- that number of args
+         -> ArgInfo
 
 mkArgInfo fun n_val_args call_cont
-  = (interestingArgContext fun call_cont, fun_stricts)
+  | n_val_args < idArity fun           -- Note [Unsaturated functions]
+  = ArgInfo { ai_rules = False
+           , ai_strs = vanilla_stricts 
+           , ai_discs = vanilla_discounts }
+  | otherwise
+  = ArgInfo { ai_rules = interestingArgContext fun call_cont
+           , ai_strs  = add_type_str (idType fun) arg_stricts
+           , ai_discs = arg_discounts }
   where
-    vanilla_stricts, fun_stricts :: [Bool]
+    vanilla_discounts, arg_discounts :: [Int]
+    vanilla_discounts = repeat 0
+    arg_discounts = case idUnfolding fun of
+                       CoreUnfolding _ _ _ _ (UnfoldIfGoodArgs _ discounts _ _)
+                             -> discounts ++ vanilla_discounts
+                       other -> vanilla_discounts
+
+    vanilla_stricts, arg_stricts :: [Bool]
     vanilla_stricts  = repeat False
 
-    fun_stricts
+    arg_stricts
       = case splitStrictSig (idNewStrictness fun) of
          (demands, result_info)
                | not (demands `lengthExceeds` n_val_args)
@@ -370,8 +390,37 @@ mkArgInfo fun n_val_args call_cont
                        map isStrictDmd demands         -- Finite => result is bottom
                   else
                        map isStrictDmd demands ++ vanilla_stricts
-
-         other -> vanilla_stricts      -- Not enough args, or no strictness
+              | otherwise
+              -> WARN( True, text "More demands than arity" <+> ppr fun <+> ppr (idArity fun) 
+                               <+> ppr n_val_args <+> ppr demands ) 
+                  vanilla_stricts      -- Not enough args, or no strictness
+
+    add_type_str :: Type -> [Bool] -> [Bool]
+    -- If the function arg types are strict, record that in the 'strictness bits'
+    -- No need to instantiate because unboxed types (which dominate the strict
+    -- types) can't instantiate type variables.
+    -- add_type_str is done repeatedly (for each call); might be better 
+    -- once-for-all in the function
+    -- But beware primops/datacons with no strictness
+    add_type_str fun_ty [] = []
+    add_type_str fun_ty strs           -- Look through foralls
+       | Just (tv, fun_ty') <- splitForAllTy_maybe fun_ty      -- Includes coercions
+       = add_type_str fun_ty' strs
+    add_type_str fun_ty (str:strs)     -- Add strict-type info
+       | Just (arg_ty, fun_ty') <- splitFunTy_maybe fun_ty
+       = (str || isStrictType arg_ty) : add_type_str fun_ty' strs
+    add_type_str fun_ty strs
+       = strs
+
+{- Note [Unsaturated functions]
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider (test eyeball/inline4)
+       x = a:as
+       y = f x
+where f has arity 2.  Then we do not want to inline 'x', because
+it'll just be floated out again.  Even if f has lots of discounts
+on its first argument -- it must be saturated for these to kick in
+-}
 
 interestingArgContext :: Id -> SimplCont -> Bool
 -- If the argument has form (f x y), where x,y are boring,
@@ -394,33 +443,15 @@ interestingArgContext :: Id -> SimplCont -> Bool
 interestingArgContext fn call_cont
   = idHasRules fn || go call_cont
   where
-    go (Select {})           = False
-    go (ApplyTo {})          = False
-    go (StrictArg {})        = True
-    go (StrictBind {})       = False   -- ??
-    go (CoerceIt _ c)        = go c
-    go (Stop _ _ interesting) = interesting
-
--------------------
-canUpdateInPlace :: Type -> Bool
--- Consider   let x = <wurble> in ...
--- If <wurble> returns an explicit constructor, we might be able
--- to do update in place.  So we treat even a thunk RHS context
--- as interesting if update in place is possible.  We approximate
--- this by seeing if the type has a single constructor with a
--- small arity.  But arity zero isn't good -- we share the single copy
--- for that case, so no point in sharing.
-
-canUpdateInPlace ty 
-  | not opt_UF_UpdateInPlace = False
-  | otherwise
-  = case splitTyConApp_maybe ty of 
-       Nothing         -> False 
-       Just (tycon, _) -> case tyConDataCons_maybe tycon of
-                               Just [dc]  -> arity == 1 || arity == 2
-                                          where
-                                             arity = dataConRepArity dc
-                               other -> False
+    go (Select {})          = False
+    go (ApplyTo {})         = False
+    go (StrictArg _ cci _ _) = interesting cci
+    go (StrictBind {})      = False    -- ??
+    go (CoerceIt _ c)       = go c
+    go (Stop cci)            = interesting cci
+
+    interesting (ArgCtxt rules _) = rules
+    interesting other            = False
 \end{code}
 
 
@@ -440,7 +471,7 @@ settings:
                        (d) Simplifying a GHCi expression or Template 
                                Haskell splice
 
-       SimplPhase n    Used at all other times
+       SimplPhase n _   Used at all other times
 
 The key thing about SimplGently is that it does no call-site inlining.
 Before full laziness we must be careful not to inline wrappers,
@@ -589,8 +620,8 @@ preInlineUnconditionally env top_lvl bndr rhs
   where
     phase = getMode env
     active = case phase of
-                  SimplGently  -> isAlwaysActive prag
-                  SimplPhase n -> isActive n prag
+                  SimplGently    -> isAlwaysActive prag
+                  SimplPhase n _ -> isActive n prag
     prag = idInlinePragma bndr
 
     try_once in_lam int_cxt    -- There's one textual occurrence
@@ -624,8 +655,8 @@ preInlineUnconditionally env top_lvl bndr rhs
     canInlineInLam _                   = False
 
     early_phase = case phase of
-                       SimplPhase 0 -> False
-                       other        -> True
+                       SimplPhase 0 _ -> False
+                       other          -> True
 -- If we don't have this early_phase test, consider
 --     x = length [1,2,3]
 -- The full laziness pass carefully floats all the cons cells to
@@ -681,7 +712,7 @@ postInlineUnconditionally
     -> Bool
 postInlineUnconditionally env top_lvl bndr occ_info rhs unfolding
   | not active            = False
-  | isLoopBreaker occ_info = False     -- If it's a loop-breaker of any kind, dont' inline
+  | isLoopBreaker occ_info = False     -- If it's a loop-breaker of any kind, don't inline
                                        -- because it might be referred to "earlier"
   | isExportedId bndr      = False
   | exprIsTrivial rhs     = True
@@ -745,8 +776,8 @@ postInlineUnconditionally env top_lvl bndr occ_info rhs unfolding
 
   where
     active = case getMode env of
-                  SimplGently  -> isAlwaysActive prag
-                  SimplPhase n -> isActive n prag
+                  SimplGently    -> isAlwaysActive prag
+                  SimplPhase n _ -> isActive n prag
     prag = idInlinePragma bndr
 
 activeInline :: SimplEnv -> OutId -> Bool
@@ -754,7 +785,7 @@ activeInline env id
   = case getMode env of
       SimplGently -> False
        -- No inlining at all when doing gentle stuff,
-       -- except for local things that occur once
+       -- except for local things that occur once (pre/postInlineUnconditionally)
        -- The reason is that too little clean-up happens if you 
        -- don't inline use-once things.   Also a bit of inlining is *good* for
        -- full laziness; it can expose constant sub-expressions.
@@ -768,7 +799,7 @@ activeInline env id
        -- and they are now constructed as Compulsory unfoldings (in MkId)
        -- so they'll happen anyway.
 
-      SimplPhase n -> isActive n prag
+      SimplPhase n _ -> isActive n prag
   where
     prag = idInlinePragma id
 
@@ -779,13 +810,13 @@ activeRule dflags env
   = Nothing    -- Rewriting is off
   | otherwise
   = case getMode env of
-       SimplGently  -> Just isAlwaysActive
+       SimplGently    -> Just isAlwaysActive
                        -- Used to be Nothing (no rules in gentle mode)
                        -- Main motivation for changing is that I wanted
                        --      lift String ===> ...
                        -- to work in Template Haskell when simplifying
                        -- splices, so we get simpler code for literal strings
-       SimplPhase n -> Just (isActive n)
+       SimplPhase n _ -> Just (isActive n)
 \end{code}
 
 
@@ -829,7 +860,7 @@ mkLam bndrs body
           ; return (mkLams bndrs body') }
    
       | otherwise 
-      = returnSmpl (mkLams bndrs body)
+      = return (mkLams bndrs body)
 \end{code}
 
 Note [Casts and lambdas]
@@ -875,8 +906,8 @@ because the latter is not well-kinded.
                        -- if this is indeed a right-hand side; otherwise
                        -- we end up floating the thing out, only for float-in
                        -- to float it right back in again!
- = tryRhsTyLam env bndrs body          `thenSmpl` \ (floats, body') ->
-   returnSmpl (floats, mkLams bndrs body')
+ = do (floats, body') <- tryRhsTyLam env bndrs body
+      return (floats, mkLams bndrs body')
 -}
 
 
@@ -920,10 +951,10 @@ There are some particularly delicate points here:
   However for GlobalIds we can look at the arity; and for primops we
   must, since they have no unfolding.  
 
-* Regardless of whether 'f' is a vlaue, we always want to 
+* Regardless of whether 'f' is a value, we always want to 
   reduce (/\a -> f a) to f
   This came up in a RULE: foldr (build (/\a -> g a))
-  did not match           foldr (build (/\b -> ...something complex...))
+  did not match          foldr (build (/\b -> ...something complex...))
   The type checker can insert these eta-expanded versions,
   with both type and dictionary lambdas; hence the slightly 
   ad-hoc isDictId
@@ -998,9 +1029,9 @@ actually computing the expansion.
 \begin{code}
 tryEtaExpansion :: DynFlags -> OutExpr -> SimplM OutExpr
 -- There is at least one runtime binder in the binders
-tryEtaExpansion dflags body
-  = getUniquesSmpl                     `thenSmpl` \ us ->
-    returnSmpl (etaExpand fun_arity us body (exprType body))
+tryEtaExpansion dflags body = do
+    us <- getUniquesM
+    return (etaExpand fun_arity us body (exprType body))
   where
     fun_arity = exprEtaExpandArity dflags body
 \end{code}
@@ -1019,7 +1050,7 @@ Consider this:
 We'd like to float this to 
        y1 = /\a. e1
        y2 = /\a. e2
-       x = /\a. C (y1 a) (y2 a)
+       x  = /\a. C (y1 a) (y2 a)
 for the usual reasons: we want to inline x rather vigorously.
 
 You may think that this kind of thing is rare.  But in some programs it is
@@ -1092,7 +1123,7 @@ it is guarded by the doFloatFromRhs call in simplLazyBind.
 abstractFloats :: [OutTyVar] -> SimplEnv -> OutExpr -> SimplM ([OutBind], OutExpr)
 abstractFloats main_tvs body_env body
   = ASSERT( notNull body_floats )
-    do { (subst, float_binds) <- mapAccumLSmpl abstract empty_subst body_floats
+    do { (subst, float_binds) <- mapAccumLM abstract empty_subst body_floats
        ; return (float_binds, CoreSubst.substExpr subst body) }
   where
     main_tv_set = mkVarSet main_tvs
@@ -1128,7 +1159,7 @@ abstractFloats main_tvs body_env body
                -- gives rise to problems.   SLPJ June 98
 
     abstract subst (Rec prs)
-       = do { (poly_ids, poly_apps) <- mapAndUnzipSmpl (mk_poly tvs_here) ids
+       = do { (poly_ids, poly_apps) <- mapAndUnzipM (mk_poly tvs_here) ids
            ; let subst' = CoreSubst.extendSubstList subst (ids `zip` poly_apps)
                  poly_rhss = [mkLams tvs_here (CoreSubst.substExpr subst' rhs) | rhs <- rhss]
            ; return (subst', Rec (poly_ids `zip` poly_rhss)) }
@@ -1150,10 +1181,11 @@ abstractFloats main_tvs body_env body
         tvs_here = main_tvs
 
     mk_poly tvs_here var
-      = do { uniq <- getUniqueSmpl
+      = do { uniq <- getUniqueM
           ; let  poly_name = setNameUnique (idName var) uniq           -- Keep same name
                  poly_ty   = mkForAllTys tvs_here (idType var) -- But new type of course
-                 poly_id   = mkLocalId poly_name poly_ty 
+                 poly_id   = transferPolyIdInfo var $  -- Note [transferPolyIdInfo] in Id.lhs
+                             mkLocalId poly_name poly_ty 
           ; return (poly_id, mkTyApps (Var poly_id) (mkTyVarTys tvs_here)) }
                -- In the olden days, it was crucial to copy the occInfo of the original var, 
                -- because we were looking at occurrence-analysed but as yet unsimplified code!
@@ -1394,7 +1426,7 @@ prepareDefault dflags env case_bndr (Just (tycon, inst_tys)) imposs_cons (Just d
 
        [con] ->        -- It matches exactly one constructor, so fill it in
                 do { tick (FillInCaseDefault case_bndr)
-                    ; us <- getUniquesSmpl
+                    ; us <- getUniquesM
                     ; let (ex_tvs, co_tvs, arg_ids) =
                               dataConRepInstPat us con inst_tys
                     ; return [(DataAlt con, ex_tvs ++ co_tvs ++ arg_ids, deflt_rhs)] }
@@ -1427,32 +1459,17 @@ mkCase tries these things
 
 
 \begin{code}
-mkCase :: OutExpr -> OutId -> OutType
-       -> [OutAlt]             -- Increasing order
+mkCase :: OutExpr -> OutId -> [OutAlt] -- Increasing order
        -> SimplM OutExpr
 
 --------------------------------------------------
---     1. Check for empty alternatives
---------------------------------------------------
-
--- This isn't strictly an error.  It's possible that the simplifer might "see"
--- that an inner case has no accessible alternatives before it "sees" that the
--- entire branch of an outer case is inaccessible.  So we simply
--- put an error case here insteadd
-mkCase scrut case_bndr ty []
-  = pprTrace "mkCase: null alts" (ppr case_bndr <+> ppr scrut) $
-    return (mkApps (Var rUNTIME_ERROR_ID)
-                  [Type ty, Lit (mkStringLit "Impossible alternative")])
-
-
---------------------------------------------------
 --     2. Identity case
 --------------------------------------------------
 
-mkCase scrut case_bndr ty alts -- Identity case
+mkCase scrut case_bndr alts    -- Identity case
   | all identity_alt alts
-  = tick (CaseIdentity case_bndr)              `thenSmpl_`
-    returnSmpl (re_cast scrut)
+  = do tick (CaseIdentity case_bndr)
+       return (re_cast scrut)
   where
     identity_alt (con, args, rhs) = check_eq con args (de_cast rhs)
 
@@ -1485,7 +1502,7 @@ mkCase scrut case_bndr ty alts    -- Identity case
 --------------------------------------------------
 --     Catch-all
 --------------------------------------------------
-mkCase scrut bndr ty alts = returnSmpl (Case scrut bndr ty alts)
+mkCase scrut bndr alts = return (Case scrut bndr (coreAltsType alts) alts)
 \end{code}