
#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