Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
  • GHC GHC
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 5,410
    • Issues 5,410
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
  • Merge requests 604
    • Merge requests 604
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
    • Test Cases
  • Deployments
    • Deployments
    • Releases
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Glasgow Haskell CompilerGlasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #22998
Closed
Open
Issue created Feb 17, 2023 by Lars Kuhtz@larskuhtz

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
Assignee
Assign to
Time tracking