
#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=, 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