Skip to content

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 newtypes 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.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information