The behavior of FIX2INT and FIX2UINT differs by platform
For instance, when
sizeof(int) < sizeof(long) (such as on Linux), then
sizeof(int) == sizeof(long) (such as on Windows), then it returns
So the behavior changes from a call to
rb_fix2int() to a raw shift without any checks.
I think it should be consistent between platforms.
Also, the code in ruby.h defining FIX2INT is fairly complicated with conditions like
#if SIZEOF_INT < SIZEOF_LONG
spanning many lines, which makes it fairly hard to follow.
and https://ci.appveyor.com/project/eregon/spec-x948i/builds/21753809/job/ed8e8k97m8syp4r7 for more differences.
Updated by jeremyevans0 (Jeremy Evans) 6 months ago
I consider this an implementation detail and not a bug. I'm guessing the reason for this behavior is if
sizeof(int) == sizeof(long), then all Fixnums are convertible to int (since all Fixnums are convertible to long). This is different than the
sizeof(int) < sizeof(long) case, where not all Fixnums are convertible to int. It is possible to add checks that a Fixnum value is passed, but doing so would hurt performance.
FIX2LONG is always a pure shift, so
FIX2LONG(Qnil) never raises. By attempting to make the
FIX2INT behavior consistent across platforms, you make
FIX2LONG inconsistent with
FIX2INT in both of the cases instead of just one.
If we still feel like this is a good idea, we could try the attached patch. I did some basic testing of this on OpenBSD-i386, where
sizeof(int) == sizeof(long). However, I recommend we keep things as they are.
Updated by mame (Yusuke Endoh) about 1 month ago
- Status changed from Open to Rejected
It is by design. doc/extension.rdoc says:
T_FIXNUM can be converted to a C integer by using the FIX2INT() macro or FIX2LONG(). Though you have to check that the data is really FIXNUM before using them, they are faster.
FIX2INT(nil) is intentionally designed to be undefined.