From 5f21795ade7531f9b4b999a8c1851701b0792a4f Mon Sep 17 00:00:00 2001 From: Sampo Kuokkanen Date: Mon, 11 May 2026 14:26:32 +0900 Subject: [PATCH] Add specs for Method#original_name and #inspect with Kernel methods Adds specs for Method#original_name and #inspect when define_method or alias is used with Kernel#is_a? / Kernel#kind_of? methods that can share an internal implementation in some Ruby implementations. Existing specs didn't catch when introspection leaked the shared internal name. --- core/method/inspect_spec.rb | 2 ++ core/method/original_name_spec.rb | 16 ++++++++++++ core/method/shared/aliased_inspect.rb | 31 ++++++++++++++++++++++++ core/method/to_s_spec.rb | 2 ++ core/unboundmethod/inspect_spec.rb | 2 ++ core/unboundmethod/original_name_spec.rb | 16 ++++++++++++ core/unboundmethod/to_s_spec.rb | 2 ++ 7 files changed, 71 insertions(+) create mode 100644 core/method/shared/aliased_inspect.rb diff --git a/core/method/inspect_spec.rb b/core/method/inspect_spec.rb index e0fe1afdd0..97ff2d8c11 100644 --- a/core/method/inspect_spec.rb +++ b/core/method/inspect_spec.rb @@ -1,6 +1,8 @@ require_relative '../../spec_helper' require_relative 'shared/to_s' +require_relative 'shared/aliased_inspect' describe "Method#inspect" do it_behaves_like :method_to_s, :inspect + it_behaves_like :method_to_s_aliased, :inspect, -> meth { meth } end diff --git a/core/method/original_name_spec.rb b/core/method/original_name_spec.rb index 8fec0e7c33..b92cf35154 100644 --- a/core/method/original_name_spec.rb +++ b/core/method/original_name_spec.rb @@ -40,4 +40,20 @@ klass.new.method(:renamed).original_name.should == :my_method klass.new.method(:aliased).original_name.should == :my_method end + + it "returns the source UnboundMethod's name for Kernel#is_a? and Kernel#kind_of?" do + klass = Class.new { define_method(:my_is_a?, ::Kernel.instance_method(:is_a?)) } + klass.new.method(:my_is_a?).original_name.should == :is_a? + + klass = Class.new { define_method(:my_kind_of?, ::Kernel.instance_method(:kind_of?)) } + klass.new.method(:my_kind_of?).original_name.should == :kind_of? + end + + it "preserves the source name when aliasing a define_method'd Kernel method" do + klass = Class.new do + define_method(:my_is_a?, ::Kernel.instance_method(:is_a?)) + alias_method :renamed_is_a?, :my_is_a? + end + klass.new.method(:renamed_is_a?).original_name.should == :is_a? + end end diff --git a/core/method/shared/aliased_inspect.rb b/core/method/shared/aliased_inspect.rb new file mode 100644 index 0000000000..2a622c2f97 --- /dev/null +++ b/core/method/shared/aliased_inspect.rb @@ -0,0 +1,31 @@ +describe :method_to_s_aliased, shared: true do + # @object converts a bound Method to either a Method (identity) or an + # UnboundMethod (-> meth { meth.unbind }), so these expectations cover both + # Method#to_s/#inspect and UnboundMethod#to_s/#inspect. + + it "shows the original name in parentheses for an aliased method" do + klass = Class.new do + def original_method; end + alias_method :renamed_method, :original_method + end + @object.call(klass.new.method(:renamed_method)).send(@method).should.include? '#renamed_method(original_method)' + end + + it "shows the source UnboundMethod's name in parentheses for a define_method'd method" do + klass = Class.new { define_method(:renamed_is_a?, ::Kernel.instance_method(:is_a?)) } + @object.call(klass.new.method(:renamed_is_a?)).send(@method).should.include? '#renamed_is_a?(is_a?)' + end + + it "does not annotate a directly looked-up Kernel method with a shared internal name" do + @object.call(Object.new.method(:is_a?)).send(@method).should_not.include? '(kind_of?)' + @object.call(Object.new.method(:kind_of?)).send(@method).should_not.include? '(is_a?)' + end + + it "shows the source name when aliasing a define_method'd Kernel method" do + klass = Class.new do + define_method(:my_is_a?, ::Kernel.instance_method(:is_a?)) + alias_method :renamed_is_a?, :my_is_a? + end + @object.call(klass.new.method(:renamed_is_a?)).send(@method).should.include? '#renamed_is_a?(is_a?)' + end +end diff --git a/core/method/to_s_spec.rb b/core/method/to_s_spec.rb index 9f19011302..ba0b4fa3c6 100644 --- a/core/method/to_s_spec.rb +++ b/core/method/to_s_spec.rb @@ -1,6 +1,8 @@ require_relative '../../spec_helper' require_relative 'shared/to_s' +require_relative 'shared/aliased_inspect' describe "Method#to_s" do it_behaves_like :method_to_s, :to_s + it_behaves_like :method_to_s_aliased, :to_s, -> meth { meth } end diff --git a/core/unboundmethod/inspect_spec.rb b/core/unboundmethod/inspect_spec.rb index cecf542fcd..3abed94f7f 100644 --- a/core/unboundmethod/inspect_spec.rb +++ b/core/unboundmethod/inspect_spec.rb @@ -1,7 +1,9 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' require_relative 'shared/to_s' +require_relative '../method/shared/aliased_inspect' describe "UnboundMethod#inspect" do it_behaves_like :unboundmethod_to_s, :inspect + it_behaves_like :method_to_s_aliased, :inspect, -> meth { meth.unbind } end diff --git a/core/unboundmethod/original_name_spec.rb b/core/unboundmethod/original_name_spec.rb index fa9a6fcc63..cd5f55805d 100644 --- a/core/unboundmethod/original_name_spec.rb +++ b/core/unboundmethod/original_name_spec.rb @@ -40,4 +40,20 @@ klass.instance_method(:renamed).original_name.should == :my_method klass.instance_method(:aliased).original_name.should == :my_method end + + it "returns the source UnboundMethod's name for Kernel#is_a? and Kernel#kind_of?" do + klass = Class.new { define_method(:my_is_a?, ::Kernel.instance_method(:is_a?)) } + klass.instance_method(:my_is_a?).original_name.should == :is_a? + + klass = Class.new { define_method(:my_kind_of?, ::Kernel.instance_method(:kind_of?)) } + klass.instance_method(:my_kind_of?).original_name.should == :kind_of? + end + + it "preserves the source name when aliasing a define_method'd Kernel method" do + klass = Class.new do + define_method(:my_is_a?, ::Kernel.instance_method(:is_a?)) + alias_method :renamed_is_a?, :my_is_a? + end + klass.instance_method(:renamed_is_a?).original_name.should == :is_a? + end end diff --git a/core/unboundmethod/to_s_spec.rb b/core/unboundmethod/to_s_spec.rb index a508229b49..615d88675b 100644 --- a/core/unboundmethod/to_s_spec.rb +++ b/core/unboundmethod/to_s_spec.rb @@ -1,7 +1,9 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' require_relative 'shared/to_s' +require_relative '../method/shared/aliased_inspect' describe "UnboundMethod#to_s" do it_behaves_like :unboundmethod_to_s, :to_s + it_behaves_like :method_to_s_aliased, :to_s, -> meth { meth.unbind } end