summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/array.c23
-rw-r--r--test/t/syntax.rb30
2 files changed, 50 insertions, 3 deletions
diff --git a/src/array.c b/src/array.c
index 9b8a49584..df953832b 100644
--- a/src/array.c
+++ b/src/array.c
@@ -891,15 +891,32 @@ mrb_ary_rindex_m(mrb_state *mrb, mrb_value self)
MRB_API mrb_value
mrb_ary_splat(mrb_state *mrb, mrb_value v)
{
+ mrb_value a, recv_class;
+
if (mrb_array_p(v)) {
return v;
}
- if (mrb_respond_to(mrb, v, mrb_intern_lit(mrb, "to_a"))) {
- return mrb_funcall(mrb, v, "to_a", 0);
+
+ if (!mrb_respond_to(mrb, v, mrb_intern_lit(mrb, "to_a"))) {
+ return mrb_ary_new_from_values(mrb, 1, &v);
}
- else {
+
+ a = mrb_funcall(mrb, v, "to_a", 0);
+ if (mrb_array_p(a)) {
+ return a;
+ }
+ else if (mrb_nil_p(a)) {
return mrb_ary_new_from_values(mrb, 1, &v);
}
+ else {
+ recv_class = mrb_obj_value(mrb_obj_class(mrb, v));
+ mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S to Array (%S#to_a gives %S)",
+ recv_class,
+ recv_class,
+ mrb_obj_value(mrb_obj_class(mrb, a))
+ );
+ return mrb_undef_value();
+ }
}
static mrb_value
diff --git a/test/t/syntax.rb b/test/t/syntax.rb
index 25ae09828..3bc68484b 100644
--- a/test/t/syntax.rb
+++ b/test/t/syntax.rb
@@ -307,6 +307,36 @@ assert('Return values of no expression case statement') do
assert_equal 1, when_value
end
+assert('splat object in assignment') do
+ o = Object.new
+ def o.to_a
+ nil
+ end
+ assert_equal [o], (a = *o)
+
+ def o.to_a
+ 1
+ end
+ assert_raise(TypeError) { a = *o }
+
+ def o.to_a
+ [2]
+ end
+ assert_equal [2], (a = *o)
+end
+
+assert('splat object in case statement') do
+ o = Object.new
+ def o.to_a
+ nil
+ end
+ a = case o
+ when *o
+ 1
+ end
+ assert_equal 1, a
+end
+
assert('splat in case statement') do
values = [3,5,1,7,8]
testa = [1,2,7]