summaryrefslogtreecommitdiff
path: root/libraries
diff options
context:
space:
mode:
authorSylvain Henry <sylvain@haskus.fr>2021-02-11 14:11:29 +0100
committerMarge Bot <ben+marge-bot@smart-cactus.org>2021-02-13 21:33:56 -0500
commit5e71dd3379ec4738c3f88271803d0de9b77e004f (patch)
treeaf9264330075bf1bc139b3d23153dcd822b0673d /libraries
parent3331b3ad0db55193832617f3af3b18182dc1d4af (diff)
downloadhaskell-5e71dd3379ec4738c3f88271803d0de9b77e004f.tar.gz
Bignum: fix bogus rewrite rule (#19345)
Fix the following rule: "fromIntegral/Int->Natural" fromIntegral = naturalFromWord . fromIntegral Its type wasn't constrained to Int hence #19345.
Diffstat (limited to 'libraries')
-rw-r--r--libraries/base/GHC/Real.hs21
1 files changed, 16 insertions, 5 deletions
diff --git a/libraries/base/GHC/Real.hs b/libraries/base/GHC/Real.hs
index ee61e34e70..4329bb7355 100644
--- a/libraries/base/GHC/Real.hs
+++ b/libraries/base/GHC/Real.hs
@@ -580,14 +580,25 @@ fromIntegral = fromInteger . toInteger
#-}
{-# RULES
-"fromIntegral/Natural->Natural" fromIntegral = id :: Natural -> Natural
-"fromIntegral/Natural->Integer" fromIntegral = toInteger :: Natural->Integer
-"fromIntegral/Natural->Word" fromIntegral = naturalToWord
+"fromIntegral/Natural->Natural" fromIntegral = id :: Natural -> Natural
+"fromIntegral/Natural->Integer" fromIntegral = toInteger :: Natural -> Integer
+"fromIntegral/Natural->Word" fromIntegral = naturalToWord :: Natural -> Word
#-}
+-- Don't forget the type signatures in the following rules! Without a type
+-- signature we end up with the rule:
+--
+-- "fromIntegral/Int->Natural" forall a (d::Integral a).
+-- fromIntegral @a @Natural = naturalFromWord . fromIntegral @a d
+--
+-- but this rule is certainly not valid for every Integral type a!
+--
+-- This rule wraps any Integral input into Word's range. As a consequence,
+-- (2^64 :: Integer) was incorrectly wrapped to (0 :: Natural), see #19345.
+
{-# RULES
-"fromIntegral/Word->Natural" fromIntegral = naturalFromWord
-"fromIntegral/Int->Natural" fromIntegral = naturalFromWord . fromIntegral
+"fromIntegral/Word->Natural" fromIntegral = naturalFromWord :: Word -> Natural
+"fromIntegral/Int->Natural" fromIntegral = naturalFromWord . fromIntegral :: Int -> Natural
#-}
-- | general coercion to fractional types