[GHC] #15696: Derived Ord instance for enumerations with more than 8 elements seems to be incorrect

GHC ghc-devs at haskell.org
Wed Oct 3 10:41:08 UTC 2018


#15696: Derived Ord instance for enumerations with more than 8 elements seems to be
incorrect
-------------------------------------+-------------------------------------
        Reporter:  mrkkrp            |                Owner:  (none)
            Type:  bug               |               Status:  patch
        Priority:  highest           |            Milestone:  8.6.2
       Component:  Compiler          |              Version:  8.6.1
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
 Type of failure:  Incorrect result  |  Unknown/Multiple
  at runtime                         |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):  Phab:D5196
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by simonpj):

 > Are you maybe confused because in the STG dump you also see the STG for
 cmpT? It's actually inlined in main so the top-level for cmpT is not used.

 That is exactly what I was doing.  Thanks!

 I backed up some more to look at comment:6, which does not have a top-
 level no-inline CAF. I see this:
 {{{
 $sgo_r5Tk :: Main.T -> Main.T -> Main.Set Main.T -> Main.Set Main.T
 [GblId, Arity=3, Str=<L,1*U><L,U><S,1*U>, Unf=OtherCon []] =
     sat-only [] \r [orig_s5Wj ds_s5Wk ds1_s5Wl]
         case ds1_s5Wl of wild_s5Wm [Occ=Once] {
           Main.Bin y_s5Wn l_s5Wo [Occ=Once] r_s5Wp [Occ=Once] ->
               case
                   case ds_s5Wk of sat_s5Wq [Occ=Once] {
                     __DEFAULT -> dataToTag# [sat_s5Wq];
                   }
               of
               a'_s5Wr
               { __DEFAULT ->
                     case dataToTag# [y_s5Wn] of b'_s5Ws {
                       __DEFAULT ->
                           case <# [a'_s5Wr b'_s5Ws] of {
                             __DEFAULT ->
 ...
 }}}
 Here we take apart a `Bin`, and call `dataToTag#` on the contents; and
 because of the `exprIsHNF` stuff there is
 no guarantee that the argument to `Bin` points directly to the data value.

 But in looking at this I found something else!  In coment:6 there is no
 top-level CAF with a NOINLINE, so
 how do things go wrong.  Here's how.

 * We start with
 {{{
 thk = f ()
 g x = ...(case thk of v -> Bin v Tip Tip)...
 }}}
   So far so good; the argument to `Bin` (which is strict) is evaluated.

 * Now we do float-out. And in doing so we do a reverse binder-swap (see
 `Note [Binder-swap during float-out]` in `SetLevels`) thus
 {{{
 g x = ...(case thk of v -> Bin thk Nil Nil)...
 }}}
   The goal of the reverse binder-swap is to allow more floating -- and it
 does!  We float the `Bin` to top level:
 {{{
 lvl = Bin thk Tip Tip
 g x = ...(case thk of v -> lvl))...
 }}}
 * Now you can see that the argument of `Bin`, namely `thk`, points to the
 thunk, not to the value as it did before; and that gives rise to the bug.

 Is this wrong?  Not really.  We are still guaranteed that the argument to
 `Bin` in `lvl` will be evaluated (by that `case thk`) before `lvl` is
 used.  But we are no longer guaranteed that the argument to `Bin` points
 directly to the evaluated value.

 So now I understand.

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


More information about the ghc-tickets mailing list