
#13468: GHC stubbornly produces dead code for empty case with type family -------------------------------------+------------------------------------- Reporter: dfeuer | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: 8.4.1 Component: Compiler | Version: 8.1 Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: Other Unknown/Multiple | Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- Consider the following instance: {{{#!hs data Void instance Generic Void where type Rep Void = V1 from x = case x of to x = case x of }}} The pattern checker, when enabled, correctly determines that both `from` and `to` cover all cases. Yay! In order to do this, it has to reduce the `Rep Void` type family application. The optimizer, on the other hand, does not perform this reduction, presumably because it is not known to terminate. Unfortunate in this case, but fine, I suppose. Here's where it gets really unfortunate. If I write {{{#!hs to (x :: V1 r) = case x of }}} then the type checker already has to do the work of unifying `Rep Void` with `V1 r`, but the optimizer doesn't take advantage of it! With `-O2 -ddump-simpl ...`, I get {{{ -- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0} lvl_r2IT :: Addr# lvl_r2IT = "Phantom.hs:18:20-23|case"# -- RHS size: {terms: 2, types: 2, coercions: 0, joins: 0/0} $fGenericVoid1 :: Void $fGenericVoid1 = patError lvl_r2IT -- RHS size: {terms: 6, types: 7, coercions: 0, joins: 0/0} $fGenericVoid_$cto :: forall x. Rep Void x -> Void $fGenericVoid_$cto = \ (@ x_a2HT) (ds_d2J8 :: Rep Void x_a2HT) -> case ds_d2J8 of { __DEFAULT -> $fGenericVoid1 } }}} That seems rather unfortunate. The only workaround I've found so far is to actually write a function just to constrain the type: {{{#!hs absV :: V1 r -> a absV x = case x of instance Generic Void where ... to = absV }}} Finally, this is clean: {{{ -- RHS size: {terms: 5, types: 12, coercions: 0, joins: 0/0} absV :: forall r a. V1 r -> a absV = \ (@ r_a2Hy) (@ a_a2Hz) (x_a1fi :: V1 r_a2Hy) -> case x_a1fi of { } -- RHS size: {terms: 4, types: 7, coercions: 0, joins: 0/0} lvl_r2IF :: forall x. V1 x -> Void lvl_r2IF = \ (@ x_a2HP) (eta_B1 :: V1 x_a2HP) -> absV eta_B1 }}} I suppose I could add `GHC.Generics.Absurd` just to write the `absV` function for `Generic` and `Generic1` deriving, but that seems more than a little silly. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13468 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler