[GHC] #8695: Arithmetic overflow from (minBound :: Int) `quot` (-1)
GHC
ghc-devs at haskell.org
Tue Jan 28 11:10:21 UTC 2014
#8695: Arithmetic overflow from (minBound :: Int) `quot` (-1)
------------------------------------------------+--------------------------
Reporter: rleslie | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: libraries/haskell2010 | Version: 7.6.3
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
Type of failure: Incorrect result at runtime | Unknown/Multiple
Test Case: | Difficulty:
Blocking: | Unknown
| Blocked By:
| Related Tickets:
------------------------------------------------+--------------------------
Comment (by rleslie):
Replying to [comment:6 hvr]:
> Fwiw as a precedent, the following C99 program when compiled with gcc or
clang, and executed on Linux results in a runtime exception as well:
>
> {{{#!c
> #include <stdio.h>
> #include <inttypes.h>
>
> int main(int argc, char *argv[])
> {
> volatile int32_t a = INT32_MIN;
> volatile int32_t b = -1;
> volatile int32_t c = a / b;
> printf("%" PRId32 "\n", c);
> return 0;
> }
> }}}
In C, the behavior of signed integer operations that overflow is
undefined, so this is not unexpected.
In Haskell, we have Data.Int which declares that signed fixed-precision
integer arithmetic operations are performed modulo 2!^n, and thus do not
overflow. Except {{{minBound `quot` (-1)}}} violates this rule.
> Given that `quot`/`div` is already a partial function due to div-by-
zero, and {{{minBound `quot` -1}}} being the only special case (beside
div-by-zero) for (`quot`/`div`) which leads to a result outside the
`[minBound..maxBound]` range, so I'd rather have this exception thrown
than to have a program which didn't take into account this non-obvious
overflow silently misbehaving due to a flipped sign (as you pointed out
yourself if I understood you correctly, but then dismissed it as not being
worth an exception).
The same argument could be made for many other arithmetic operations, like
`minBound * (-1)`, as well as `minBound - 1`, `maxBound + 1`, etc. I don't
see any reason to have a special case for {{{minBound `quot` (-1)}}}.
It happens that the only reason I discovered this behavior and have
reported it as a bug is that it unexpectedly caused a program to abort
rather than return the (expected) modulo arithmetic result. So a non-
obvious and unexpected exception can equally cause a program to misbehave.
This can be especially devastating in a server application.
A program that is sensitive to overflow conditions probably ought not be
using fixed-precision integers in the first place; `Integer` would be a
better choice.
But despite what you or I might prefer, the fact remains that modulo
arithmetic is the documented behavior for signed fixed-precision integers,
so I still tend to view the exception thrown by {{{minBound `quot` (-1)}}}
as a bug.
> PS: I believe one may as well argue (as an academic exercise) in a
parallel way, that `quotRem` by 0 could be assigned a value that satisfies
the laws from § 6.4.2 as well, thus making it a total function.
While that might be an interesting exercise, the laws I quoted only apply
“if `y` is non-zero”. So I argue the laws ''demand'' satisfaction when `y`
is `(-1)`.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/8695#comment:7>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list