Project

General

Profile

Bug #15551

The behavior of FIX2INT and FIX2UINT differs by platform

Added by Eregon (Benoit Daloze) 9 months ago. Updated 3 months ago.

Status:
Open
Priority:
Normal
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

History

Updated by Eregon (Benoit Daloze) 9 months 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) 3 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.

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.

Also available in: Atom PDF