Project

General

Profile

Actions

Bug #20620

closed

singleton_method undefined for module using "extend self"

Added by dentarg (Patrik Ragnarsson) 6 months ago. Updated 3 months ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 3.4.0dev (2024-07-08T21:43:28Z master e500222de1) [x86_64-linux]
[ruby-core:118514]

Description

Is this a bug? I expected ExtendSelf.singleton_method(:foo) to work when ExtendSelf.singleton_methods worked and :foo was in the list returned.

# singleton_method.rb
class Klass
  def self.foo
  end
end

module ExtendSelf
  extend self

  def foo
  end
end

p RUBY_DESCRIPTION

p "Klass"
p Klass.singleton_methods      # => [:foo]
p Klass.singleton_method(:foo) # => #<Method: Klass.foo() singleton_method.rb:2>

p "ExtendSelf"
p ExtendSelf.singleton_methods      # => [:foo]
p ExtendSelf.singleton_method(:foo) # => singleton_method.rb:19:in `singleton_method': undefined singleton method `foo' for `ExtendSelf' (NameError)
$ docker run --rm -it -v $(pwd):/app -w /app rubylang/ruby:master-nightly-jammy
Unable to find image 'rubylang/ruby:master-nightly-jammy' locally
master-nightly-jammy: Pulling from rubylang/ruby
...
Digest: sha256:922037b184b897786a26b2460f70a66139f87dce67f20ddf760cd4186790ed9f

root@9807305c322a:/app# ruby -v
ruby 3.4.0dev (2024-07-08T21:43:28Z master e500222de1) [x86_64-linux]

root@9807305c322a:/app# ruby singleton_method.rb
"ruby 3.4.0dev (2024-07-08T21:43:28Z master e500222de1) [x86_64-linux]"
"Klass"
[:foo]
#<Method: Klass.foo() singleton_method.rb:2>
"ExtendSelf"
[:foo]
singleton_method.rb:21:in 'Kernel#singleton_method': undefined singleton method 'foo' for 'ExtendSelf' (NameError)

Updated by jeremyevans0 (Jeremy Evans) 6 months ago

I don't think this is a bug. It does seem inconsistent, but only because the all argument to singleton_methods defaults to true. If you call singleton_methods(false), then you get the behavior you would expect from the method name (only show actual singleton methods, not methods in modules that extend the object).

Updated by matz (Yukihiro Matsumoto) 5 months ago

I think singleton_method should traverse super-classes (as long as they are ICLASS) too. Probably we need to check for compatibility issues.

Matz.

Updated by jeremyevans0 (Jeremy Evans) 3 months ago

I submitted a pull request to implement this: https://github.com/ruby/ruby/pull/11605

In terms of compatibility issues:

  • For singleton classes that prepend a module, and have the method defined in both the singleton class and prepended module, singleton_method now returns the method in the prepended module.

  • Cases where a method is defined in a module prepended to or included in the singleton classes and not in the singleton class itself now result in a Method Object being returned, instead of raising NameError.

Use of singleton_method isn't that common in my experience, so I think we should make the change. There is still time to back it out of 3.4 if it causes issues.

Updated by matz (Yukihiro Matsumoto) 3 months ago

@jeremyevans0 (Jeremy Evans) Thank you. Let us merge the pull-request, and experiment with the preview.

Matz.

Actions #5

Updated by jeremyevans (Jeremy Evans) 3 months ago

  • Status changed from Open to Closed

Applied in changeset git|9986a7c3930437bc9d9b88736c22695585aa6c48.


Make Object#singleton_method return methods in modules included in or prepended to singleton class

To simplify the implementation, this makes Object#singleton_method
call the same method called by Object#method (rb_obj_method), then
check that the returned Method is defined before the superclass of the
object's singleton class. To keep the same error messages, it rescues
exceptions raised by rb_obj_method, and then raises its own exception.

Fixes [Bug #20620]

Actions

Also available in: Atom PDF

Like0
Like1Like0Like0Like0Like0