Hello,
I’m trying to fix a bug in the mocks.cr shard. (Here’s my issue on GitHub.) It’s doing some hash calculations like this:
def hash
object_id.hash * 32 + args.hash
end
# ...
def hash
@registry_name.hash * 32 * 32 + @name.hash * 32 + @object_id.hash
end
These are crashing with OverflowError: Arithmetic overflow
:
Error: Arithmetic overflow
OverflowError: Arithmetic overflow
lib/mocks/src/mocks/registry.cr:86:60 in 'hash'
/usr/local/Cellar/crystal/0.31.1/src/hash.cr:893:12 in 'key_hash'
/usr/local/Cellar/crystal/0.31.1/src/hash.cr:336:5 in 'upsert'
/usr/local/Cellar/crystal/0.31.1/src/hash.cr:912:5 in '[]='
lib/mocks/src/mocks/registry.cr:104:9 in 'add'
lib/mocks/src/mocks/registry.cr:156:9 in 'store_stub'
...
Is there any way I can tell the compiler that I don’t care about overflows, since this is a hashing algorithm where the final result just needs to be unique?
In the meantime, I’ve been able to fix these hash methods with some bit shifts (and sent a PR), to make sure it never overflows a UInt64:
def hash
(object_id.hash >> 2) + (args.hash >> 2)
end
# ...
def hash
(@registry_name.hash >> 3) + (@name.hash >> 3) + (@object_id.hash >> 3)
end
Is there a better way to fix this issue?