[前][次][番号順一覧][スレッド一覧]

ruby-changes:64540

From: Jeremy <ko1@a...>
Date: Thu, 24 Dec 2020 12:29:41 +0900 (JST)
Subject: [ruby-changes:64540] 1e215a66d2 (master): Fix class of method in Method#inspect for singleton classes of classes

https://git.ruby-lang.org/ruby.git/commit/?id=1e215a66d2

From 1e215a66d26d56befab4fbb72e1d953879411955 Mon Sep 17 00:00:00 2001
From: Jeremy Evans <code@j...>
Date: Tue, 22 Dec 2020 21:30:32 -0800
Subject: 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]

diff --git a/proc.c b/proc.c
index 06a6b80..d3310e8 100644
--- a/proc.c
+++ b/proc.c
@@ -3003,9 +3003,12 @@ method_inspect(VALUE method) https://github.com/ruby/ruby/blob/trunk/proc.c#L3003
     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 1fbee87..8f7dd8c 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 https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/method/shared/to_s.rb#L62
       @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 af47261..3dfab84 100644
--- a/test/ruby/test_method.rb
+++ b/test/ruby/test_method.rb
@@ -472,6 +472,20 @@ class TestMethod < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_method.rb#L472
     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
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]