Bug #20620
closedsingleton_method undefined for module using "extend self"
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 raisingNameError
.
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.
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]