Skip to content

Commit 4fb0bbe

Browse files
authored
Merge pull request jruby#9336 from kares/bignum-eql-10
[fix] Bignum#eql?: use type-strict comparison (not ==)
2 parents 330e2e0 + 5707d5c commit 4fb0bbe

2 files changed

Lines changed: 36 additions & 7 deletions

File tree

core/src/main/java/org/jruby/RubyBignum.java

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,13 +1076,7 @@ public IRubyObject op_equal(ThreadContext context, IRubyObject other) {
10761076
return asBoolean(context, value.compareTo(otherValue) == 0);
10771077
}
10781078

1079-
/** rb_big_eql
1080-
*
1081-
*/
1082-
@Override
1083-
public IRubyObject eql_p(ThreadContext context, IRubyObject other) {
1084-
return op_equal(context, other); // '==' and '===' are the same, but they differ from 'eql?'.
1085-
}
1079+
// eql_p inherited from RubyNumeric: type-strict check (getClass) + equalInternal
10861080

10871081
// MRI: rb_big_hash
10881082
public RubyFixnum hash(ThreadContext context) {
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
require 'rspec'
2+
3+
# Regression test for Bignum#eql? type-strict semantics.
4+
#
5+
# Ruby's eql? must be type-strict: it should return false when
6+
# comparing an Integer with a Float or Rational, even if they
7+
# represent the same numeric value. The bug was that RubyBignum
8+
# delegated eql? to == which accepts cross-type comparisons.
9+
10+
describe "Bignum#eql?" do
11+
it "returns true for same-value Bignums" do
12+
expect((2**100).eql?(2**100)).to be true
13+
end
14+
15+
it "returns false for different-value Bignums" do
16+
expect((2**100).eql?(2**100 + 1)).to be false
17+
end
18+
19+
it "returns false for Float with same numeric value" do
20+
expect((2**100).eql?((2**100).to_f)).to be false
21+
end
22+
23+
it "returns false for Rational with same numeric value" do
24+
expect((2**100).eql?(Rational(2**100))).to be false
25+
end
26+
27+
it "returns false for Fixnum-range Integer" do
28+
expect((2**100).eql?(42)).to be false
29+
end
30+
31+
it "does not affect == which remains type-loose" do
32+
expect((2**100) == (2**100).to_f).to be true
33+
expect((2**100) == Rational(2**100)).to be true
34+
end
35+
end

0 commit comments

Comments
 (0)