summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2020-12-22 21:30:32 -0800
committerJeremy Evans <code@jeremyevans.net>2020-12-23 19:29:19 -0800
commit1e215a66d26d56befab4fbb72e1d953879411955 (patch)
tree1633af4390f554711ca04b50566f544d84ee9f9e
parent9aca51e8a597fb4689c058b4e6b215ae87434e1b (diff)
Fix class of method in Method#inspect for singleton classes of classes
Previously, due to a change to fix bug 15608, Method#inspect output changed for class methods: Ruby 2.7 "#<Method: String.prepend(*)>" Before change: "#<Method: #<Class:Object>(Module)#prepend(*)>" This is wrong because the Method object was created from String and not Object. This is because the fix for bug 15608 assumed it was being called on the singleton class of a instance, and would skip the first singleton class until it got to the class itself. For class methods, this results in always using the superclass. Fix behavior to not skip until the superclass if the singleton class is the singleton class of a module or class. After change: "#<Method: #<Class:Object>(Module)#prepend(*)>" Fixes [Bug #17428]
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/3984
-rw-r--r--proc.c9
-rw-r--r--spec/ruby/core/method/shared/to_s.rb6
-rw-r--r--test/ruby/test_method.rb14
3 files changed, 26 insertions, 3 deletions
diff --git a/proc.c b/proc.c
index 06a6b80649..d3310e8621 100644
--- a/proc.c
+++ b/proc.c
@@ -3003,9 +3003,12 @@ method_inspect(VALUE method)
else {
mklass = data->klass;
if (FL_TEST(mklass, FL_SINGLETON)) {
- do {
- mklass = RCLASS_SUPER(mklass);
- } while (RB_TYPE_P(mklass, T_ICLASS));
+ VALUE v = rb_ivar_get(mklass, attached);
+ if (!(RB_TYPE_P(v, T_CLASS) || RB_TYPE_P(v, T_MODULE))) {
+ do {
+ mklass = RCLASS_SUPER(mklass);
+ } while (RB_TYPE_P(mklass, T_ICLASS));
+ }
}
rb_str_buf_append(str, rb_inspect(mklass));
if (defined_class != mklass) {
diff --git a/spec/ruby/core/method/shared/to_s.rb b/spec/ruby/core/method/shared/to_s.rb
index 1fbee870d6..8f7dd8c161 100644
--- a/spec/ruby/core/method/shared/to_s.rb
+++ b/spec/ruby/core/method/shared/to_s.rb
@@ -62,6 +62,12 @@ describe :method_to_s, shared: true do
@m = obj.method(:bar)
@string = @m.send(@method)
@string.should.start_with? "#<Method: MethodSpecs::MySub(MethodSpecs::MyMod)#bar"
+
+ c = MethodSpecs::MySub.dup
+ m = Module.new{def bar; end}
+ c.extend(m)
+ @string = c.method(:bar).send(@method)
+ @string.should.start_with? "#<Method: #<Class:#{c.inspect}>(#{m.inspect})#bar"
end
end
diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb
index af47261859..3dfab84e93 100644
--- a/test/ruby/test_method.rb
+++ b/test/ruby/test_method.rb
@@ -472,6 +472,20 @@ class TestMethod < Test::Unit::TestCase
o.singleton_class
m4 = o.method(:bar)
assert_equal("#<Method: #{c4.inspect}(#{c.inspect})#bar(foo)() #{__FILE__}:#{line_no}>", m4.inspect, bug15608)
+
+ bug17428 = '[ruby-core:101635] [Bug #17428]'
+ c4 = Class.new(c)
+ c4.class_eval { alias bar foo }
+ o = c4.new
+ o.singleton_class
+ m4 = o.method(:bar)
+ assert_equal("#<Method: #<Class:String>(Module)#prepend(*)>", String.method(:prepend).inspect, bug17428)
+
+ c5 = Class.new(String)
+ m = Module.new{def prepend; end; alias prep prepend}; line_no = __LINE__
+ c5.extend(m)
+ c6 = Class.new(c5)
+ assert_equal("#<Method: #<Class:#{c6.inspect}>(#{m.inspect})#prep(prepend)() #{__FILE__}:#{line_no}>", c6.method(:prep).inspect, bug17428)
end
def test_callee_top_level