GHC stubbornly produces dead code for empty case with type family
Consider the following instance:
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
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:
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.
Trac metadata
| Trac field | Value |
|---|---|
| Version | 8.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture |