From: "shugo (Shugo Maeda) via ruby-core" Date: 2026-09-10T07:43:55+00:00 Subject: [ruby-core:126637] [Ruby Bug#22276] alias in a module falls back to Object even in classes not inheriting from Object Issue #22276 has been updated by shugo (Shugo Maeda). matz (Yukihiro Matsumoto) wrote in #note-3: > So I'd like to remove this special treatment instead of resolving the alias at call time (option 2). A module should be able to alias only its own methods and its ancestors' methods, and aliasing any other method should raise `NameError`. This is a breaking change, but I agree it is the best behavior. > I leave the migration path (e.g. a deprecation warning before raising `NameError`) to the implementer. How about the following schedule? 4.1: Verbose-mode deprecation warning 4.2: Non-verbose-mode deprecation warning 4.3: Removal of the special fallback to Object (raise `NameError`) Unlike ruby2_keywords (#22205), I think a documentation-only phase is not needed here, because the migration (e.g., replacing the alias with a method definition that delegates to another method) works the same on all Ruby versions. ---------------------------------------- Bug #22276: alias in a module falls back to Object even in classes not inheriting from Object https://bugs.ruby-lang.org/issues/22276#change-118892 * Author: shugo (Shugo Maeda) * Status: Open * ruby -v: ruby 4.1.0dev (2026-08-28T07:43:16Z master 69b49ac7ae) +PRISM [x86_64-linux] * Backport: 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- When `alias` (or `alias_method`) is used in a module and the method is not found in the module, `alias` searches the method from `Object`. So a module can alias a method of `Kernel` or `Object`, and the alias works even if the module is later included in a class that does not have `Object` and `Kernel` as ancestors: ```ruby module M alias foo puts public :foo end class X < BasicObject include ::M end X.new.foo("hello") #=> hello ``` `X` does not include `Kernel`, but `X.new.foo` calls `Kernel#puts`. This fallback comes from Ruby 1.8, where `Object` was the root class, so every class that includes a module always had `Object` and `Kernel` as ancestors. Since Ruby 1.9 introduced `BasicObject`, this is no longer true, but the fallback is unchanged. As discussed in #22273, a module should be able to alias only its own methods and its ancestors' methods, and `Object` is not an ancestor of a module. This behavior is intentional in the current implementation. There are tests for it (`test_alias_in_module` in test/ruby/test_alias.rb for #9663, and "accesses a method defined on Object from Kernel" in spec/ruby/core/module/alias_method_spec.rb), and the documentation of `Module#alias_method` has an example `module Mod; alias_method :orig_exit, :exit; end`. So code like `module M; alias orig_to_s to_s; end` exists, and simply raising `NameError` will break it. Possible fixes: 1. Remove the fallback and raise `NameError`. This breaks existing code. 2. Do not resolve the method at alias time. Instead, resolve it at call time from the ancestors of the receiver's class, like ZSUPER methods. Existing code that includes the module in a subclass of `Object` keeps working, and `X.new.foo` above raises `NoMethodError`. 3. Keep the current behavior and document it. I think 2 is the best choice for compatibility. -- 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/