Opened 10 years ago

Closed 10 years ago

#2166 closed bug (wontfix)

minBound `rem` (-1) fails

Reported by: atsampson Owned by:
Priority: normal Milestone:
Component: libraries/base Version: 6.8.2
Keywords: Cc:
Operating System: Linux Architecture: x86
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:


I would expect both of the following operations to return 0, on the grounds that anything rem/mod -1 is zero:

Prelude> (minBound :: Int) `rem` (-1)
*** Exception: arithmetic overflow
Prelude> (minBound :: Int) `mod` (-1)
*** Exception: arithmetic overflow

In GHC 6.8.2, the instances of Integral for the various integer types explicitly check for this case and throw the error:

    rem     x@(I32# x#) y@(I32# y#)
        | y == 0                  = divZeroError
        | x == minBound && y == (-1) = overflowError
        | otherwise               = I32# (x# `remInt32#` y#)

The current behaviour makes some sense in that rem/mod's behaviours are defined in terms of quot/div which can't give a sensible output for these input values -- but I can't really see anything wrong with changing the second guard there to return 0.

(I ran into this while implementing constant expression folding in a compiler for the occam programming language; the occam compiler test suite explicitly checks that minBound `rem` (-1) == 0.)

Change History (1)

comment:1 Changed 10 years ago by igloo

difficulty: Unknown
Resolution: wontfix
Status: newclosed

It would be odd for

(minBound :: Int) `rem` (-1)

to be different to

snd ((minBound :: Int) `quotRem` (-1))

Perhaps we could also say

quotRem x y
 | x == minBound && y == (-1) = (overflowError, 0)

although then the exception won't be thrown until later (is that good or bad?).

Anyway, can you please make a library submissions proposal for this?

Note: See TracTickets for help on using tickets.