[GHC] #13468: GHC stubbornly produces dead code for empty case with type family
GHC
ghc-devs at haskell.org
Thu Mar 23 05:29:06 UTC 2017
#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
More information about the ghc-tickets
mailing list