From: "jeremyevans0 (Jeremy Evans)" Date: 2022-08-10T20:32:11+00:00 Subject: [ruby-core:109471] [Ruby master Bug#18435] Calling `protected` on ancestor method changes result of `instance_methods(false)` Issue #18435 has been updated by jeremyevans0 (Jeremy Evans). Backport changed from 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN to 2.6: DONTNEED, 2.7: DONTNEED, 3.0: DONTNEED, 3.1: REQUIRED Status changed from Open to Closed matz (Yukihiro Matsumoto) wrote in #note-11: > I thought it was OK to accept this behavior, but it caused issues like #18729 and #18751. At the time of the decision, I haven't noticed those corner cases. Although it has already been shipped with 3.1, I proposed to revert this change. I estimate the impact of reverting incompatibility is minimal. I committed the revert at commit:ff42e2359bdbf37e1721a82b4cfd95b31f494f3f. My understanding is that @matz would like this backported to Ruby 3.1, so marking for backport. > Instead of changing old behavior, the documentation of `instance_methods(false)` should be updated to explain why `method1` is included in the above example (visibility changes or making aliases are considered as *definition* by `instance_methods`). I'll see if I can update the documentation for `instance_methods` to explain this. ---------------------------------------- Bug #18435: Calling `protected` on ancestor method changes result of `instance_methods(false)` https://bugs.ruby-lang.org/issues/18435#change-98633 * Author: ufuk (Ufuk Kayserilioglu) * Status: Closed * Priority: Normal * ruby -v: ruby 2.7.5p203 (2021-11-24 revision f69aeb8314) [x86_64-darwin20] * Backport: 2.6: DONTNEED, 2.7: DONTNEED, 3.0: DONTNEED, 3.1: REQUIRED ---------------------------------------- As documented `instance_methods(false)` works as follows: ```ruby module A def method1() end end class B include A def method2() end end p B.instance_methods(false) #=> [:method2] ``` However, calling `protected` on the method defined by `A`, unexpectedly changes the result of `instance_methods(false)` on `B`, even though the owner of the method is still `A`: ```ruby module A def method1() end end class B include A protected :method1 def method2() end end p B.instance_methods(false) #=> [:method1, :method2] p B.instance_method(:method1).owner #=> A ``` In contrast, calling `private` or `public` on the same method does not cause any changes on the result of `B.instance_methods(false)`. This feels like a bug in the implementation of `instance_methods(false)`, but, if it is by design, it should at least be documented on `Module#instance_methods`. This reproduction script gives the same output all the way from Ruby 2.0 up to Ruby-HEAD: https://wandbox.org/permlink/LqbXMBTYxURRZmDz -- https://bugs.ruby-lang.org/ Unsubscribe: