Bug #15551

The behavior of FIX2INT and FIX2UINT differs by platform

Added by Eregon (Benoit Daloze) over 1 year ago. Updated 9 months ago.

Target version:
ruby -v:
ruby 2.4.5p335 (2018-10-18 revision 65137) [x64-mingw32]


For instance, when sizeof(int) < sizeof(long) (such as on Linux), then


raises TypeError.
But when sizeof(int) == sizeof(long) (such as on Windows), then it returns 4.

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 for more differences.


fix2int-consistent.patch (1017 Bytes) fix2int-consistent.patch jeremyevans0 (Jeremy Evans), 07/30/2019 08:49 PM

Updated by Eregon (Benoit Daloze) over 1 year ago

FWIW, sizeof(int) == sizeof(long) is also the case on i686 Linux:

Updated by jeremyevans0 (Jeremy Evans) about 1 year 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.

Note that 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) 9 months 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.

So FIX2INT(nil) is intentionally designed to be undefined.

Also available in: Atom PDF