Skip to content

Add specs for Method#original_name and #inspect with Kernel methods#1356

Merged
eregon merged 1 commit into
ruby:masterfrom
sampokuokkanen:original-name-and-inspect
May 14, 2026
Merged

Add specs for Method#original_name and #inspect with Kernel methods#1356
eregon merged 1 commit into
ruby:masterfrom
sampokuokkanen:original-name-and-inspect

Conversation

@sampokuokkanen
Copy link
Copy Markdown
Contributor

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.

Also documents inspect's behavior on aliased methods, which wasn't previously covered.

Continuing the work started in #1353 and adding specs that fail at least on JRuby. (the specs added in that PR now pass on JRuby master though!)

sampokuokkanen added a commit to sampokuokkanen/jruby that referenced this pull request May 12, 2026
Fix Method#original_name and #inspect when two methods share a wrapper (like is_a?/kind_of?)

Introduce sourceName on DynamicMethod to preserve a method's source name when methods share a single underlying wrapper. Set it in RubyModule when binding, walk the alias chain in AliasMethod#getOldName to reach it, and consult it from Method#original_name and #inspect so both report the correct source name instead of whichever name happened to live on the wrapper.

Covered by new specs in ruby/spec#1356 (ruby/spec#1356).
sampokuokkanen added a commit to sampokuokkanen/jruby that referenced this pull request May 12, 2026
Fix Method#original_name and #inspect when two methods share a wrapper (like is_a?/kind_of?)

Introduce sourceName on DynamicMethod to preserve a method's source name when methods share a single underlying wrapper. Set it in RubyModule when binding, walk the alias chain in AliasMethod#getOldName to reach it, and consult it from Method#original_name and #inspect so both report the correct source name instead of whichever name happened to live on the wrapper.

Covered by new specs in ruby/spec#1356 (ruby/spec#1356).
Copy link
Copy Markdown
Contributor

@headius headius left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks fine to me and fills a gap in specs.

Copy link
Copy Markdown
Contributor

@headius headius left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, two small changes here would clean this up and we can merge.

Comment thread core/method/shared/to_s.rb Outdated
Comment thread core/unboundmethod/shared/to_s.rb Outdated
@sampokuokkanen sampokuokkanen force-pushed the original-name-and-inspect branch from b1a7c91 to 03ed56a Compare May 13, 2026 00:43
@sampokuokkanen sampokuokkanen requested a review from headius May 13, 2026 00:44
Comment thread core/method/shared/to_s.rb Outdated
def original_method; end
alias_method :renamed_method, :original_method
end
klass.new.method(:renamed_method).send(@method).should =~ /#renamed_method\(original_method\)/
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
klass.new.method(:renamed_method).send(@method).should =~ /#renamed_method\(original_method\)/
klass.new.method(:renamed_method).send(@method).should.include? '#renamed_method(original_method)'

Comment thread core/method/shared/to_s.rb Outdated

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?)) }
klass.new.method(:renamed_is_a?).send(@method).should =~ /#renamed_is_a\?\(is_a\?\)/
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same, .should.include? is much easier to read by avoiding escaping.
Same below

Comment thread core/method/shared/to_s.rb Outdated
Comment on lines +96 to +97
Object.new.method(:is_a?).send(@method).should_not =~ /\(kind_of\?\)/
Object.new.method(:kind_of?).send(@method).should_not =~ /\(is_a\?\)/
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.should_not.include?

Comment thread core/method/shared/to_s.rb Outdated

it "shows the source name when aliasing a define_method'd Kernel method" do
klass = Class.new do
define_method(:is_a?, ::Kernel.instance_method(:is_a?))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd be good to give this one another name for clarity and to make it more interesting

Comment thread core/method/original_name_spec.rb Outdated
Comment on lines +45 to +46
klass = Class.new { define_method(:is_a?, ::Kernel.instance_method(:is_a?)) }
klass.new.method(:is_a?).original_name.should == :is_a?
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Give the new method another name otherwise this doesn't test anything, same below

Comment thread core/method/original_name_spec.rb Outdated

it "preserves the source name when aliasing a define_method'd Kernel method" do
klass = Class.new do
define_method(:is_a?, ::Kernel.instance_method(:is_a?))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same, this should have another name

Comment thread core/unboundmethod/shared/to_s.rb Outdated
UnboundMethodSpecs::A.instance_method(:baz).send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::A#baz"
end

it "shows the original name in parentheses for an aliased method" do
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This duplication for UnboundMethod is not ideal. One way to fix it would be to use a separate shared spec describe, require it from both specs and pass a lambda as @object, for Method it's just be identity and for UnboundMethod it'd be -> meth { meth.unbind }.
This is a bigger/trickier change though so if you don't feel comfortable with it I think it's OK to keep the duplication in this PR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! That did make tests look much nicer.

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.
@sampokuokkanen sampokuokkanen force-pushed the original-name-and-inspect branch from 03ed56a to 5f21795 Compare May 14, 2026 10:19
@sampokuokkanen sampokuokkanen requested a review from eregon May 14, 2026 10:21
Copy link
Copy Markdown
Member

@eregon eregon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the new specs!

@eregon eregon merged commit e96a412 into ruby:master May 14, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants