Nasty interaction between MagicHash and CPP LANGUAGE pragmas
Found this problem when trying to use MagicHash and CPP in the same source file.
Small test program:
{-# LANGUAGE OverloadedStrings, MagicHash, BangPatterns #-}
{-# LANGUAGE CPP #-}
import Data.ByteString (ByteString)
import Data.Int (Int64)
import qualified Data.ByteString.Char8 as B
import qualified Data.Char as C
import qualified Test.QuickCheck as QC
import GHC.Prim
import GHC.Types
readInt64 :: ByteString -> Int64
readInt64 bs =
B.foldl' (\i c -> i * 10 + fromIntegral (mhDigitToInt c)) 0
$ B.takeWhile C.isDigit bs
data Table = Table !Addr#
mhDigitToInt :: Char -> Int
mhDigitToInt (C# i) = I# (word2Int# $ indexWord8OffAddr# addr (ord# i))
where
!(Table addr) = table
table :: Table
table = Table
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00\x00\x00\x00\x00\x00\
\\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"#
-- A QuickCheck property. Test that for a number >= 0, converting it to
-- a string using show and then reading the value back with the function
-- under test returns the original value.
-- The functions under test only work on Natural numbers (the Conent-Length
-- field in a HTTP header is always >= 0) so we check the absolute value of
-- the value that QuickCheck generates for us.
prop_read_show_idempotent :: Integral a => (ByteString -> a) -> a -> Bool
prop_read_show_idempotent freader x =
let px = abs x
in px == freader (B.pack $ show px)
main :: IO ()
main =
QC.quickCheck (prop_read_show_idempotent readInt64)
Compile and running that as:
{{{ ghc -Wall test.hs -o test && ./test }}
generates an executable (with out any warnings) and when I run the executable it fails the QuickCheck test.
However, if I remove the LANGUAGE CPP pragma and recompile it, the program passes the QuickCheck test.
Using the two pragmas together makes correct code generate incorrect results.
Would like to see an error message if MagicHash and CPP are used in the same source file.
Trac metadata
Trac field | Value |
---|---|
Version | 7.2.2 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |