mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
should not ignore the rest of recursive constructs
* array.c (rb_ary_hash): should not ignore the rest of recursive constructs. * hash.c (rb_hash_hash): ditto. * range.c (range_hash): ditto. * struct.c (rb_struct_hash): ditto. * test/-ext-/test_recursion.rb (TestRecursion): separate from test/ruby/test_thread.rb. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43860 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
d503381ce8
commit
94f01c55df
10 changed files with 85 additions and 18 deletions
14
ChangeLog
14
ChangeLog
|
@ -1,3 +1,17 @@
|
|||
Wed Nov 27 02:20:13 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* array.c (rb_ary_hash): should not ignore the rest of recursive
|
||||
constructs.
|
||||
|
||||
* hash.c (rb_hash_hash): ditto.
|
||||
|
||||
* range.c (range_hash): ditto.
|
||||
|
||||
* struct.c (rb_struct_hash): ditto.
|
||||
|
||||
* test/-ext-/test_recursion.rb (TestRecursion): separate from
|
||||
test/ruby/test_thread.rb.
|
||||
|
||||
Tue Nov 26 22:43:36 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* hash.c (rb_hash): cut off if recursion detected to get rid of stack
|
||||
|
|
2
array.c
2
array.c
|
@ -3807,7 +3807,7 @@ recursive_hash(VALUE ary, VALUE dummy, int recur)
|
|||
static VALUE
|
||||
rb_ary_hash(VALUE ary)
|
||||
{
|
||||
return rb_exec_recursive_outer(recursive_hash, ary, 0);
|
||||
return rb_exec_recursive_paired(recursive_hash, ary, ary, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
2
ext/-test-/recursion/extconf.rb
Normal file
2
ext/-test-/recursion/extconf.rb
Normal file
|
@ -0,0 +1,2 @@
|
|||
require 'mkmf'
|
||||
create_makefile("-test-/recursion")
|
28
ext/-test-/recursion/recursion.c
Normal file
28
ext/-test-/recursion/recursion.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include <ruby.h>
|
||||
|
||||
static VALUE
|
||||
recursive_i(VALUE obj, VALUE mid, int recur)
|
||||
{
|
||||
if (recur) return Qnil;
|
||||
return rb_funcallv(obj, rb_to_id(mid), 0, 0);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
exec_recursive(VALUE self, VALUE mid)
|
||||
{
|
||||
return rb_exec_recursive(recursive_i, self, mid);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
exec_recursive_outer(VALUE self, VALUE mid)
|
||||
{
|
||||
return rb_exec_recursive_outer(recursive_i, self, mid);
|
||||
}
|
||||
|
||||
void
|
||||
Init_recursion(void)
|
||||
{
|
||||
VALUE m = rb_define_module_under(rb_define_module("Bug"), "Recursive");
|
||||
rb_define_method(m, "exec_recursive", exec_recursive, 1);
|
||||
rb_define_method(m, "exec_recursive_outer", exec_recursive_outer, 1);
|
||||
}
|
2
hash.c
2
hash.c
|
@ -1944,7 +1944,7 @@ recursive_hash(VALUE hash, VALUE dummy, int recur)
|
|||
static VALUE
|
||||
rb_hash_hash(VALUE hash)
|
||||
{
|
||||
return rb_exec_recursive_outer(recursive_hash, hash, 0);
|
||||
return rb_exec_recursive_paired(recursive_hash, hash, hash, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
2
range.c
2
range.c
|
@ -274,7 +274,7 @@ recursive_hash(VALUE range, VALUE dummy, int recur)
|
|||
static VALUE
|
||||
range_hash(VALUE range)
|
||||
{
|
||||
return rb_exec_recursive_outer(recursive_hash, range, 0);
|
||||
return rb_exec_recursive_paired(recursive_hash, range, range, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
2
struct.c
2
struct.c
|
@ -980,7 +980,7 @@ recursive_hash(VALUE s, VALUE dummy, int recur)
|
|||
static VALUE
|
||||
rb_struct_hash(VALUE s)
|
||||
{
|
||||
return rb_exec_recursive_outer(recursive_hash, s, 0);
|
||||
return rb_exec_recursive_paired(recursive_hash, s, s, 0);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
|
36
test/-ext-/test_recursion.rb
Normal file
36
test/-ext-/test_recursion.rb
Normal file
|
@ -0,0 +1,36 @@
|
|||
# -*- coding: us-ascii -*-
|
||||
require 'test/unit'
|
||||
require_relative '../ruby/envutil'
|
||||
|
||||
class TestRecursion < Test::Unit::TestCase
|
||||
require '-test-/recursion'
|
||||
|
||||
def setup
|
||||
@obj = Struct.new(:visited).new(false)
|
||||
@obj.extend(Bug::Recursive)
|
||||
end
|
||||
|
||||
def test_recursive
|
||||
def @obj.doit
|
||||
self.visited = true
|
||||
exec_recursive(:doit)
|
||||
raise "recursive"
|
||||
end
|
||||
assert_raise_with_message(RuntimeError, "recursive") {
|
||||
@obj.exec_recursive(:doit)
|
||||
}
|
||||
assert(@obj.visited, "obj.hash was not called")
|
||||
end
|
||||
|
||||
def test_recursive_outer
|
||||
def @obj.doit
|
||||
self.visited = true
|
||||
exec_recursive_outer(:doit)
|
||||
raise "recursive_outer should short circuit intermediate calls"
|
||||
end
|
||||
assert_nothing_raised {
|
||||
@obj.exec_recursive_outer(:doit)
|
||||
}
|
||||
assert(@obj.visited, "obj.hash was not called")
|
||||
end
|
||||
end
|
|
@ -2012,9 +2012,9 @@ class TestArray < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_hash2
|
||||
assert_not_equal([[1]].hash, [[2]].hash)
|
||||
a = []
|
||||
a << a
|
||||
assert_equal([[a]].hash, a.hash)
|
||||
assert_not_equal([a, a].hash, a.hash) # Implementation dependent
|
||||
end
|
||||
|
||||
|
|
|
@ -467,19 +467,6 @@ class TestThread < Test::Unit::TestCase
|
|||
m.unlock
|
||||
end
|
||||
|
||||
def test_recursive_outer
|
||||
arr = []
|
||||
obj = Struct.new(:foo, :visited).new(arr, false)
|
||||
arr << obj
|
||||
def obj.hash
|
||||
self[:visited] = true
|
||||
super
|
||||
raise "recursive_outer should short circuit intermediate calls"
|
||||
end
|
||||
assert_nothing_raised {arr.hash}
|
||||
assert(obj[:visited], "obj.hash was not called")
|
||||
end
|
||||
|
||||
def test_thread_instance_variable
|
||||
bug4389 = '[ruby-core:35192]'
|
||||
assert_in_out_err([], <<-INPUT, %w(), [], bug4389)
|
||||
|
|
Loading…
Reference in a new issue