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); } /*