I think that I've found a bug in GHC that relates to
the -O flag,
strictness qualifiers in datatype declarations, and
derived instances
of Eq.
BACKGROUND
I have a datatype PropRec defined like so:
data PropRec = PropRec { b :: !Bool
, em :: !Bool
, i :: !Bool
, s :: !Bool
, tt :: !Bool
, u :: !Int
, size :: !Int
, color :: !Color -- !
doesn't mix with -O
}
deriving (Eq,Show)
In my program I test two PropRecs for equality via
(==), and they
sometimes test as False (that is, unequal) when they
are in fact
equal. Just to make sure that I'm not crazy, I also
tested the
respective members of the two PropRecs (b, em, ...) ,
and they all
match. As a double-double-check, showing the
indivdual PropRecs
yields identical strings.
I have not been successful at reducing the problematic
code into a
smaller example of the abberent behavior. So far, all
that I have
been able to determine is that the problem goes away
when I remove the
strictness flag for color in the PropRec declaration
or when I turn
off all compiler optimizations (both -O and -O2 result
in abberent
behavior).
RECIPE FOR REPRODUCING THE ABBERENT BEHAVIOR
The only example code in which I can reliably
reproduce the problem is
my ICFP programming contest entry (discovered after
submission,
unfortunately). I have enclosed the code here, and if
you want
to reproduce the problem, here is the recipe:
tar zxvf functional-beer-submission.tar.gz
cd functional-beer-submission/source
make clean && make NaiveOptimization_qc.o ghci
./quickcheck NaiveOptimization_qc.hs # may take a
few runs to get exception
What you're looking for is something like this (which
I've reformated
for easy online reading):
*** Exception: diffPRE empty!
r == mr = False
prop-by-prop (==) =
[True,True,True,True,True,True,True,True]
(r,mr) =
(PropRec
{b=False,em=False,i=False,s=False,tt=False,u=0,size=(-
1),color=White}
,PropRec
{b=False,em=False,i=False,s=False,tt=False,u=0,size=(-
1),color=White})
This error is raised in NaiveOptimization.hs. Search
for "should
NEVER be True" to find the exact location.
If you edit the Makefile and remove -O2 from GHC_XOPTS
the problem
will go away. (You must re-run the final two lines of
the above recipe
to rebuild and re-test.)
If you remove the stricness flag for color in the
PropRec declaration
in Meaning.hs, the problem goes away (even with -O2
on). (Again,
re-run the final two lines of the recipe.)
I'm willing to help hunt down the root of the problem,
but I don't
know where to look next. I've tried making a smaller
example using
the same key concepts as in my original source, but
the problem doesn't
occur. I must be missing something.
If somebody who is familiar with what -O does under
the hood and how
it affects datatypes declared with the strictness
flags would take a
closer look, I would be grateful.
Cheers,
Tom