Project

General

Profile

Actions

Bug #15551

closed

The behavior of FIX2INT and FIX2UINT differs by platform

Added by Eregon (Benoit Daloze) about 5 years ago. Updated over 4 years ago.

Status:
Rejected
Assignee:
-
Target version:
-
ruby -v:
ruby 2.4.5p335 (2018-10-18 revision 65137) [x64-mingw32]
[ruby-core:91192]

Description

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

FIX2INT(nil)

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.

See https://github.com/ruby/spec/blob/c661c0ba6a602be6e06768a319bd7d87b2a8eda6/optional/capi/fixnum_spec.rb
and https://ci.appveyor.com/project/eregon/spec-x948i/builds/21753809/job/ed8e8k97m8syp4r7 for more differences.


Files

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

Updated by Eregon (Benoit Daloze) about 5 years ago

FWIW, sizeof(int) == sizeof(long) is also the case on i686 Linux:
https://travis-ci.org/ruby/ruby/jobs/482143545

Updated by jeremyevans0 (Jeremy Evans) over 4 years 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) over 4 years 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.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0