Skip to content

Commit 9ae6172

Browse files
authored
Merge pull request jruby#9338 from kares/bignum-op-site-10
[fix] Bignum: use correct site for coerced comparisons
2 parents bd5053a + 1b8fe65 commit 9ae6172

2 files changed

Lines changed: 44 additions & 2 deletions

File tree

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -919,7 +919,7 @@ private IRubyObject big_op(ThreadContext context, IRubyObject other, BIGNUM_OP_T
919919
} else if (other instanceof RubyFloat) {
920920
rel = float_cmp(context, (RubyFloat)other);
921921
} else {
922-
CallSite site;
922+
CallSite site = sites(context).op_gt;
923923
switch (op) {
924924
case BIGNUM_OP_GT:
925925
site = sites(context).op_gt;
@@ -934,7 +934,7 @@ private IRubyObject big_op(ThreadContext context, IRubyObject other, BIGNUM_OP_T
934934
site = sites(context).op_le;
935935
break;
936936
}
937-
return coerceRelOp(context, sites(context).op_gt, other);
937+
return coerceRelOp(context, site, other);
938938
}
939939

940940
if (rel.isNil()) return context.fals;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
require 'rspec'
2+
3+
# Regression test for RubyBignum.big_op coercion.
4+
#
5+
# When a Bignum is compared against a custom numeric type that
6+
# implements coerce, the coerced comparison must use the correct
7+
# operator (>, >=, <, <=). The bug was that all four operators
8+
# used > after coercion, so < and <= returned wrong results.
9+
10+
describe "Bignum comparison with coerce" do
11+
before :all do
12+
@cls = Class.new do
13+
def initialize(v) @v = v end
14+
def coerce(other) [self.class.new(other), self] end
15+
def >(other) @v.to_i > other.to_i end
16+
def >=(other) @v.to_i >= other.to_i end
17+
def <(other) @v.to_i < other.to_i end
18+
def <=(other) @v.to_i <= other.to_i end
19+
def to_i() @v.to_i end
20+
end
21+
end
22+
23+
it "uses > after coercion for >" do
24+
expect((2**100) > @cls.new(1)).to be true
25+
expect((2**100) > @cls.new(2**101)).to be false
26+
end
27+
28+
it "uses >= after coercion for >=" do
29+
expect((2**100) >= @cls.new(1)).to be true
30+
expect((2**100) >= @cls.new(2**101)).to be false
31+
end
32+
33+
it "uses < after coercion for <" do
34+
expect((2**100) < @cls.new(2**101)).to be true
35+
expect((2**100) < @cls.new(1)).to be false
36+
end
37+
38+
it "uses <= after coercion for <=" do
39+
expect((2**100) <= @cls.new(2**101)).to be true
40+
expect((2**100) <= @cls.new(1)).to be false
41+
end
42+
end

0 commit comments

Comments
 (0)