Skip to content

-O, strictness flags, and derived Eq

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

Trac metadata
Trac field Value
Version None
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution ResolvedFixed
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information