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>
|
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
|
* 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
|
static VALUE
|
||||||
rb_ary_hash(VALUE ary)
|
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
|
static VALUE
|
||||||
rb_hash_hash(VALUE hash)
|
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
|
static int
|
||||||
|
|
2
range.c
2
range.c
|
@ -274,7 +274,7 @@ recursive_hash(VALUE range, VALUE dummy, int recur)
|
||||||
static VALUE
|
static VALUE
|
||||||
range_hash(VALUE range)
|
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
|
static void
|
||||||
|
|
2
struct.c
2
struct.c
|
@ -980,7 +980,7 @@ recursive_hash(VALUE s, VALUE dummy, int recur)
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_struct_hash(VALUE s)
|
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
|
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
|
end
|
||||||
|
|
||||||
def test_hash2
|
def test_hash2
|
||||||
|
assert_not_equal([[1]].hash, [[2]].hash)
|
||||||
a = []
|
a = []
|
||||||
a << a
|
a << a
|
||||||
assert_equal([[a]].hash, a.hash)
|
|
||||||
assert_not_equal([a, a].hash, a.hash) # Implementation dependent
|
assert_not_equal([a, a].hash, a.hash) # Implementation dependent
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -467,19 +467,6 @@ class TestThread < Test::Unit::TestCase
|
||||||
m.unlock
|
m.unlock
|
||||||
end
|
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
|
def test_thread_instance_variable
|
||||||
bug4389 = '[ruby-core:35192]'
|
bug4389 = '[ruby-core:35192]'
|
||||||
assert_in_out_err([], <<-INPUT, %w(), [], bug4389)
|
assert_in_out_err([], <<-INPUT, %w(), [], bug4389)
|
||||||
|
|
Loading…
Reference in a new issue