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) 10 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) 10 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) 8 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) 7 months ago
@jeremyevans0 (Jeremy Evans) Thank you. Let us merge the pull-request, and experiment with the preview.
Matz.
Updated by jeremyevans (Jeremy Evans) 7 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]