summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-01-25 03:04:10 (GMT)
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-01-25 03:04:10 (GMT)
commitaa436bdca6068a3e94dbc0a4a46a242a56355e2c (patch)
tree80ec96be355c21b0dfd25c213744eb1276826af5
parent7d87d0c466bc742b5776f2306637a73894c402ef (diff)
array.c: reduce to_ary call
* array.c (flatten): no need to call to_ary method on elements beyond the given level. [ruby-core:67637] [Bug #10748] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@49400 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog5
-rw-r--r--NEWS3
-rw-r--r--array.c6
-rw-r--r--test/ruby/test_array.rb26
4 files changed, 39 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 7af21fe..1029920 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Sun Jan 25 12:04:12 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * array.c (flatten): no need to call to_ary method on elements
+ beyond the given level. [ruby-core:67637] [Bug #10748]
+
Sun Jan 25 00:42:24 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/fiddle/win32/libffi.mk.tmpl: assemble without directory prefix.
diff --git a/NEWS b/NEWS
index 6d034b3..13185d1 100644
--- a/NEWS
+++ b/NEWS
@@ -22,6 +22,9 @@ with all sufficient information, see the ChangeLog file.
no longer changes the receiver array instantly every time the
block is called. [Feature #10714]
+ * Array#flatten and Array#flatten! no longer try to call #to_ary
+ method on elements beyond the given level. [Bug #10748]
+
* IO
* IO#close doesn't raise when the IO object is closed. [Feature #10718]
diff --git a/array.c b/array.c
index e63778e..c02ee57 100644
--- a/array.c
+++ b/array.c
@@ -4387,11 +4387,15 @@ flatten(VALUE ary, int level, int *modified)
while (1) {
while (i < RARRAY_LEN(ary)) {
elt = RARRAY_AREF(ary, i++);
+ if (level >= 0 && RARRAY_LEN(stack) / 2 >= level) {
+ rb_ary_push(result, elt);
+ continue;
+ }
tmp = rb_check_array_type(elt);
if (RBASIC(result)->klass) {
rb_raise(rb_eRuntimeError, "flatten reentered");
}
- if (NIL_P(tmp) || (level >= 0 && RARRAY_LEN(stack) / 2 >= level)) {
+ if (NIL_P(tmp)) {
rb_ary_push(result, elt);
}
else {
diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb
index 2cec70d..bf14d3d 100644
--- a/test/ruby/test_array.rb
+++ b/test/ruby/test_array.rb
@@ -790,6 +790,19 @@ class TestArray < Test::Unit::TestCase
assert_not_same(a8, a9)
end
+ def test_flatten_splat
+ bug10748 = '[ruby-core:67637] [Bug #10748]'
+ o = Object.new
+ o.singleton_class.class_eval do
+ define_method(:to_ary) do
+ raise bug10748
+ end
+ end
+ a = @cls[@cls[o]]
+ assert_raise_with_message(RuntimeError, bug10748) {a.flatten}
+ assert_nothing_raised(RuntimeError, bug10748) {a.flatten(1)}
+ end
+
def test_flatten!
a1 = @cls[ 1, 2, 3]
a2 = @cls[ 5, 6 ]
@@ -814,6 +827,19 @@ class TestArray < Test::Unit::TestCase
assert_nil(@cls[].flatten!(0), '[ruby-core:23382]')
end
+ def test_flatten_splat!
+ bug10748 = '[ruby-core:67637] [Bug #10748]'
+ o = Object.new
+ o.singleton_class.class_eval do
+ define_method(:to_ary) do
+ raise bug10748
+ end
+ end
+ a = @cls[@cls[o]]
+ assert_raise_with_message(RuntimeError, bug10748) {a.flatten!}
+ assert_nothing_raised(RuntimeError, bug10748) {a.flatten!(1)}
+ end
+
def test_flatten_with_callcc
need_continuation
o = Object.new