Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Float#equal? behaves differently from MRI in 2.0 mode #2418

Closed
mvz opened this issue Jan 3, 2015 · 6 comments
Closed

Float#equal? behaves differently from MRI in 2.0 mode #2418

mvz opened this issue Jan 3, 2015 · 6 comments

Comments

@mvz
Copy link

mvz commented Jan 3, 2015

Float#equal? changed behavior in MRI 2.0.0 wrt MRI 1.9.3. For identical values, the older MRI would return false. MRI 2.0 and up return true:

MRI 1.9.3:

1.0.equal? 1.0
=> false

MRI 2.0.0:

1.0.equal? 1.0
=> true

JRuby returns false even in 2.0 mode.

@headius
Copy link
Member

headius commented Jan 12, 2015

This might be an easy one to track down, so I'll mark with beginner for now.

We don't officially support 2.0 mode on 1.7, so marking this as a 9k bug.

@haberbyte
Copy link

I don't quite get how JRuby manages object ids in the implementation yet, so no fix here but maybe this helps people get started:

Problem in JRuby is that a Float does not always map to the same object id:

>> 1.0.object_id
=> 2042
>> 1.0.object_id
=> 2044
>> 1.0.object_id
=> 2046

Whereas MRI gives:

>> 1.0.object_id
=> -36028797018963966
>> 1.0.object_id
=> -36028797018963966

Also note that there is an existing spec in spec/ruby/core/kernel/Float_spec.rb that is supposed to test exactly that, i guess.

it "returns the identical Float for numeric Floats" do
    float = 1.12
    float2 = @object.send(:Float, float)
    float2.should == float
    float2.object_id.should == float.object_id
  end

But this test actually PASSES also on JRuby, so i guess the spec should also add:
float.object_id.should == 1.12.object_id

@enebo
Copy link
Member

enebo commented Jan 14, 2015

Ruby 1.8.x used to allow floats to be modified via scale= and I suspect our logic reflects that it used to be a non-immediate value type.

@headius
Copy link
Member

headius commented Jan 14, 2015

Oh, I just realized what's causing this: MRI now uses tagged pointers for floats too.

We do not have any way to support tagged pointers, which means that all Float instances are real, allocated, GCable objects with their own identities. Rubinius and other impls also do not use tagged pointers for Float, though some support tagged pointers for Fixnum.

I would call this an implementation detail; you should not rely on two Floats being .equal?.

@headius
Copy link
Member

headius commented Jan 14, 2015

Did you run into this issue in the wild? I would strongly recommend against ever writing code that expects two value-equivalent Float objects to always be the same object.

@mvz
Copy link
Author

mvz commented Jan 15, 2015

I came across it while debugging a build failure on unparser (https://github.com/mbj/unparser). It was fixed in mbj/unparser@fab00e7 by replacing #equal? with #eql?.

I'm fine with calling this an implementation detail and leaving it at that.

Thanks for looking into this.

@headius headius closed this as completed Jan 16, 2015
@headius headius modified the milestones: Won't Fix, JRuby 9.0.0.0 Jan 16, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants