summaryrefslogtreecommitdiff
path: root/compiler/GHC/HsToCore/Arrows.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/GHC/HsToCore/Arrows.hs')
-rw-r--r--compiler/GHC/HsToCore/Arrows.hs42
1 files changed, 29 insertions, 13 deletions
diff --git a/compiler/GHC/HsToCore/Arrows.hs b/compiler/GHC/HsToCore/Arrows.hs
index 3d93e0b7a5..b9a2648dbf 100644
--- a/compiler/GHC/HsToCore/Arrows.hs
+++ b/compiler/GHC/HsToCore/Arrows.hs
@@ -1,5 +1,5 @@
-
{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TupleSections #-}
{-# OPTIONS_GHC -Wno-incomplete-record-updates #-}
@@ -50,7 +50,9 @@ import GHC.Utils.Panic
import GHC.Types.Var.Set
import GHC.Types.SrcLoc
import GHC.Data.List.SetOps( assocMaybe )
+import Data.Foldable (toList)
import Data.List (mapAccumL)
+import Data.List.NonEmpty (NonEmpty(..), nonEmpty)
import GHC.Utils.Misc
import GHC.Types.Unique.DSet
@@ -466,6 +468,8 @@ dsCmd ids local_vars stack_ty res_ty (HsCmdIf _ mb_fun cond then_cmd else_cmd)
fvs_cond `unionDVarSet` fvs_then `unionDVarSet` fvs_else)
{-
+Note [Desugaring HsCmdCase]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
Case commands are treated in much the same way as if commands
(see above) except that there are more alternatives. For example
@@ -516,6 +520,7 @@ dsCmd ids local_vars stack_ty res_ty
either_con <- dsLookupTyCon eitherTyConName
left_con <- dsLookupDataCon leftDataConName
right_con <- dsLookupDataCon rightDataConName
+ void_ty <- mkTyConTy <$> dsLookupTyCon voidTyConName
let
left_id = mkConLikeTc (RealDataCon left_con)
right_id = mkConLikeTc (RealDataCon right_con)
@@ -536,12 +541,22 @@ dsCmd ids local_vars stack_ty res_ty
map (right_expr in_ty1 in_ty2) builds2,
mkTyConApp either_con [in_ty1, in_ty2],
do_choice ids in_ty1 in_ty2 res_ty core_exp1 core_exp2)
- (leaves', sum_ty, core_choices) = foldb merge_branches branches
-
- -- Replace the commands in the case with these tagged tuples,
- -- yielding a HsExpr Id we can feed to dsExpr.
-
- (_, matches') = mapAccumL (replaceLeavesMatch res_ty) leaves' matches
+ (leaves', sum_ty, core_choices) <- case nonEmpty branches of
+ Just bs -> return $ foldb merge_branches bs
+ -- when the case command has no alternatives, the sum type from
+ -- Note [Desugaring HsCmdCase] becomes the empty sum type,
+ -- i.e. Void. The choices then effectively become `arr absurd`,
+ -- implemented as `arr \case {}`.
+ Nothing -> ([], void_ty,) . do_arr ids void_ty res_ty <$>
+ dsExpr (HsLamCase EpAnnNotUsed
+ (MG { mg_alts = noLocA []
+ , mg_ext = MatchGroupTc [Scaled Many void_ty] res_ty
+ , mg_origin = Generated }))
+
+
+ -- Replace the commands in the case with these tagged tuples,
+ -- yielding a HsExpr Id we can feed to dsExpr.
+ let (_, matches') = mapAccumL (replaceLeavesMatch res_ty) leaves' matches
in_ty = envStackType env_ids stack_ty
core_body <- dsExpr (HsCase noExtField exp
@@ -1151,11 +1166,12 @@ replaceLeavesGRHS [] _ = panic "replaceLeavesGRHS []"
-- Balanced fold of a non-empty list.
-foldb :: (a -> a -> a) -> [a] -> a
-foldb _ [] = error "foldb of empty list"
-foldb _ [x] = x
+foldb :: (a -> a -> a) -> NonEmpty a -> a
+foldb _ (x:|[]) = x
foldb f xs = foldb f (fold_pairs xs)
where
- fold_pairs [] = []
- fold_pairs [x] = [x]
- fold_pairs (x1:x2:xs) = f x1 x2:fold_pairs xs
+ fold_pairs (x1:|x2:xs) = f x1 x2 :| keep_empty fold_pairs xs
+ fold_pairs xs = xs
+
+ keep_empty :: (NonEmpty a -> NonEmpty a) -> [a] -> [a]
+ keep_empty f = maybe [] (toList . f) . nonEmpty