Skip to content

Commit 33d10f5

Browse files
committed
Fix the exception type raised when type coercion via to_f raises a NoMethodError.
1 parent 0fed0d0 commit 33d10f5

File tree

2 files changed

+26
-44
lines changed

2 files changed

+26
-44
lines changed

spec/ruby/core/math/cos_spec.rb

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
Math.cos(2*Math::PI).should be_close(1.0, TOLERANCE)
1616
end
1717

18-
1918
it "raises a TypeError unless the argument is Numeric and has #to_f" do
2019
-> { Math.cos("test") }.should raise_error(TypeError)
2120
end
@@ -24,14 +23,23 @@
2423
Math.cos(nan_value).nan?.should be_true
2524
end
2625

27-
it "raises a TypeError if the argument is nil" do
28-
-> { Math.cos(nil) }.should raise_error(TypeError)
29-
end
30-
31-
it "coerces its argument with #to_f" do
32-
f = mock_numeric('8.2')
33-
f.should_receive(:to_f).and_return(8.2)
34-
Math.cos(f).should == Math.cos(8.2)
26+
describe "coerces its argument with #to_f" do
27+
it "coerces its argument with #to_f" do
28+
f = mock_numeric('8.2')
29+
f.should_receive(:to_f).and_return(8.2)
30+
Math.cos(f).should == Math.cos(8.2)
31+
end
32+
33+
it "raises a TypeError if the given argument can't be converted to a Float" do
34+
-> { Math.cos(nil) }.should raise_error(TypeError)
35+
-> { Math.cos(:abc) }.should raise_error(TypeError)
36+
end
37+
38+
it "raises a NoMethodError if the given argument raises a NoMethodError during type coercion to a Float" do
39+
object = mock_numeric('mock-float')
40+
object.should_receive(:to_f).and_raise(NoMethodError)
41+
-> { Math.cos(object) }.should raise_error(NoMethodError)
42+
end
3543
end
3644
end
3745

src/main/java/org/truffleruby/core/cast/ToFNode.java

Lines changed: 9 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,13 @@
1010

1111
package org.truffleruby.core.cast;
1212

13+
import com.oracle.truffle.api.dsl.Cached;
14+
import com.oracle.truffle.api.dsl.Specialization;
1315
import org.truffleruby.core.numeric.BigIntegerOps;
1416
import org.truffleruby.core.numeric.RubyBignum;
1517
import org.truffleruby.language.RubyBaseNode;
16-
import org.truffleruby.language.control.RaiseException;
1718
import org.truffleruby.language.dispatch.DispatchNode;
1819

19-
import com.oracle.truffle.api.CompilerDirectives;
20-
import com.oracle.truffle.api.dsl.Cached;
21-
import com.oracle.truffle.api.dsl.Specialization;
22-
import com.oracle.truffle.api.profiles.BranchProfile;
23-
2420
public abstract class ToFNode extends RubyBaseNode {
2521

2622
@Child private DispatchNode toFNode;
@@ -53,34 +49,12 @@ protected double coerceRubyBignum(RubyBignum value) {
5349

5450
@Specialization(guards = { "!isRubyBignum(object)", "!isImplicitLongOrDouble(object)" })
5551
protected double coerceObject(Object object,
56-
@Cached BranchProfile errorProfile) {
57-
if (toFNode == null) {
58-
CompilerDirectives.transferToInterpreterAndInvalidate();
59-
toFNode = insert(DispatchNode.create());
60-
}
61-
62-
final Object coerced;
63-
try {
64-
coerced = toFNode.call(object, "to_f");
65-
} catch (RaiseException e) {
66-
if (e.getException().getLogicalClass() == coreLibrary().noMethodErrorClass) {
67-
errorProfile.enter();
68-
throw new RaiseException(
69-
getContext(),
70-
coreExceptions().typeErrorNoImplicitConversion(object, "Float", this));
71-
} else {
72-
throw e;
73-
}
74-
}
75-
76-
if (coerced instanceof Double) {
77-
return (double) coerced;
78-
} else {
79-
errorProfile.enter();
80-
throw new RaiseException(
81-
getContext(),
82-
coreExceptions().typeErrorBadCoercion(object, "Float", "to_f", coerced, this));
83-
}
52+
@Cached DispatchNode toFNode) {
53+
return (double) toFNode.call(
54+
coreLibrary().truffleTypeModule,
55+
"rb_convert_type",
56+
object,
57+
coreLibrary().floatClass,
58+
coreSymbols().TO_F);
8459
}
85-
8660
}

0 commit comments

Comments
 (0)