[GHC] #15307: Incorrect -ddump-deriv parenthesization for GND'd fmap implementation

GHC ghc-devs at haskell.org
Sun Jun 24 11:39:01 UTC 2018


#15307: Incorrect -ddump-deriv parenthesization for GND'd fmap implementation
-------------------------------------+-------------------------------------
           Reporter:  RyanGlScott    |             Owner:  (none)
               Type:  bug            |            Status:  new
           Priority:  normal         |         Milestone:  8.6.1
          Component:  Compiler       |           Version:  8.4.3
           Keywords:                 |  Operating System:  Unknown/Multiple
       Architecture:                 |   Type of failure:  None/Unknown
  Unknown/Multiple                   |
          Test Case:                 |        Blocked By:
           Blocking:                 |   Related Tickets:
Differential Rev(s):                 |         Wiki Page:
-------------------------------------+-------------------------------------
 This program:

 {{{#!hs
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# OPTIONS_GHC -ddump-deriv #-}
 module Bug where

 newtype Foo a = MkFoo (Maybe a) deriving Functor
 }}}

 When compiling, displays incorrect code in its `-ddump-deriv` output:

 {{{
 $ ghci Bug.hs
 GHCi, version 8.4.3: http://www.haskell.org/ghc/  :? for help
 Loaded GHCi configuration from /home/ryanglscott/.ghci
 [1 of 1] Compiling Bug              ( Bug.hs, interpreted )

 ==================== Derived instances ====================
 Derived class instances:
   instance GHC.Base.Functor Bug.Foo where
     GHC.Base.fmap
       = GHC.Prim.coerce
           @(forall (a_a1y2 :: TYPE GHC.Types.LiftedRep)
                    (b_a1y3 :: TYPE GHC.Types.LiftedRep).
             a_a1y2 -> b_a1y3 -> GHC.Base.Maybe a_a1y2 -> GHC.Base.Maybe
 b_a1y3)
           @(forall (a_a1y2 :: TYPE GHC.Types.LiftedRep)
                    (b_a1y3 :: TYPE GHC.Types.LiftedRep).
             a_a1y2 -> b_a1y3 -> Bug.Foo a_a1y2 -> Bug.Foo b_a1y3)
           GHC.Base.fmap
     (GHC.Base.<$)
       = GHC.Prim.coerce
           @(forall (a_a1y9 :: TYPE GHC.Types.LiftedRep)
                    (b_a1ya :: TYPE GHC.Types.LiftedRep).
             a_a1y9 -> GHC.Base.Maybe b_a1ya -> GHC.Base.Maybe a_a1y9)
           @(forall (a_a1y9 :: TYPE GHC.Types.LiftedRep)
                    (b_a1ya :: TYPE GHC.Types.LiftedRep).
             a_a1y9 -> Bug.Foo b_a1ya -> Bug.Foo a_a1y9)
           (GHC.Base.<$)


 Derived type family instances:


 Ok, one module loaded.
 }}}

 Notice how the type of `fmap` is `a_a1y2 -> b_a1y3 -> Bug.Foo a_a1y2 ->
 Bug.Foo b_a1y3`, not `(a_a1y2 -> b_a1y3) -> Bug.Foo a_a1y2 -> Bug.Foo
 b_a1y3`.

 The culprit is the `nlHsFunTy` function, which is used to construct this
 function type in `typeToLHsType`:

 {{{#!hs
 nlHsFunTy :: LHsType (GhcPass p) -> LHsType (GhcPass p) -> LHsType
 (GhcPass p)
 nlHsFunTy a b = noLoc (HsFunTy noExt a b)
 }}}

 This makes no attempt to add `HsParTy`s around any of its arguments. It's
 tempting to parenthesize //both// arguments, but interestingly, if you do
 this, then the type of `fmap` would become:

 {{{#!hs
 (a -> b) -> (Foo a -> Foo b)
 }}}

 This perhaps not what we want, since the parentheses around `Foo a -> Foo
 b` are redundant. Therefore, I propose that we adopt the same
 parenthesization scheme that `ppr_ty` uses for pretty-printing Core
 `Type`s:

 {{{#!hs
 ppr_ty ctxt_prec (IfaceFunTy ty1 ty2)
   = -- We don't want to lose synonyms, so we mustn't use splitFunTys here.
     maybeParen ctxt_prec funPrec $
     sep [ppr_ty funPrec ty1, sep (ppr_fun_tail ty2)]
   where
     ppr_fun_tail (IfaceFunTy ty1 ty2)
       = (arrow <+> ppr_ty funPrec ty1) : ppr_fun_tail ty2
     ppr_fun_tail other_ty
       = [arrow <+> pprIfaceType other_ty]
 }}}

 Namely, always parenthesize the argument type under `funPrec`, and
 recursively check the result type to see if it's also a function type,
 parenthesizing its arguments as necessary.

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


More information about the ghc-tickets mailing list