[ruby-core:125553] [Ruby Bug#22076] defined? returns nil for protected methods defined in a module even when callable
Issue #22076 has been reported by sampokuokkanen (Sampo Kuokkanen). ---------------------------------------- Bug #22076: defined? returns nil for protected methods defined in a module even when callable https://bugs.ruby-lang.org/issues/22076 * Author: sampokuokkanen (Sampo Kuokkanen) * Status: Open * Backport: 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- Filing this to confirm whether defined? should return "method" here (matching the call check), or whether the current nil behavior is intentional. ### Summary `defined?` returns `nil` for a protected method defined in a module, even when the same call succeeds. For a protected method defined in a class, `defined?` and the call agree. ### Reproduction ~~~ruby module Mix def secret; 42; end protected :secret end class A; include Mix; end class B include Mix def call_it(other) = other.secret def defined_it(other) = defined?(other.secret) end p B.new.call_it(A.new) # => 42 p B.new.defined_it(A.new) # => nil (expected "method") ~~~ The class-defined version returns `"method"` for the same shape: ~~~ruby class Base def secret; 42; end protected :secret end class A < Base; end class B < Base def defined_it(other) = defined?(other.secret) end p B.new.defined_it(A.new) # => "method" ~~~ ### Fix Use `rb_callable_method_entry_with_refinements` and the existing `vm_defined_class_for_protected_call` helper. Patch with test: (will update soon) ## Environment - MacOS Tahoe 26.2 - Ruby master (HEAD) - ruby 4.0.1 -- https://bugs.ruby-lang.org/
Issue #22076 has been updated by nobu (Nobuyoshi Nakada). Backport changed from 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN to 3.3: REQUIRED, 3.4: REQUIRED, 4.0: REQUIRED The expectation and the fix seem reasonable both. ---------------------------------------- Bug #22076: defined? returns nil for protected methods defined in a module even when callable https://bugs.ruby-lang.org/issues/22076#change-117380 * Author: sampokuokkanen (Sampo Kuokkanen) * Status: Open * ruby -v: ruby 4.0.1 (2026-01-13 revision e04267a14b) +PRISM [arm64-darwin25] * Backport: 3.3: REQUIRED, 3.4: REQUIRED, 4.0: REQUIRED ---------------------------------------- Filing this to confirm whether defined? should return "method" here (matching the call check), or whether the current nil behavior is intentional. ### Summary `defined?` returns `nil` for a protected method defined in a module, even when the same call succeeds. For a protected method defined in a class, `defined?` and the call agree. ### Reproduction ~~~ruby module Mix def secret; 42; end protected :secret end class A; include Mix; end class B include Mix def call_it(other) = other.secret def defined_it(other) = defined?(other.secret) end p B.new.call_it(A.new) # => 42 p B.new.defined_it(A.new) # => nil (expected "method") ~~~ The class-defined version returns `"method"` for the same shape: ~~~ruby class Base def secret; 42; end protected :secret end class A < Base; end class B < Base def defined_it(other) = defined?(other.secret) end p B.new.defined_it(A.new) # => "method" ~~~ ### Fix Use `rb_callable_method_entry_with_refinements` and the existing `vm_defined_class_for_protected_call` helper. Patch with test: https://github.com/ruby/ruby/pull/17069 ## Environment - MacOS Tahoe 26.2 - Ruby master (HEAD) - ruby 4.0.1 -- https://bugs.ruby-lang.org/
Issue #22076 has been updated by k0kubun (Takashi Kokubun). Backport changed from 3.3: REQUIRED, 3.4: REQUIRED, 4.0: REQUIRED to 3.3: REQUIRED, 3.4: REQUIRED, 4.0: DONE ruby_4_0 commit:c5c292762e0a06f96859738bbdd974cade9f2664. ---------------------------------------- Bug #22076: defined? returns nil for protected methods defined in a module even when callable https://bugs.ruby-lang.org/issues/22076#change-117389 * Author: sampokuokkanen (Sampo Kuokkanen) * Status: Closed * ruby -v: ruby 4.0.1 (2026-01-13 revision e04267a14b) +PRISM [arm64-darwin25] * Backport: 3.3: REQUIRED, 3.4: REQUIRED, 4.0: DONE ---------------------------------------- Filing this to confirm whether defined? should return "method" here (matching the call check), or whether the current nil behavior is intentional. ### Summary `defined?` returns `nil` for a protected method defined in a module, even when the same call succeeds. For a protected method defined in a class, `defined?` and the call agree. ### Reproduction ~~~ruby module Mix def secret; 42; end protected :secret end class A; include Mix; end class B include Mix def call_it(other) = other.secret def defined_it(other) = defined?(other.secret) end p B.new.call_it(A.new) # => 42 p B.new.defined_it(A.new) # => nil (expected "method") ~~~ The class-defined version returns `"method"` for the same shape: ~~~ruby class Base def secret; 42; end protected :secret end class A < Base; end class B < Base def defined_it(other) = defined?(other.secret) end p B.new.defined_it(A.new) # => "method" ~~~ ### Fix Use `rb_callable_method_entry_with_refinements` and the existing `vm_defined_class_for_protected_call` helper. Patch with test: https://github.com/ruby/ruby/pull/17069 ## Environment - MacOS Tahoe 26.2 - Ruby master (HEAD) - ruby 4.0.1 -- https://bugs.ruby-lang.org/
participants (3)
-
k0kubun (Takashi Kokubun) -
nobu (Nobuyoshi Nakada) -
sampokuokkanen (Sampo Kuokkanen)