Wrong result for modulo arithmetic with GHC 9.4
Summary
With GHC-9.4.4 and optimization enabled (-O1
or -O2
) I have been observing erroneous results for newtype
s over Mod q
from the mod
package for q ≥ 2^64.
The buggy behavior appears only with GHC-9.4 and only when optimization is enabled. This indicates that it may be a bug in GHC-9.4. Moreover, the manifestation of the bug is somewhat non-deterministic. In particular it varies based on where code is placed (same or other module) and whether unrelated code is compiled along with the problematic code.
Steps to reproduce
Building and running the following program with cabal run -w ghc-9.4.4 Main.hs
(-O1
enabled) prints 0
to the terminal.
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeApplications #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Main (main) where
import Data.Mod (Mod)
import GHC.TypeNats (KnownNat)
import Numeric.Natural (Natural)
import Test.QuickCheck (Arbitrary, arbitrary)
import Test.QuickCheck.Instances ()
newtype Fq = Fq (Mod 18446744073709551616 {- 2^64 -}) deriving (Num)
instance KnownNat n => Arbitrary (Mod n) where
arbitrary = fromIntegral <$> arbitrary @Natural
instance Arbitrary Fq where
arbitrary = Fq <$> arbitrary
main :: IO ()
main = let Fq x = -1 in print x
-- the result will be the same for value of -2, -3, ... or 0 - 1.
Note, that in this example the redundant Arbitrary
instances are required for the bug to manifest. On larger code bases I have observed the bug also without these instances in the code base.
Build dependencies:
cabal-version: 3.0
name: mod-bug
version: 0.1.0.0
synopsis: demonstrate bug when using mod package
executable bug
main-is: Main.hs
hs-source-dirs: .
default-language: Haskell2010
build-depends:
, base ==4.17.0.0
, mod ==0.2.0.1
, QuickCheck ==2.14.2
, quickcheck-instances ==0.3.28
Please also see this Github issue and this gist for further details.
Expected behavior
Above program should print: 18446744073709551615
Environment
GHC-9.4.4, amd64, build with -O1
or -O2
. The bug has been reproduced both with Linux and MacOS.
I have not been able to reproduce the bug with other versions of GHC or with -O0
. I haven't tried on arm architectures.