[GHC] #15969: Generic1 deriving should use more coercions

GHC ghc-devs at haskell.org
Thu Nov 29 05:30:52 UTC 2018


#15969: Generic1 deriving should use more coercions
-------------------------------------+-------------------------------------
           Reporter:  dfeuer         |             Owner:  (none)
               Type:  bug            |            Status:  new
           Priority:  normal         |         Milestone:  8.8.1
          Component:  Compiler       |           Version:  8.6.2
           Keywords:  Generics       |  Operating System:  Unknown/Multiple
       Architecture:                 |   Type of failure:  Runtime
  Unknown/Multiple                   |  performance bug
          Test Case:                 |        Blocked By:
           Blocking:                 |   Related Tickets:
Differential Rev(s):                 |         Wiki Page:
-------------------------------------+-------------------------------------
 Consider

 {{{#!hs
 newtype Foo a = Foo (Maybe [a]) deriving (Generic1)
 }}}

 This produces some rather unsatisfactory Core:

 {{{
 -- to1 worker
 Travv.$fGeneric1Foo1 :: forall a. Rep1 Foo a -> Maybe [a]
 Travv.$fGeneric1Foo1
   = \ (@ a_a7RL) (ds_d9dZ :: Rep1 Foo a_a7RL) ->
       case ds_d9dZ `cast` <Co:103> of {
         Nothing -> GHC.Maybe.Nothing @ [a_a7RL];
         Just a1_a9fD -> GHC.Maybe.Just @ [a_a7RL] (a1_a9fD `cast` <Co:5>)
 }

 -- from1 worker
 Travv.$fGeneric1Foo2 :: forall a. Foo a -> Maybe (Rec1 [] a)
 Travv.$fGeneric1Foo2
   = \ (@ a_a7R6) (x_a7GJ :: Foo a_a7R6) ->
       case x_a7GJ `cast` <Co:2> of {
         Nothing -> GHC.Maybe.Nothing @ (Rec1 [] a_a7R6);
         Just a1_a9fD ->
           GHC.Maybe.Just @ (Rec1 [] a_a7R6) (a1_a9fD `cast` <Co:6>)
       }
 }}}

 Both of these functions could be implemented as safe coercions, but
 neither of them is! Similarly, if I define

 {{{#!hs
 data Bar a = Bar (Maybe [a]) deriving Generic1
 }}}

 I get a `to1` worker that looks like

 {{{
 Travv.$fGeneric1Bar_$cto1 :: forall a. Rep1 Bar a -> Bar a
 Travv.$fGeneric1Bar_$cto1
   = \ (@ a_a7UA) (ds_d9ho :: Rep1 Bar a_a7UA) ->
       Travv.Bar
         @ a_a7UA
         (case ds_d9ho `cast` <Co:103> of {
            Nothing -> GHC.Maybe.Nothing @ [a_a7UA];
            Just a1_a9iK -> GHC.Maybe.Just @ [a_a7UA] (a1_a9iK `cast`
 <Co:5>)
          })
 }}}

 That `case` expression should really just be a cast.

 I think the basic trick is probably to inspect the role of the type
 argument of each type in a composition, using that to work out whether to
 coerce that step.

-- 
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/15969>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list