Skip to content

Commit d8f050d

Browse files
committed
Fix numeric coercion when #coerce isn't public
1 parent 241afc9 commit d8f050d

File tree

5 files changed

+54
-2
lines changed

5 files changed

+54
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Compatibility:
1717
* Fix explicitly inherited `Struct` subclasses and don't provide `#members` method (#3802, @andrykonchin).
1818
* Support Digest plugins (#1390, @nirvdrum).
1919
* Joni has been updated from 2.2.1 to 2.2.6 (@andrykonchin).
20+
* Fix numeric coercing when `#coerce` method is not public (#3848, @andrykonchin).
2021

2122
Performance:
2223

spec/ruby/core/integer/divide_spec.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,21 @@
106106
-> { @bignum / :symbol }.should raise_error(TypeError)
107107
end
108108
end
109+
110+
it "coerces the RHS and calls #coerce" do
111+
obj = mock("integer plus")
112+
obj.should_receive(:coerce).with(6).and_return([6, 3])
113+
(6 / obj).should == 2
114+
end
115+
116+
it "coerces the RHS and calls #coerce even if it's private" do
117+
obj = Object.new
118+
class << obj
119+
private def coerce(n)
120+
[n, 3]
121+
end
122+
end
123+
124+
(6 / obj).should == 2
125+
end
109126
end

spec/ruby/core/integer/minus_spec.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,21 @@
4040
-> { @bignum - :symbol }.should raise_error(TypeError)
4141
end
4242
end
43+
44+
it "coerces the RHS and calls #coerce" do
45+
obj = mock("integer plus")
46+
obj.should_receive(:coerce).with(5).and_return([5, 10])
47+
(5 - obj).should == -5
48+
end
49+
50+
it "coerces the RHS and calls #coerce even if it's private" do
51+
obj = Object.new
52+
class << obj
53+
private def coerce(n)
54+
[n, 10]
55+
end
56+
end
57+
58+
(5 - obj).should == -5
59+
end
4360
end

spec/ruby/core/integer/plus_spec.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,21 @@ def +(other)
5555
RUBY
5656
ruby_exe(code).should == "-1"
5757
end
58+
59+
it "coerces the RHS and calls #coerce" do
60+
obj = mock("integer plus")
61+
obj.should_receive(:coerce).with(6).and_return([6, 3])
62+
(6 + obj).should == 9
63+
end
64+
65+
it "coerces the RHS and calls #coerce even if it's private" do
66+
obj = Object.new
67+
class << obj
68+
private def coerce(n)
69+
[n, 3]
70+
end
71+
end
72+
73+
(6 + obj).should == 9
74+
end
5875
end

src/main/ruby/truffleruby/core/numeric.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,9 @@ def coerce(other)
179179

180180
def math_coerce(other, error = :coerce_error)
181181
other = Truffle::Interop.unbox_if_needed(other)
182-
return math_coerce_error(other, error) unless other.respond_to? :coerce
182+
return math_coerce_error(other, error) unless other.respond_to?(:coerce, true)
183183

184-
values = other.coerce(self)
184+
values = other.__send__(:coerce, self)
185185

186186
unless Primitive.is_a?(values, Array) && values.length == 2
187187
if error == :no_error

0 commit comments

Comments
 (0)