From 7ea65f9be26d17d4bcb50b85301bf5bf379e72ef Mon Sep 17 00:00:00 2001 From: nobu Date: Sat, 27 Jan 2018 10:41:43 +0000 Subject: [PATCH] compile.c: try to convert in massign `for` * compile.c (compile_for_masgn): try to convert to an Array if an element of massign `for` is not an Array. [ruby-core:84931] [Bug #14374] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62073 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- compile.c | 7 ++++--- test/ruby/test_iterator.rb | 10 ++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/compile.c b/compile.c index 0585c294c1..4365a177b4 100644 --- a/compile.c +++ b/compile.c @@ -5040,7 +5040,7 @@ static int compile_for_masgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) { /* massign to var in "for" - * args.length == 1 && Array === (tmp = args[0]) ? tmp : args + * (args.length == 1 && Array.try_convert(args[0])) || args */ const int line = nd_line(node); const NODE *var = node->nd_var; @@ -5056,8 +5056,9 @@ compile_for_masgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const nod ADD_INSN1(ret, line, putobject, INT2FIX(0)); ADD_CALL(ret, line, idAREF, INT2FIX(1)); ADD_INSN1(ret, line, putobject, rb_cArray); - ADD_INSN1(ret, line, topn, INT2FIX(1)); - ADD_CALL(ret, line, idEqq, INT2FIX(1)); + ADD_INSN(ret, line, swap); + ADD_CALL(ret, line, rb_intern("try_convert"), INT2FIX(1)); + ADD_INSN(ret, line, dup); ADD_INSNL(ret, line, branchunless, not_ary); ADD_INSN(ret, line, swap); ADD_LABEL(ret, not_ary); diff --git a/test/ruby/test_iterator.rb b/test/ruby/test_iterator.rb index 9bfa947607..ebfb60354a 100644 --- a/test/ruby/test_iterator.rb +++ b/test/ruby/test_iterator.rb @@ -107,6 +107,16 @@ class TestIterator < Test::Unit::TestCase assert_equal([1, 2, 3, 4, 5, 6, 7], x) end + def test_array_for_masgn + a = [Struct.new(:to_ary).new([1,2])] + x = [] + a.each {|i,j|x << [i,j]} + assert_equal([[1,2]], x) + x = [] + for i,j in a; x << [i,j]; end + assert_equal([[1,2]], x) + end + def test_append_method_to_built_in_class x = [[1,2],[3,4],[5,6]] assert_equal(x.iter_test1{|e|e}, x.iter_test2{|e|e})