summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authornagachika <nagachika@ruby-lang.org>2022-10-01 13:39:47 +0900
committernagachika <nagachika@ruby-lang.org>2022-10-01 15:32:44 +0900
commit9e739022ded433f189a575017d3936b79541f229 (patch)
treecfb987600d99acf60ab1959873e1cbf51028f8f7 /test
parente46532feafadef252682794c941180df72483c19 (diff)
merge revision(s) 94cea3e4d0a60326bd95be762819eed8ccd59ca6,aa53d69aa21c4dfa2a78a1cec5cb34e9697b3d30,6b7d32a5e54088b6b4014529bbf2b4b8c1a96029,c6319026caa6c8f0f569f80011e8502349a04b14,aa490f9442c32cd0e1e449ac817f410bd5924c8b: [Backport #18435]
Fix {Method,UnboundMethod}#super_method for zsuper methods * We need to resolve the zsuper method first, and then look the super method of that. --- proc.c | 25 ++++++++++++----------- spec/ruby/core/method/super_method_spec.rb | 15 +++----------- spec/ruby/core/unboundmethod/super_method_spec.rb | 16 ++++++--------- 3 files changed, 22 insertions(+), 34 deletions(-) Add specs for {Method,UnboundMethod}#owner of a zsuper method --- spec/ruby/core/method/owner_spec.rb | 6 ++++++ spec/ruby/core/unboundmethod/owner_spec.rb | 7 +++++++ 2 files changed, 13 insertions(+) Resolve zsuper method during lookup but preserve owner separately * See https://bugs.ruby-lang.org/issues/18729#note-34 * See [Bug #18729] --- proc.c | 109 +++++++++++++++++++++++++---------------------- test/ruby/test_method.rb | 66 +++++++++++++++++++++++----- 2 files changed, 114 insertions(+), 61 deletions(-) Extend tests for a zsuper method of which the method it resolved to has been removed --- test/ruby/test_method.rb | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) Reduce diff to proc.c @ b0b9f7201acab05c2a3ad92c3043a1f01df3e17f * So it's easy to review https://github.com/ruby/ruby/pull/6242 + https://github.com/ruby/ruby/pull/6467 and there are less changes overall. --- proc.c | 76 ++++++++++++++++++------------------------------ test/ruby/test_method.rb | 7 +++-- 2 files changed, 34 insertions(+), 49 deletions(-)
Diffstat (limited to 'test')
-rw-r--r--test/ruby/test_method.rb112
1 files changed, 100 insertions, 12 deletions
diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb
index f1522890e5..ac50a9d0b0 100644
--- a/test/ruby/test_method.rb
+++ b/test/ruby/test_method.rb
@@ -1052,7 +1052,7 @@ class TestMethod < Test::Unit::TestCase
c1.class_eval {undef foo}
m = c3.instance_method(:foo)
m = assert_nothing_raised(NameError, Feature9781) {break m.super_method}
- assert_equal c2, m.owner
+ assert_nil(m, Feature9781)
end
def test_super_method_removed_regular
@@ -1064,19 +1064,26 @@ class TestMethod < Test::Unit::TestCase
end
def test_prepended_public_zsuper
- mod = EnvUtil.labeled_module("Mod") {private def foo; :ok end}
+ mod = EnvUtil.labeled_module("Mod") {private def foo; [:ok] end}
obj = Object.new.extend(mod)
- mods = [obj.singleton_class]
+
class << obj
public :foo
end
- 2.times do |i|
- mods.unshift(mod = EnvUtil.labeled_module("Mod#{i}") {def foo; end})
- obj.singleton_class.prepend(mod)
- end
+
+ mod1 = EnvUtil.labeled_module("Mod1") {def foo; [:mod1] + super end}
+ obj.singleton_class.prepend(mod1)
+
+ mod2 = EnvUtil.labeled_module("Mod2") {def foo; [:mod2] + super end}
+ obj.singleton_class.prepend(mod2)
+
m = obj.method(:foo)
- assert_equal(mods, mods.map {m.owner.tap {m = m.super_method}})
- assert_nil(m.super_method)
+ assert_equal mod2, m.owner
+ assert_equal mod1, m.super_method.owner
+ assert_equal obj.singleton_class, m.super_method.super_method.owner
+ assert_equal nil, m.super_method.super_method.super_method
+
+ assert_equal [:mod2, :mod1, :ok], obj.foo
end
def test_super_method_with_prepended_module
@@ -1242,11 +1249,92 @@ class TestMethod < Test::Unit::TestCase
a.remove_method(:foo)
- assert_equal [[:rest]], unbound.parameters
- assert_equal "#<UnboundMethod: B#foo(*)>", unbound.inspect
+ assert_equal "#<UnboundMethod: B(A)#foo(arg=...) #{__FILE__}:#{line}>", unbound.inspect
+ assert_equal [[:opt, :arg]], unbound.parameters
obj = b.new
- assert_raise_with_message(NoMethodError, /super: no superclass method `foo'/) { unbound.bind_call(obj) }
+ assert_equal 1, unbound.bind_call(obj)
+
+ assert_include b.instance_methods(false), :foo
+ link = 'https://github.com/ruby/ruby/pull/6467#issuecomment-1262159088'
+ assert_raise(NameError, link) { b.instance_method(:foo) }
+ # For #test_method_list below, otherwise we get the same error as just above
+ b.remove_method(:foo)
+ end
+
+ def test_zsuper_method_removed_higher_method
+ a0 = EnvUtil.labeled_class('A0') do
+ def foo(arg1 = nil, arg2 = nil)
+ 0
+ end
+ end
+ line0 = __LINE__ - 4
+ a0_foo = a0.instance_method(:foo)
+
+ a = EnvUtil.labeled_class('A', a0) do
+ private
+ def foo(arg = nil)
+ 1
+ end
+ end
+ line = __LINE__ - 4
+
+ b = EnvUtil.labeled_class('B', a) do
+ public :foo
+ end
+
+ unbound = b.instance_method(:foo)
+
+ assert_equal a0_foo, unbound.super_method
+
+ a.remove_method(:foo)
+
+ assert_equal "#<UnboundMethod: B(A)#foo(arg=...) #{__FILE__}:#{line}>", unbound.inspect
+ assert_equal [[:opt, :arg]], unbound.parameters
+ assert_equal a0_foo, unbound.super_method
+
+ obj = b.new
+ assert_equal 1, unbound.bind_call(obj)
+
+ assert_include b.instance_methods(false), :foo
+ assert_equal "#<UnboundMethod: B(A0)#foo(arg1=..., arg2=...) #{__FILE__}:#{line0}>", b.instance_method(:foo).inspect
+ end
+
+ def test_zsuper_method_redefined_bind_call
+ c0 = EnvUtil.labeled_class('C0') do
+ def foo
+ [:foo]
+ end
+ end
+
+ c1 = EnvUtil.labeled_class('C1', c0) do
+ def foo
+ super + [:bar]
+ end
+ end
+ m1 = c1.instance_method(:foo)
+
+ c2 = EnvUtil.labeled_class('C2', c1) do
+ private :foo
+ end
+
+ assert_equal [:foo], c2.private_instance_methods(false)
+ m2 = c2.instance_method(:foo)
+
+ c1.class_exec do
+ def foo
+ [:bar2]
+ end
+ end
+
+ m3 = c2.instance_method(:foo)
+ c = c2.new
+ assert_equal [:foo, :bar], m1.bind_call(c)
+ assert_equal c1, m1.owner
+ assert_equal [:foo, :bar], m2.bind_call(c)
+ assert_equal c2, m2.owner
+ assert_equal [:bar2], m3.bind_call(c)
+ assert_equal c2, m3.owner
end
# Bug #18751