Skip to content

Commit 0fed0d0

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

File tree

2 files changed

+32
-39
lines changed

2 files changed

+32
-39
lines changed

spec/ruby/core/queue/initialize_spec.rb

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,29 @@
2222
q.should.empty?
2323
end
2424

25-
it "uses #to_a on the provided Enumerable" do
26-
enumerable = MockObject.new('mock-enumerable')
27-
enumerable.should_receive(:to_a).and_return([1, 2, 3])
28-
q = Queue.new(enumerable)
29-
q.size.should == 3
30-
q.should_not.empty?
31-
q.pop.should == 1
32-
q.pop.should == 2
33-
q.pop.should == 3
34-
q.should.empty?
25+
describe "converts the given argument to an Array using #to_a" do
26+
it "uses #to_a on the provided Enumerable" do
27+
enumerable = MockObject.new('mock-enumerable')
28+
enumerable.should_receive(:to_a).and_return([1, 2, 3])
29+
q = Queue.new(enumerable)
30+
q.size.should == 3
31+
q.should_not.empty?
32+
q.pop.should == 1
33+
q.pop.should == 2
34+
q.pop.should == 3
35+
q.should.empty?
36+
end
37+
38+
it "raises a TypeError if the given argument can't be converted to an Array" do
39+
-> { Queue.new(42) }.should raise_error(TypeError)
40+
-> { Queue.new(:abc) }.should raise_error(TypeError)
41+
end
42+
43+
it "raises a NoMethodError if the given argument raises a NoMethodError during type coercion to an Array" do
44+
enumerable = MockObject.new('mock-enumerable')
45+
enumerable.should_receive(:to_a).and_raise(NoMethodError)
46+
-> { Queue.new(enumerable) }.should raise_error(NoMethodError)
47+
end
3548
end
3649

3750
it "raises TypeError if the provided Enumerable does not respond to #to_a" do

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

Lines changed: 9 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,8 @@
1313
import com.oracle.truffle.api.dsl.NeverDefault;
1414
import com.oracle.truffle.api.dsl.NodeChild;
1515
import com.oracle.truffle.api.dsl.Specialization;
16-
import com.oracle.truffle.api.profiles.BranchProfile;
1716
import org.truffleruby.core.array.RubyArray;
1817
import org.truffleruby.language.RubyBaseNodeWithExecute;
19-
import org.truffleruby.language.control.RaiseException;
2018
import org.truffleruby.language.dispatch.DispatchNode;
2119

2220
// Casting of enumerable that is supposed to respond to the #to_a method to RubyArray
@@ -41,33 +39,15 @@ protected RubyArray toA(RubyArray array) {
4139
return array;
4240
}
4341

44-
@Specialization(guards = "!isRubyArray(enumerable)")
45-
protected RubyArray toA(Object enumerable,
46-
@Cached BranchProfile errorProfile,
47-
@Cached DispatchNode toANode) {
48-
final Object coerced;
49-
50-
try {
51-
coerced = toANode.call(enumerable, "to_a");
52-
} catch (RaiseException e) {
53-
errorProfile.enter();
54-
if (e.getException().getLogicalClass() == coreLibrary().noMethodErrorClass) {
55-
throw new RaiseException(
56-
getContext(),
57-
coreExceptions().typeErrorCantConvertInto(enumerable, "Array", this));
58-
} else {
59-
throw e;
60-
}
61-
}
62-
63-
if (!(coerced instanceof RubyArray)) {
64-
errorProfile.enter();
65-
throw new RaiseException(
66-
getContext(),
67-
coreExceptions().typeErrorCantConvertTo(enumerable, "Array", "to_a", coerced, this));
68-
}
69-
70-
return (RubyArray) coerced;
42+
@Specialization(guards = "!isRubyArray(object)")
43+
protected RubyArray coerceObject(Object object,
44+
@Cached DispatchNode toAryNode) {
45+
return (RubyArray) toAryNode.call(
46+
coreLibrary().truffleTypeModule,
47+
"rb_convert_type",
48+
object,
49+
coreLibrary().arrayClass,
50+
coreSymbols().TO_A);
7151
}
7252

7353
@Override

0 commit comments

Comments
 (0)