[GHC] #12791: Superclass methods could be more aggressively specialised.

GHC ghc-devs at haskell.org
Wed Dec 7 20:21:02 UTC 2016


#12791: Superclass methods could be more aggressively specialised.
-------------------------------------+-------------------------------------
        Reporter:  mpickering        |                Owner:  danharaj
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              Version:  8.0.1
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:  #5835             |  Differential Rev(s):  Phab:D2714
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by danharaj):

 #5835 is indeed related and my patch resolves it too.

 However, my patch causes a regression in #10359.

 The core has bad bits that all look similar to this:

 {{{
 main6
 main6 =
   \ ds ->
     case ds of _ { Box ds1 ds2 ->
     case ds1 main7 main_number ds2 of dt { D# ipv ->
     Box
       (\ @ dum $d(%,%) -> ds1 ($p1(%,%) $d(%,%), $p2(%,%) $d(%,%))) dt
     }
     }
 }}}

 The issue is caused by the fact that the `Box` constructor has a local
 tuple constraint:

 {{{#!hs
 type Numerical a = (Fractional a, Real a)

 data Box a = Box
     { func :: forall dum. (Numerical dum) => dum -> a -> a
     , obj :: !a }
 }}}

 When code that unpacks `Box` and uses its local constraint to do some
 stuff, the solver needs to produce the tuple constraint. A tuple
 constraint is implemented as a class with its components as superclasses.
 The solution with my current patch goes like:

 {{{
 runStage interact with inerts {
   workitem   =  [W] $d(%,%) :: (Fractional num[sk],
                                 Real num[sk]) (CDictCan(psc))
 updSolvedSetTcs: [W] $d(%,%) :: (Fractional num[sk], Real num[sk])
 newWantedEvVar/cache hit [G] $dFractional :: Fractional num[sk]
 newWantedEvVar/cache hit [G] $dReal :: Real num[sk]
 addTcEvBind
   a2bg
   [W] $d(%,%)
     = C:(%,%) @[Fractional num[sk], Real num[sk]]
               [$dFractional, $dReal]
 end stage interact with inerts }
 }}}

 The old, unpatched solution goes like:

 {{{
 runStage interact with inerts {
   workitem   =  [W] $d(%,%) :: (Fractional dum[sk],
                                 Real dum[sk]) (CDictCan(psc))
 addTcEvBind
   a1Tk
   [W] $d(%,%) = $d(%,%)
 end stage interact with inerts }
 }}}

 The old solution just uses the tuple constraint we are given. The new
 solution is trying to be too smart: It tries to solve from the top-level
 instance and it can do so because the solver has decomposed the given
 tuple constraint into given constraints of its components. So we end up
 constructing a dictionary that is essentially the same as a given one.
 Bad!

 It's not clear to me how to exclude corner cases like this. It is
 potentially possible that we *do* want to try to solve a tuple constraint
 from instances because we might be able to find a more concrete solution
 to one of its components. Is it possible to notice this inefficiency in a
 core2core pass and resolve it then instead?

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


More information about the ghc-tickets mailing list