[GHC] #10845: Incorrect behavior when let binding implicit CallStack object

GHC ghc-devs at haskell.org
Tue Nov 3 13:30:30 UTC 2015


#10845: Incorrect behavior when let binding implicit CallStack object
-------------------------------------+-------------------------------------
        Reporter:  nitromaster101    |                Owner:  gridaphobe
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              Version:  7.11
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:  #10846            |  Differential Rev(s):  Phab:D1422
       Wiki Page:                    |
-------------------------------------+-------------------------------------
Changes (by simonpj):

 * differential:   => Phab:D1422


Comment:

 On [Phab:D1422] you say:
 Sadly, it turns out we can't remove the no-given solver entirely. Consider
 {{{
 main = do putStrLn $ showCallStack ?loc
           putStrLn $ showCallStack ?loc
 }}}
 GHC treats the constraints arising from the two occurrences of ?loc as
 interchangeable (after all, they have the same type), and solves one from
 the other, giving us the incorrect output
 {{{
 % ./T10845
 CallStack:
   ?loc, called at T10845.hs:33:36 in main:Main
 CallStack:
   ?loc, called at T10845.hs:33:36 in main:Main
 }}}
 (note that both CallStacks refer to the same location).

 Good point!  But there is a better way to solve this particular issue:

  * In `Inst.instCallConstraints`, add a special case for `CallStack`
    constraints, where you push on the call site (i.e. do what the
    solver currently does, in `isCallStackIP`

  * Now any Wanted call-stack constraints encountered by the solver
    can be solved by equality from each other, or directly from a given.
    In fact this makes call-stack constraints behave even more like
    implicit-parameter constraints.

  * Defaulting solves a `CallStack` constraint with `EmptyStack`

 This is much simpler and more direct.

 There is a wrinkle: what if the function being called had a type
 like `f :: c => T c -> Int`, and `c` was subsequently inferred to
 be `IP "foo" CallStack`?  So the fact that it's a call-stack constraint
 isn't immediately obvious.

 It's a pretty obscure problem but could be solved by NOT solving in
 `instCallConstraints`, but intead

  * Have two kind of call-stack constraints, with origin
    `OccurrenceOf`, and `IPOccOrigin` (this is actually true already;
    see `IPCallStackIP`.

  * The only way to solve an `OccurrenceOf` call-stack constraint is by
    pushing on the call item, and producing a new wanted `IPOccOrigin`
    call-stack constraint

  * Solve wanted `IPOccOrigin` call-stack constraints as above, from each
 other,
    from givens, or by defaulting.

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


More information about the ghc-tickets mailing list