+ (alts_wo_default, maybe_deflt) = findDefault alts
+ imposs_cons = case scrut of
+ Var v -> otherCons (idUnfolding v)
+ other -> []
+
+ -- "imposs_deflt_cons" are handled either by the context,
+ -- OR by a branch in this case expression. (Don't include DEFAULT!!)
+ imposs_deflt_cons = nub (imposs_cons ++ [con | (con,_,_) <- alts_wo_default])
+
+simplDefault :: SimplEnv
+ -> OutId -- Case binder; need just for its type. Note that as an
+ -- OutId, it has maximum information; this is important.
+ -- Test simpl013 is an example
+ -> [AltCon] -- These cons can't happen when matching the default
+ -> SimplCont
+ -> Maybe InExpr
+ -> SimplM [OutAlt] -- One branch or none; we use a list because it's what
+ -- mergeAlts expects
+
+
+simplDefault env case_bndr' imposs_cons cont Nothing
+ = return [] -- No default branch
+
+simplDefault env case_bndr' imposs_cons cont (Just rhs)
+ | -- This branch handles the case where we are
+ -- scrutinisng an algebraic data type
+ Just (tycon, inst_tys) <- splitTyConApp_maybe (idType case_bndr'),
+ isAlgTyCon tycon, -- It's a data type, tuple, or unboxed tuples.
+ not (isNewTyCon tycon), -- We can have a newtype, if we are just doing an eval:
+ -- case x of { DEFAULT -> e }
+ -- and we don't want to fill in a default for them!
+ Just all_cons <- tyConDataCons_maybe tycon,
+ not (null all_cons), -- This is a tricky corner case. If the data type has no constructors,
+ -- which GHC allows, then the case expression will have at most a default
+ -- alternative. We don't want to eliminate that alternative, because the
+ -- invariant is that there's always one alternative. It's more convenient
+ -- to leave
+ -- case x of { DEFAULT -> e }
+ -- as it is, rather than transform it to
+ -- error "case cant match"
+ -- which would be quite legitmate. But it's a really obscure corner, and
+ -- not worth wasting code on.
+
+ let imposs_data_cons = [con | DataAlt con <- imposs_cons] -- We now know it's a data type
+ poss_data_cons = filterOut (`elem` imposs_data_cons) all_cons
+ gadt_imposs | all isTyVarTy inst_tys = []
+ | otherwise = filter (cant_match inst_tys) poss_data_cons
+ final_poss = filterOut (`elem` gadt_imposs) poss_data_cons
+
+ = case final_poss of
+ [] -> returnSmpl [] -- Eliminate the default alternative
+ -- altogether if it can't match
+
+ [con] -> -- It matches exactly one constructor, so fill it in
+ do { tick (FillInCaseDefault case_bndr')
+ ; us <- getUniquesSmpl
+ ; let (ex_tvs, co_tvs, arg_ids) =
+ dataConRepInstPat us con inst_tys
+ ; let con_alt = (DataAlt con, ex_tvs ++ co_tvs ++ arg_ids, rhs)
+ ; Just (_, alt') <- simplAlt env [] case_bndr' cont con_alt
+ -- The simplAlt must succeed with Just because we have
+ -- already filtered out construtors that can't match
+ ; return [alt'] }
+
+ two_or_more -> simplify_default (map DataAlt gadt_imposs ++ imposs_cons)
+
+ | otherwise
+ = simplify_default imposs_cons
+ where
+ cant_match tys data_con = not (dataConCanMatch data_con tys)
+
+ simplify_default imposs_cons
+ = do { let env' = addBinderOtherCon env case_bndr' imposs_cons
+ -- Record the constructors that the case-binder *can't* be.
+ ; rhs' <- simplExprC env' rhs cont
+ ; return [(DEFAULT, [], rhs')] }
+
+simplAlt :: SimplEnv
+ -> [AltCon] -- These constructors can't be present when
+ -- matching this alternative
+ -> OutId -- The case binder
+ -> SimplCont
+ -> InAlt