In order to get the same behaviour as with -Ddisable_overflow you will have to use wrapping operators (&+ etc.), as announced in the release notes of 0.34.0 and 0.31.0.
If we want to avoid OverflowError exception we must use the &+ method
puts Int64::MAX
puts Int64::MAX &+ 1
Result:
9223372036854775807
-9223372036854775808
If we use the + method it will throw an OverflowError exception:
Unhandled exception: Arithmetic overflow (OverflowError)
from /eval:3:17 in '__crystal_main'
from /usr/lib/crystal/crystal/main.cr:106:5 in 'main_user_code'
from /usr/lib/crystal/crystal/main.cr:92:7 in 'main'
from /usr/lib/crystal/crystal/main.cr:115:3 in 'main'
from __libc_start_main
from _start
from ???
But most of my code is using u64 numbers, not signed.
Can you show more normal code usage.
I’m getting this error message repeated:
Unhandled exception in spawn: Arithmetic overflow (OverflowError)
from /home/jzakiya/crystal/share/crystal/src/array.cr:575:29 in '->'
from /home/jzakiya/crystal/share/crystal/src/fiber.cr:255:3 in 'run'
These are lines 254:255
te = (Time.monotonic - ts).total_seconds.round(6)
puts "setup time = #{te} secs" # display sieve setup time
It’s strange. On Mac, if I run the code I get the exact location where the error happens:
Unhandled exception in spawn: Arithmetic overflow (OverflowError)
from foo.cr:193:59 in 'twins_sieve'
from foo.cr:248:14 in '->'
from /usr/local/Cellar/crystal/0.34.0/src/fiber.cr:255:3 in 'run'
from /usr/local/Cellar/crystal/0.34.0/src/fiber.cr:92:34 in '->'
Do you get the same error? Maybe in linux it doesn’t work exactly like that…
In any case, the relevant code is this:
((2_u64 << ((kn - 1) & bmask)) - 1)
The expression on the right side which is being subtracted 1 from ends up being 0_u64. Then 0_u64 - 1 will overflow (actually underflow, but we use the same exception object).
If it’s okay that it should overflow, you can use &- 1 instead of - 1.
I’m going to see if I can find equivalent code without overflow issues.
Please provide better description/documentation of this new “feature” that’s easier for users to understand. You can even use this code snippet if you want to explicitly show code susceptible to overflow (it errors after kn gets too large), and then how to fix it.
Are you comparing 0.33.0 with -Ddisable_overflow against 0.34.0? That’s likely influenced by other changes between 0.33.0 and 0.34.0. You need to compare default 0.33.0 (without -Ddisable_overflow.) against 0.34.0.
The overflow feature was not introduced in 0.34.0 but 0.31.0. So it’s not a “new” feature. We just stopped supporting the legacy behaviour. Since 0.31.0 your code required the disable flag to retain the old operator semantics. It was announced this flag would just be temporary feature to ease the porting process.
When you replace all operators with the wrapping variant (&+) you should technically end up with essentially the same compiled code as before 0.31.0. So 1 &+ 1 in 0.31.0+ is equivalent to 1 + 1 in 0.30.0 (and 0.31.0 - 0.33.0 with -Ddisable_overflow).
-Ddisable_overflow is ignored in 0.34.0 I think. If you want the old speed (with unsafe operatorion–are those overflows it reported expected?) you could use &+ etc. everywhere. It should be as fast.
In terms of size you could iterate over the commits between 0.33.0 and 0.34.0 and see which ones seemed to add it and debate their merits.
Cheers!
Both 1) and 2) will compile/run with 0.34 without -Ddisable_overflow.
For 0.33, 1) needs -Ddisable_overflow, 2) doesn’t, but runs either way.
However, compiling 0.33 w/o -Ddisable_overflow the (stripped) binary is 20KB larger than with it.
Please run on your systems to see these size/performance differences.
Clarification:
I meant the original code for 1) w/o &- needs flag for 0.33.