diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/deSugar/DsExpr.lhs | 13 | ||||
-rw-r--r-- | compiler/deSugar/DsUtils.lhs | 2 | ||||
-rw-r--r-- | compiler/deSugar/Match.lhs | 55 | ||||
-rw-r--r-- | compiler/deSugar/MatchCon.lhs | 3 | ||||
-rw-r--r-- | compiler/deSugar/MatchLit.lhs | 2 | ||||
-rw-r--r-- | compiler/main/DynFlags.hs | 4 | ||||
-rw-r--r-- | compiler/parser/Parser.y.pp | 2 | ||||
-rw-r--r-- | compiler/rename/RnBinds.lhs | 18 |
8 files changed, 68 insertions, 31 deletions
diff --git a/compiler/deSugar/DsExpr.lhs b/compiler/deSugar/DsExpr.lhs index 6e9a7acbb3..7f439eabe6 100644 --- a/compiler/deSugar/DsExpr.lhs +++ b/compiler/deSugar/DsExpr.lhs @@ -205,11 +205,7 @@ dsExpr (NegApp expr neg_expr) dsExpr (HsLam a_Match) = uncurry mkLams <$> matchWrapper LambdaExpr a_Match -dsExpr (HsLamCase arg matches@(MatchGroup _ rhs_ty)) - | isEmptyMatchGroup matches -- A Core 'case' is always non-empty - = -- So desugar empty HsLamCase to error call - mkErrorAppDs pAT_ERROR_ID (funResultTy rhs_ty) (ptext (sLit "\\case")) - | otherwise +dsExpr (HsLamCase arg matches) = do { arg_var <- newSysLocalDs arg ; ([discrim_var], matching_code) <- matchWrapper CaseAlt matches ; return $ Lam arg_var $ bindNonRec discrim_var (Var arg_var) matching_code } @@ -305,12 +301,7 @@ dsExpr (HsSCC cc expr@(L loc _)) = do dsExpr (HsCoreAnn _ expr) = dsLExpr expr -dsExpr (HsCase discrim matches@(MatchGroup _ rhs_ty)) - | isEmptyMatchGroup matches -- A Core 'case' is always non-empty - = -- So desugar empty HsCase to error call - mkErrorAppDs pAT_ERROR_ID (funResultTy rhs_ty) (ptext (sLit "case")) - - | otherwise +dsExpr (HsCase discrim matches) = do { core_discrim <- dsLExpr discrim ; ([discrim_var], matching_code) <- matchWrapper CaseAlt matches ; return (bindNonRec discrim_var core_discrim matching_code) } diff --git a/compiler/deSugar/DsUtils.lhs b/compiler/deSugar/DsUtils.lhs index 504a76dc86..e05a175950 100644 --- a/compiler/deSugar/DsUtils.lhs +++ b/compiler/deSugar/DsUtils.lhs @@ -307,7 +307,7 @@ mkCoAlgCaseMatchResult dflags var ty match_alts match_results = [match_result | (_,_,match_result) <- match_alts] fail_flag | exhaustive_case - = foldr1 orFail [can_it_fail | MatchResult can_it_fail _ <- match_results] + = foldr orFail CantFail [can_it_fail | MatchResult can_it_fail _ <- match_results] | otherwise = CanFail diff --git a/compiler/deSugar/Match.lhs b/compiler/deSugar/Match.lhs index 75a3aa5191..2de2bb4d42 100644 --- a/compiler/deSugar/Match.lhs +++ b/compiler/deSugar/Match.lhs @@ -291,9 +291,8 @@ match [] ty eqns eqn_rhs eqn | eqn <- eqns ] -match vars@(v:_) ty eqns - = ASSERT( not (null eqns ) ) - do { dflags <- getDynFlags +match vars@(v:_) ty eqns -- Eqns *can* be empty + = do { dflags <- getDynFlags ; -- Tidy the first pattern, generating -- auxiliary bindings if necessary (aux_binds, tidy_eqns) <- mapAndUnzipM (tidyEqnInfo v) eqns @@ -304,13 +303,18 @@ match vars@(v:_) ty eqns -- print the view patterns that are commoned up to help debug ; whenDOptM Opt_D_dump_view_pattern_commoning (debug grouped) - ; match_results <- mapM match_group grouped - ; return (adjustMatchResult (foldr1 (.) aux_binds) $ + ; match_results <- match_groups grouped + ; return (adjustMatchResult (foldr (.) id aux_binds) $ foldr1 combineMatchResults match_results) } where dropGroup :: [(PatGroup,EquationInfo)] -> [EquationInfo] dropGroup = map snd + match_groups :: [[(PatGroup,EquationInfo)]] -> DsM [MatchResult] + -- Result list of [MatchResult] is always non-empty + match_groups [] = matchEmpty v ty + match_groups gs = mapM match_group gs + match_group :: [(PatGroup,EquationInfo)] -> DsM MatchResult match_group [] = panic "match_group" match_group eqns@((group,_) : _) @@ -339,6 +343,14 @@ match vars@(v:_) ty eqns maybeWarn $ (map (\g -> text "Putting these view expressions into the same case:" <+> (ppr g)) (filter (not . null) gs)) +matchEmpty :: Id -> Type -> DsM [MatchResult] +-- See Note [Empty case expressions] +matchEmpty var res_ty + = return [MatchResult CanFail mk_seq] + where + mk_seq fail = return $ mkWildCase (Var var) (idType var) res_ty + [(DEFAULT, [], fail)] + matchVariables :: [Id] -> Type -> [EquationInfo] -> DsM MatchResult -- Real true variables, just like in matchVar, SLPJ p 94 -- No binding to do: they'll all be wildcards by now (done in tidy) @@ -394,6 +406,24 @@ getViewPat (ViewPat _ pat _) = unLoc pat getViewPat _ = panic "getBangPat" \end{code} +Note [Empty case alternatives] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The list of EquationInfo can be empty, arising from + case x of {} or \case {} +In that situation we desugar to + case x of { _ -> error "pattern match failure" } +The *desugarer* isn't certain whether there really should be no +alternatives, so it adds a default case, as it always does. A later +pass may remove it if it's inaccessible. (See also Note [Empty case +alternatives] in CoreSyn.) + +We do *not* deugar simply to + error "empty case" +or some such, because 'x' might be bound to (error "hello"), in which +case we want to see that "hello" exception, not (error "empty case"). +See also Note [Case elimination: lifted case] in Simplify. + + %************************************************************************ %* * Tidying patterns @@ -693,17 +723,16 @@ one pattern, and match simply only accepts one pattern. JJQC 30-Nov-1997 \begin{code} -matchWrapper ctxt (MatchGroup matches match_ty) - = ASSERT( notNull matches ) - do { eqns_info <- mapM mk_eqn_info matches - ; new_vars <- selectMatchVars arg_pats +matchWrapper ctxt (MG { mg_alts = matches + , mg_arg_tys = arg_tys + , mg_res_ty = rhs_ty }) + = do { eqns_info <- mapM mk_eqn_info matches + ; new_vars <- case matches of + [] -> mapM newSysLocalDs arg_tys + (m:_) -> selectMatchVars (map unLoc (hsLMatchPats m)) ; result_expr <- matchEquations ctxt new_vars eqns_info rhs_ty ; return (new_vars, result_expr) } where - arg_pats = map unLoc (hsLMatchPats (head matches)) - n_pats = length arg_pats - (_, rhs_ty) = splitFunTysN n_pats match_ty - mk_eqn_info (L _ (Match pats _ grhss)) = do { let upats = map unLoc pats ; match_result <- dsGRHSs ctxt upats grhss rhs_ty diff --git a/compiler/deSugar/MatchCon.lhs b/compiler/deSugar/MatchCon.lhs index 10270e50ca..5c4f4273b0 100644 --- a/compiler/deSugar/MatchCon.lhs +++ b/compiler/deSugar/MatchCon.lhs @@ -134,7 +134,8 @@ matchOneCon vars ty (eqn1 : eqns) -- All eqns for a single constructor match_group :: [Id] -> [(ConArgPats, EquationInfo)] -> DsM MatchResult -- All members of the group have compatible ConArgPats match_group arg_vars arg_eqn_prs - = do { (wraps, eqns') <- liftM unzip (mapM shift arg_eqn_prs) + = ASSERT( notNull arg_eqn_prs ) + do { (wraps, eqns') <- liftM unzip (mapM shift arg_eqn_prs) ; let group_arg_vars = select_arg_vars arg_vars arg_eqn_prs ; match_result <- match (group_arg_vars ++ vars) ty eqns' ; return (adjustMatchResult (foldr1 (.) wraps) match_result) } diff --git a/compiler/deSugar/MatchLit.lhs b/compiler/deSugar/MatchLit.lhs index 80f2124d1f..b9b6ec5a4f 100644 --- a/compiler/deSugar/MatchLit.lhs +++ b/compiler/deSugar/MatchLit.lhs @@ -236,7 +236,7 @@ matchLiterals :: [Id] -> DsM MatchResult matchLiterals (var:vars) ty sub_groups - = ASSERT( all notNull sub_groups ) + = ASSERT( notNull sub_groups && all notNull sub_groups ) do { -- Deal with each group ; alts <- mapM match_group sub_groups diff --git a/compiler/main/DynFlags.hs b/compiler/main/DynFlags.hs index 749651fab4..096fc23f21 100644 --- a/compiler/main/DynFlags.hs +++ b/compiler/main/DynFlags.hs @@ -529,6 +529,7 @@ data ExtensionFlag | Opt_LambdaCase | Opt_MultiWayIf | Opt_TypeHoles + | Opt_EmptyCase deriving (Eq, Enum, Show) -- | Contains not only a collection of 'GeneralFlag's but also a plethora of @@ -2608,7 +2609,8 @@ xFlags = [ ( "UndecidableInstances", Opt_UndecidableInstances, nop ), ( "IncoherentInstances", Opt_IncoherentInstances, nop ), ( "PackageImports", Opt_PackageImports, nop ), - ( "TypeHoles", Opt_TypeHoles, nop ) + ( "TypeHoles", Opt_TypeHoles, nop ), + ( "EmptyCase", Opt_EmptyCase, nop ) ] defaultFlags :: Settings -> [GeneralFlag] diff --git a/compiler/parser/Parser.y.pp b/compiler/parser/Parser.y.pp index e3f4994166..b6139621d1 100644 --- a/compiler/parser/Parser.y.pp +++ b/compiler/parser/Parser.y.pp @@ -1712,6 +1712,8 @@ guardquals1 :: { Located [LStmt RdrName (LHsExpr RdrName)] } altslist :: { Located [LMatch RdrName (LHsExpr RdrName)] } : '{' alts '}' { LL (reverse (unLoc $2)) } | vocurly alts close { L (getLoc $2) (reverse (unLoc $2)) } + | '{' '}' { noLoc [] } + | vocurly close { noLoc [] } alts :: { Located [LMatch RdrName (LHsExpr RdrName)] } : alts1 { L1 (unLoc $1) } diff --git a/compiler/rename/RnBinds.lhs b/compiler/rename/RnBinds.lhs index 717b885e63..bed22613af 100644 --- a/compiler/rename/RnBinds.lhs +++ b/compiler/rename/RnBinds.lhs @@ -781,9 +781,11 @@ rnMatchGroup :: Outputable (body RdrName) => HsMatchContext Name -> (Located (body RdrName) -> RnM (Located (body Name), FreeVars)) -> MatchGroup RdrName (Located (body RdrName)) -> RnM (MatchGroup Name (Located (body Name)), FreeVars) -rnMatchGroup ctxt rnBody (MatchGroup ms _) - = do { (new_ms, ms_fvs) <- mapFvRn (rnMatch ctxt rnBody) ms - ; return (MatchGroup new_ms placeHolderType, ms_fvs) } +rnMatchGroup ctxt rnBody (MG { mg_alts = ms }) + = do { empty_case_ok <- xoptM Opt_EmptyCase + ; when (null ms && not empty_case_ok) (addErr (emptyCaseErr ctxt)) + ; (new_ms, ms_fvs) <- mapFvRn (rnMatch ctxt rnBody) ms + ; return (mkMatchGroup new_ms, ms_fvs) } rnMatch :: Outputable (body RdrName) => HsMatchContext Name -> (Located (body RdrName) -> RnM (Located (body Name), FreeVars)) @@ -808,6 +810,16 @@ rnMatch' ctxt rnBody match@(Match pats maybe_rhs_sig grhss) ; return (Match pats' Nothing grhss', grhss_fvs) }} +emptyCaseErr :: HsMatchContext Name -> SDoc +emptyCaseErr ctxt = hang (ptext (sLit "Empty list of alterantives in") <+> pp_ctxt) + 2 (ptext (sLit "Use -XEmptyCase to allow this")) + where + pp_ctxt = case ctxt of + CaseAlt -> ptext (sLit "case expression") + LambdaExpr -> ptext (sLit "\\case expression") + _ -> ptext (sLit "(unexpected)") <+> pprMatchContextNoun ctxt + + resSigErr :: Outputable body => HsMatchContext Name -> Match RdrName body -> HsType RdrName -> SDoc resSigErr ctxt match ty = vcat [ ptext (sLit "Illegal result type signature") <+> quotes (ppr ty) |