Niklas Hambüchen
2017-09-21 12:24:14 UTC
This is not a joke.
I just found a bug in base (https://ghc.haskell.org/trac/ghc/ticket/14262):
import System.IO
hWaitForInput stdin 4294968296
This code should wait for 49.something days, but it waits for 1 second.
It is caused by a quick use of `fromIntegral` to "convert" `Int -> CInt`
(where CInt = Int32), causing an overflow.
I argue that `fromIntegral` causes unnoticed data corruption without any
warning, and thus are worse than partial functions.
In this case, this data corruption occurs in the most fundamental code
that we all use and have to rely upon (`base`).
So I propose that we add a deprecation pragma to `fromIntegral`
(however, keeping it forever, like Java does, as there's no benefit to
removing it, we just want that people use safer functions over time),
and instead provide a `safeFromIntegral` that can only widen ranges, and
one or more `unsafeFromIntegral` or appropriately named functions that
can error, wrap, return Maybe, or have whatever desired behaviour when
the input value doesn't fit into the output type.
For some inspiration, `foundation` provides ideas in that direction:
http://hackage.haskell.org/package/basement-0.0.2/docs/Basement-From.html
http://hackage.haskell.org/package/basement-0.0.2/docs/Basement-IntegralConv.html
It is a bit funny how we argue that Haskell is good for high assurance
programming, and we build all sorts of fancy constructs to eliminate
more run-time errors, when in fact we do worse than C in detecting
errors in the most basic types a computer can use, such as converting
between 64-bit and 32-bit integers.
Let's fix that.
It avoids real problems in real production systems that are difficult to
debug when they happen (who writes a unit test checking that a timeout
of 50 days still works? This is the kind of stuff where you have to rely
on -- very basic -- types).
I'd like to probe support for such a change before doing any work on it.
Niklas
I just found a bug in base (https://ghc.haskell.org/trac/ghc/ticket/14262):
import System.IO
hWaitForInput stdin 4294968296
This code should wait for 49.something days, but it waits for 1 second.
It is caused by a quick use of `fromIntegral` to "convert" `Int -> CInt`
(where CInt = Int32), causing an overflow.
I argue that `fromIntegral` causes unnoticed data corruption without any
warning, and thus are worse than partial functions.
In this case, this data corruption occurs in the most fundamental code
that we all use and have to rely upon (`base`).
So I propose that we add a deprecation pragma to `fromIntegral`
(however, keeping it forever, like Java does, as there's no benefit to
removing it, we just want that people use safer functions over time),
and instead provide a `safeFromIntegral` that can only widen ranges, and
one or more `unsafeFromIntegral` or appropriately named functions that
can error, wrap, return Maybe, or have whatever desired behaviour when
the input value doesn't fit into the output type.
For some inspiration, `foundation` provides ideas in that direction:
http://hackage.haskell.org/package/basement-0.0.2/docs/Basement-From.html
http://hackage.haskell.org/package/basement-0.0.2/docs/Basement-IntegralConv.html
It is a bit funny how we argue that Haskell is good for high assurance
programming, and we build all sorts of fancy constructs to eliminate
more run-time errors, when in fact we do worse than C in detecting
errors in the most basic types a computer can use, such as converting
between 64-bit and 32-bit integers.
Let's fix that.
It avoids real problems in real production systems that are difficult to
debug when they happen (who writes a unit test checking that a timeout
of 50 days still works? This is the kind of stuff where you have to rely
on -- very basic -- types).
I'd like to probe support for such a change before doing any work on it.
Niklas