From: "jeremyevans0 (Jeremy Evans) via ruby-core" <ruby-core@...> Date: 2025-02-09T02:45:24+00:00 Subject: [ruby-core:120920] [Ruby master Bug#21125] Kernel is called first Issue #21125 has been updated by jeremyevans0 (Jeremy Evans). Assignee set to tenderlovemaking (Aaron Patterson) The reason this works in Ruby 3.3 and below is that `system` is a private method and not a public method, and calls to private methods where the receiver is not `self` call `method_missing`. `raw.system` is a method call where the receiver is not `self`, but `Kernel#system` is a private method, so this should be calling `method_missing`. The fact that `method_missing` is not called in Ruby 3.4 is a bug. I've determined the bug is in generic argument forwarding. If you switch `...` (generic argument forwarding) to `*, **, &` (anonymous splat usage), things work correctly. Assigning to @tenderlovemaking. ---------------------------------------- Bug #21125: Kernel is called first https://bugs.ruby-lang.org/issues/21125#change-111802 * Author: mikik0 (Hashino Mikiko) * Status: Open * Assignee: tenderlovemaking (Aaron Patterson) * ruby -v: ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [arm64-darwin24] * Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- Kernel#system is being called when there is a column or method name named system. The other methods of Kernel reproduce the problem. Ex.Rand returns a random value, and exit terminates the program. ## Reproducible script: ``` ruby class ObjectifiedHash def initialize(hash) @hash = hash end private attr_reader :hash def method_missing(method_name, *args, &block) if hash.key?(method_name.to_sym) hash[method_name.to_sym] else super end end def respond_to_missing?(method_name, include_private = false) hash.key?(method_name.to_sym) || super end end class Foo def system(...) # Kernel#system is called raw.system(...) # (...) passes if there is no # raw.system end def initialize(raw) @raw = raw end def get_system system end private attr_reader :raw end class Test def self.run obj = ObjectifiedHash.new({ system: 'system' }) foo = Foo.new(obj) # foo.system would pass. # After executing foo.system, hoge.get_system also passes. # p foo.system p foo.get_system end end Test.run ``` ## Execution Results ``` shell hoge.rb:26:in 'Kernel#system': wrong number of arguments (given 0, expected 1+) (ArgumentError) raw.system(...) ^^^ from ruby.rb:26:in 'Foo#system' from ruby.rb:36:in 'Foo#get_system' from ruby.rb:54:in 'Test.run' from ruby.rb:58:in '<main>' ``` ## Expected results ``` shell "system" ``` PR that may be relevant: https://github.com/ruby/ruby/pull/11028 -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/