ruby-changes:60341
From: Jeremy <ko1@a...>
Date: Mon, 9 Mar 2020 23:57:35 +0900 (JST)
Subject: [ruby-changes:60341] e02bd0e713 (master): Don't display singleton class in Method#inspect unless method defined there
https://git.ruby-lang.org/ruby.git/commit/?id=e02bd0e713 From e02bd0e713ef920e6d12c27f16548f48ec5c2cf0 Mon Sep 17 00:00:00 2001 From: Jeremy Evans <code@j...> Date: Mon, 9 Mar 2020 07:57:16 -0700 Subject: Don't display singleton class in Method#inspect unless method defined there Previously, if an object has a singleton class, and you call Object#method on the object, the resulting string would include the object's singleton class, even though the method was not defined in the singleton class. Change this so the we only show the singleton class if the method is defined in the singleton class. Fixes [Bug #15608] diff --git a/proc.c b/proc.c index 390b1bf..0b1be9c 100644 --- a/proc.c +++ b/proc.c @@ -2812,7 +2812,8 @@ method_inspect(VALUE method) https://github.com/ruby/ruby/blob/trunk/proc.c#L2812 TypedData_Get_Struct(method, struct METHOD, &method_data_type, data); str = rb_sprintf("#<% "PRIsVALUE": ", rb_obj_class(method)); - mklass = data->klass; + mklass = data->iclass; + if (!mklass) mklass = data->klass; if (RB_TYPE_P(mklass, T_ICLASS)) { /* TODO: I'm not sure why mklass is T_ICLASS. @@ -2852,6 +2853,12 @@ method_inspect(VALUE method) https://github.com/ruby/ruby/blob/trunk/proc.c#L2853 } } else { + mklass = data->klass; + if (FL_TEST(mklass, FL_SINGLETON)) { + do { + mklass = RCLASS_SUPER(mklass); + } while (RB_TYPE_P(mklass, T_ICLASS)); + } rb_str_buf_append(str, rb_inspect(mklass)); if (defined_class != mklass) { rb_str_catf(str, "(% "PRIsVALUE")", defined_class); diff --git a/spec/ruby/core/method/shared/to_s.rb b/spec/ruby/core/method/shared/to_s.rb index 373398a..7666322 100644 --- a/spec/ruby/core/method/shared/to_s.rb +++ b/spec/ruby/core/method/shared/to_s.rb @@ -31,4 +31,22 @@ describe :method_to_s, shared: true do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/method/shared/to_s.rb#L31 it "returns a String containing the Module the method is referenced from" do @string.should =~ /MethodSpecs::MySub/ end + + ruby_version_is '2.8' do + it "returns a String containing the Module containing the method if object has a singleton class but method is not defined in the singleton class" do + obj = MethodSpecs::MySub.new + obj.singleton_class + @m = obj.method(:bar) + @string = @m.send(@method).sub(/0x\w+/, '0xXXXXXX') + @string.should =~ /\A#<Method: MethodSpecs::MySub\(MethodSpecs::MyMod\)#bar\(\) / + end + end + + it "returns a String containing the singleton class if method is defined in the singleton class" do + obj = MethodSpecs::MySub.new + def obj.bar; end + @m = obj.method(:bar) + @string = @m.send(@method).sub(/0x\w+/, '0xXXXXXX') + @string.should =~ /\A#<Method: #<MethodSpecs::MySub:0xXXXXXX>\.bar/ + end end diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb index 563011a..01a6905 100644 --- a/test/ruby/test_method.rb +++ b/test/ruby/test_method.rb @@ -465,6 +465,14 @@ class TestMethod < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_method.rb#L465 c3.class_eval { alias bar foo } m3 = c3.new.method(:bar) assert_equal("#<Method: #{c3.inspect}(#{c.inspect})#bar(foo)() #{__FILE__}:#{line_no}>", m3.inspect, bug7806) + + bug15608 = '[ruby-core:91570] [Bug #15608]' + c4 = Class.new(c) + c4.class_eval { alias bar foo } + o = c4.new + o.singleton_class + m4 = o.method(:bar) + assert_equal("#<Method: #{c4.inspect}(#{c.inspect})#bar(foo)() #{__FILE__}:#{line_no}>", m4.inspect, bug15608) end def test_callee_top_level -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/