1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

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]
This commit is contained in:
Jeremy Evans 2020-12-22 21:30:32 -08:00
parent 9aca51e8a5
commit 1e215a66d2
Notes: git 2020-12-24 12:29:45 +09:00
3 changed files with 26 additions and 3 deletions

9
proc.c
View file

@ -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) {

View file

@ -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

View file

@ -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