Skip to content

Commit b1afc59

Browse files
committed
Fix the exception type raised when type coercion via to_ary raises a NoMethodError.
1 parent 9f072f2 commit b1afc59

File tree

2 files changed

+24
-30
lines changed

2 files changed

+24
-30
lines changed

spec/ruby/core/array/plus_spec.rb

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,23 @@
1414
(ary + ary).should == [1, 2, 3, 1, 2, 3]
1515
end
1616

17-
it "tries to convert the passed argument to an Array using #to_ary" do
18-
obj = mock('["x", "y"]')
19-
obj.should_receive(:to_ary).and_return(["x", "y"])
20-
([1, 2, 3] + obj).should == [1, 2, 3, "x", "y"]
17+
describe "converts the passed argument to an Array using #to_ary" do
18+
it "successfully concatenates the resulting array from the #to_ary call" do
19+
obj = mock('["x", "y"]')
20+
obj.should_receive(:to_ary).and_return(["x", "y"])
21+
([1, 2, 3] + obj).should == [1, 2, 3, "x", "y"]
22+
end
23+
24+
it "raises a Typeerror if the given argument can't be converted to an array" do
25+
-> { [1, 2, 3] + nil }.should raise_error(TypeError)
26+
-> { [1, 2, 3] + "abc" }.should raise_error(TypeError)
27+
end
28+
29+
it "raises a NoMethodError if the given argument raises a NoMethodError during type coercion to an Array" do
30+
obj = mock("hello")
31+
obj.should_receive(:to_ary).and_raise(NoMethodError)
32+
-> { [1, 2, 3] + obj }.should raise_error(NoMethodError)
33+
end
2134
end
2235

2336
it "properly handles recursive arrays" do

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

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,11 @@
1212
import com.oracle.truffle.api.dsl.NeverDefault;
1313
import org.truffleruby.core.array.RubyArray;
1414
import org.truffleruby.language.RubyBaseNodeWithExecute;
15-
import org.truffleruby.language.control.RaiseException;
16-
import org.truffleruby.language.dispatch.DispatchNode;
1715

1816
import com.oracle.truffle.api.dsl.Cached;
1917
import com.oracle.truffle.api.dsl.NodeChild;
2018
import com.oracle.truffle.api.dsl.Specialization;
21-
import com.oracle.truffle.api.profiles.BranchProfile;
19+
import org.truffleruby.language.dispatch.DispatchNode;
2220

2321
@NodeChild(value = "childNode", type = RubyBaseNodeWithExecute.class)
2422
public abstract class ToAryNode extends RubyBaseNodeWithExecute {
@@ -43,30 +41,13 @@ protected RubyArray coerceRubyArray(RubyArray array) {
4341

4442
@Specialization(guards = "!isRubyArray(object)")
4543
protected RubyArray coerceObject(Object object,
46-
@Cached BranchProfile errorProfile,
4744
@Cached DispatchNode toAryNode) {
48-
final Object coerced;
49-
try {
50-
coerced = toAryNode.call(object, "to_ary");
51-
} catch (RaiseException e) {
52-
errorProfile.enter();
53-
if (e.getException().getLogicalClass() == coreLibrary().noMethodErrorClass) {
54-
throw new RaiseException(
55-
getContext(),
56-
coreExceptions().typeErrorNoImplicitConversion(object, "Array", this));
57-
} else {
58-
throw e;
59-
}
60-
}
61-
62-
if (coerced instanceof RubyArray) {
63-
return (RubyArray) coerced;
64-
} else {
65-
errorProfile.enter();
66-
throw new RaiseException(
67-
getContext(),
68-
coreExceptions().typeErrorBadCoercion(object, "Array", "to_ary", coerced, this));
69-
}
45+
return (RubyArray) toAryNode.call(
46+
coreLibrary().truffleTypeModule,
47+
"rb_convert_type",
48+
object,
49+
coreLibrary().arrayClass,
50+
coreSymbols().TO_ARY);
7051
}
7152

7253
@Override

0 commit comments

Comments
 (0)