@@ -279,7 +279,8 @@ simpleCase tc defcase reflect phase fc inacc argtys cs erInfo
279 (tree, st) = runCaseBuilder erInfo
279 (tree, st) = runCaseBuilder erInfo
280 (match ns' ps' defcase)
280 (match ns' ps' defcase)
281 ([], numargs, [])
281 ([], numargs, [])
282− t = CaseDef ns (prune proj (depatt ns' tree)) (fstT st) in
282+ sc = removeUnreachable (prune proj (depatt ns' tree))
283+ t = CaseDef ns sc (fstT st) in
283 if proj then return (stripLambdas t)
284 if proj then return (stripLambdas t)
284 else return t
285 else return t
285 Error err -> Error (At fc err)
286 Error err -> Error (At fc err)
@@ -765,6 +766,56 @@ prune proj (Case up n alts) = case alts' of
766prune _ t = t
767prune _ t = t
769+-- Remove any branches we can't reach because of variables we've already
771+removeUnreachable :: SC -> SC
772+removeUnreachable sc = ru [] sc
774+ -- keep a mapping from variable names, to the constructor tag we've
775+ -- already checked it as in this branch
776+ ru :: [(Name, Int)] -> SC -> SC
777+ ru checked (Case t n alts)
778+ = let alts' = map (ruAlt checked n) (dropImpossible (lookup n checked) alts) in
782+ dropImpossible Nothing alts = alts
783+ dropImpossible (Just t) [] = []
784+ dropImpossible (Just t) (ConCase con tag args sc : rest)
785+ | t == tag = [ConCase con tag args sc] -- must be this case
786+ | otherwise = dropImpossible (Just t) rest -- can't be this case
787+ dropImpossible (Just t) (c : rest)
788+ = c : dropImpossible (Just t) rest
790+ ruAlt :: [(Name, Int)] -> Name -> CaseAlt -> CaseAlt
791+ ruAlt checked var (ConCase con tag args sc)
792+ = let checked' = dropChecked args (updateChecked var tag checked)
793+ sc' = ru checked' sc in
794+ ConCase con tag args sc'
795+ ruAlt checked var (FnCase n args sc)
796+ = let checked' = dropChecked [var] checked
797+ sc' = ru checked' sc in
799+ ruAlt checked var (ConstCase c sc)
800+ = let checked' = dropChecked [var] checked
801+ sc' = ru checked' sc in
803+ ruAlt checked var (SucCase n sc)
804+ = let checked' = dropChecked [var] checked
805+ sc' = ru checked' sc in
807+ ruAlt checked var (DefaultCase sc)
808+ = let checked' = dropChecked [var] checked
809+ sc' = ru checked' sc in
812+ updateChecked :: Name -> Int -> [(Name, Int)] -> [(Name, Int)]
813+ updateChecked n i checked
814+ = (n, i) : filter (\x -> fst x /= n) checked
816+ dropChecked :: [Name] -> [(Name, Int)] -> [(Name, Int)]
817+ dropChecked ns checked = filter (\x -> fst x `notElem` ns) checked
768stripLambdas :: CaseDef -> CaseDef
819stripLambdas :: CaseDef -> CaseDef
769stripLambdas (CaseDef ns (STerm (Bind x (Lam _ _) sc)) tm)
820stripLambdas (CaseDef ns (STerm (Bind x (Lam _ _) sc)) tm)
770 = stripLambdas (CaseDef (ns ++ [x]) (STerm (instantiate (P Bound x Erased) sc)) tm)
821 = stripLambdas (CaseDef (ns ++ [x]) (STerm (instantiate (P Bound x Erased) sc)) tm)