[ruby-core:94336] [Ruby master Bug#16100] Visibility modifiers don't call super correctly when overridden in alternative ways
From:
merch-redmine@...
Date:
2019-08-14 03:50:24 UTC
List:
ruby-core #94336
Issue #16100 has been updated by jeremyevans0 (Jeremy Evans).
This issue is related to scope. In all cases, your call to `private` is calling ruby's default behavior. However, when you call `super`, it just changes the scope of the `super` call to `private`. The scope of your overridden `private` method in your `explicit` example just happens to be the same as when you call `private` on the next line, so you get the same behavior.
Here's an example that shows this in action. Note that `C.private` is called outside the scope of `class C`, but the effect takes place inside the scope of `class C`.
```ruby
t = Thread.new do
class C
def self.private(*); super; end
sleep 0.5
def private_method; end
end
end
sleep 0.25
C.private
t.join
C.private_instance_methods(false)
# => [:private_method]
```
I don't think this is a bug, I think this is an implementation detail. Hopefully another committer can confirm that.
This does make it a bad idea to override `private`/`protected`/`public`/`module_function`, since normal Ruby code cannot replicate their affect on scopes.
----------------------------------------
Bug #16100: Visibility modifiers don't call super correctly when overridden in alternative ways
https://bugs.ruby-lang.org/issues/16100#change-80733
* Author: prebsch (Patrick Rebsch)
* Status: Open
* Priority: Normal
* Assignee:
* Target version:
* ruby -v: ruby 2.7.0dev (2019-08-14) [x86_64-darwin18]
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN
----------------------------------------
It seems that the method visibility modifiers don't call `super` correctly when they are overridden in certain ways. I expected the following examples to all behave the same since they are all being defined on the singleton class, but only the first operates correctly presumably because it is explicitly defined on the singleton class. I've reproduced this behavior with `2.7.0`, `2.6.3`, and `2.5.5`.
``` ruby
def test_visibility(description, klass)
puts "Case: #{ description }"
puts " #=> #{ klass.private_instance_methods.include?(:private_method) }"
puts
end
test_visibility('explicit', Class.new {
def self.private(*); super; end
private; def private_method; end
})
test_visibility('opened singleton', Class.new {
class << self
def private(*); super; end
end
private; def private_method; end
})
test_visibility('include/prepend to singleton', Class.new {
module M
def private(*); super; end
end
singleton_class.prepend(M)
private; def private_method; end
})
```
```
Case: explicit
#=> true
Case: opened singleton
#=> false
Case: include/prepend to singleton
#=> false
```
--
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>