[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