summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/-test-/recursion/recursion.c2
-rw-r--r--hash.c2
-rw-r--r--include/ruby/internal/intern/thread.h3
-rw-r--r--test/ruby/test_hash.rb21
-rw-r--r--thread.c4
5 files changed, 27 insertions, 5 deletions
diff --git a/ext/-test-/recursion/recursion.c b/ext/-test-/recursion/recursion.c
index 13d41f0ba8..c9935f2de2 100644
--- a/ext/-test-/recursion/recursion.c
+++ b/ext/-test-/recursion/recursion.c
@@ -16,7 +16,7 @@ exec_recursive(VALUE self, VALUE mid)
static VALUE
exec_recursive_outer(VALUE self, VALUE mid)
{
- return rb_exec_recursive_outer(recursive_i, self, mid);
+ return rb_exec_recursive_outer_mid(recursive_i, self, mid, rb_intern("exec_recursive_outer"));
}
void
diff --git a/hash.c b/hash.c
index 797fe6fbfe..c6aa83eb0d 100644
--- a/hash.c
+++ b/hash.c
@@ -195,7 +195,7 @@ obj_any_hash(VALUE obj)
VALUE hval = rb_check_funcall_basic_kw(obj, id_hash, rb_mKernel, 0, 0, 0);
if (hval == Qundef) {
- hval = rb_exec_recursive_outer(hash_recursive, obj, 0);
+ hval = rb_exec_recursive_outer_mid(hash_recursive, obj, 0, id_hash);
}
while (!FIXNUM_P(hval)) {
diff --git a/include/ruby/internal/intern/thread.h b/include/ruby/internal/intern/thread.h
index 716375acd7..ef4274e4b3 100644
--- a/include/ruby/internal/intern/thread.h
+++ b/include/ruby/internal/intern/thread.h
@@ -292,6 +292,7 @@ VALUE rb_exec_recursive_paired(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VAL
* @param[in] f The function that possibly recurs.
* @param[in,out] g Passed as-is to `f`.
* @param[in,out] h Passed as-is to `f`.
+ * @param[in] mid The ID of the method name being called
* @return The return value of f.
*
* @internal
@@ -299,7 +300,7 @@ VALUE rb_exec_recursive_paired(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VAL
* It seems nobody uses the "it calls rb_throw_obj()" part of this function.
* @shyouhei doesn't understand the needs.
*/
-VALUE rb_exec_recursive_outer(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h);
+VALUE rb_exec_recursive_outer_mid(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h, ID mid);
/**
* Identical to rb_exec_recursive_outer(), except it checks for the recursion
diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb
index 073a0dabe8..91423f81ea 100644
--- a/test/ruby/test_hash.rb
+++ b/test/ruby/test_hash.rb
@@ -2166,6 +2166,27 @@ class TestHash < Test::Unit::TestCase
end
end
+ # Previously this test would fail because rb_hash inside opt_aref would look
+ # at the current method name
+ def test_hash_recursion_independent_of_mid
+ o = Class.new do
+ def hash(h, k)
+ h[k]
+ end
+
+ def any_other_name(h, k)
+ h[k]
+ end
+ end.new
+
+ rec = []; rec << rec
+
+ h = @cls[]
+ h[rec] = 1
+ assert o.hash(h, rec)
+ assert o.any_other_name(h, rec)
+ end
+
def test_any_hash_fixable
20.times do
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
diff --git a/thread.c b/thread.c
index 1295823cb3..5e659a643f 100644
--- a/thread.c
+++ b/thread.c
@@ -5158,9 +5158,9 @@ rb_exec_recursive_paired(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE pai
*/
VALUE
-rb_exec_recursive_outer(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE arg)
+rb_exec_recursive_outer_mid(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE arg, ID mid)
{
- return exec_recursive(func, obj, 0, arg, 1, rb_frame_last_func());
+ return exec_recursive(func, obj, 0, arg, 1, mid);
}
/*