[ruby-core:126066] [Ruby Misc#22192] Clarify the scope of default visibility changed inside a block
Issue #22192 has been reported by shugo (Shugo Maeda). ---------------------------------------- Misc #22192: Clarify the scope of default visibility changed inside a block https://bugs.ruby-lang.org/issues/22192 * Author: shugo (Shugo Maeda) * Status: Assigned * Assignee: matz (Yukihiro Matsumoto) ---------------------------------------- `private` etc. called with no arguments inside a block changes the default visibility of the enclosing lexical scope, and the change survives the block: ```ruby class C %i[foo bar].each do |name| private define_method(name) { } end def afterwards; end # also private end C.private_method_defined?(:foo) #=> true C.private_method_defined?(:afterwards) #=> true ``` When multiple Procs share the same lexical scope, `private` in a Proc affects all Procs: ```ruby class Host SET_PRIVATE = proc { private } DEFINE = proc { def probe; end } end Host::SET_PRIVATE.call Host::DEFINE.call Host.private_method_defined?(:probe) #=> true ``` Neither CRuby nor ruby/spec has corresponding tests. I assume this is intentional, but am I correct? It seems that the visibility change is effective only within the block on JRuby, so I'd like to clarify this. -- https://bugs.ruby-lang.org/
Issue #22192 has been updated by shugo (Shugo Maeda). I checked the behavior of past versions with all-ruby: ``` $ docker run -it --rm rubylang/all-ruby ./all-ruby -e 'class C; [1].each { private; def foo; end }; def afterwards; end; end; p [C.private_instance_methods(false).sort, C.public_instance_methods(false).sort]' ... ruby-1.1b9_06 -e:1: undefined method `public_instance_methods' for C (NameError) exit 1 ruby-1.1b9_07 [["afterwards", "foo"], []] ... ruby-1.6.8 [["afterwards", "foo"], []] ruby-1.8.0 [["foo"], ["afterwards"]] ... ruby-1.8.7-p374 [["foo"], ["afterwards"]] ruby-1.9.0-0 [[:afterwards, :foo], []] ... ruby-4.0.5 [[:afterwards, :foo], []] ``` | Versions | Behavior | |-----------------|------------------------------------------------| | 1.1b9 - 1.6.8 | same as the current behavior | | 1.8.0 - 1.8.7 | same as JRuby (reverted at the end of a block) | | 1.9.0 - 3.3 | same as the current behavior | ---------------------------------------- Misc #22192: Clarify the scope of default visibility changed inside a block https://bugs.ruby-lang.org/issues/22192#change-118067 * Author: shugo (Shugo Maeda) * Status: Assigned * Assignee: matz (Yukihiro Matsumoto) ---------------------------------------- `private` etc. called with no arguments inside a block changes the default visibility of the enclosing lexical scope, and the change survives the block: ```ruby class C %i[foo bar].each do |name| private define_method(name) { } end def afterwards; end # also private end C.private_method_defined?(:foo) #=> true C.private_method_defined?(:afterwards) #=> true ``` When multiple Procs share the same lexical scope, `private` in a Proc affects all Procs: ```ruby class Host SET_PRIVATE = proc { private } DEFINE = proc { def probe; end } end Host::SET_PRIVATE.call Host::DEFINE.call Host.private_method_defined?(:probe) #=> true ``` Neither CRuby nor ruby/spec has corresponding tests. I assume this is intentional, but am I correct? It seems that the visibility change is effective only within the block on JRuby, so I'd like to clarify this. -- https://bugs.ruby-lang.org/
Issue #22192 has been updated by shugo (Shugo Maeda). ISO/IEC 30170 also specifies that the default visibility change survives the block (a block call pushes only local variable bindings; the default visibility stack is untouched). ---------------------------------------- Misc #22192: Clarify the scope of default visibility changed inside a block https://bugs.ruby-lang.org/issues/22192#change-118069 * Author: shugo (Shugo Maeda) * Status: Assigned * Assignee: matz (Yukihiro Matsumoto) ---------------------------------------- `private` etc. called with no arguments inside a block changes the default visibility of the enclosing lexical scope, and the change survives the block: ```ruby class C %i[foo bar].each do |name| private define_method(name) { } end def afterwards; end # also private end C.private_method_defined?(:foo) #=> true C.private_method_defined?(:afterwards) #=> true ``` When multiple Procs share the same lexical scope, `private` in a Proc affects all Procs: ```ruby class Host SET_PRIVATE = proc { private } DEFINE = proc { def probe; end } end Host::SET_PRIVATE.call Host::DEFINE.call Host.private_method_defined?(:probe) #=> true ``` Neither CRuby nor ruby/spec has corresponding tests. I assume this is intentional, but am I correct? It seems that the visibility change is effective only within the block on JRuby, so I'd like to clarify this. -- https://bugs.ruby-lang.org/
Issue #22192 has been updated by Eregon (Benoit Daloze). TruffleRuby also behaves like CRuby here. My understanding is method visibility is some state that only exists in methods and not in blocks (same as `$~`, etc). There should already be some ruby/spec for that. ---------------------------------------- Misc #22192: Clarify the scope of default visibility changed inside a block https://bugs.ruby-lang.org/issues/22192#change-118079 * Author: shugo (Shugo Maeda) * Status: Assigned * Assignee: matz (Yukihiro Matsumoto) ---------------------------------------- `private` etc. called with no arguments inside a block changes the default visibility of the enclosing lexical scope, and the change survives the block: ```ruby class C %i[foo bar].each do |name| private define_method(name) { } end def afterwards; end # also private end C.private_method_defined?(:foo) #=> true C.private_method_defined?(:afterwards) #=> true ``` When multiple Procs share the same lexical scope, `private` in a Proc affects all Procs: ```ruby class Host SET_PRIVATE = proc { private } DEFINE = proc { def probe; end } end Host::SET_PRIVATE.call Host::DEFINE.call Host.private_method_defined?(:probe) #=> true ``` Neither CRuby nor ruby/spec has corresponding tests. I assume this is intentional, but am I correct? It seems that the visibility change is effective only within the block on JRuby, so I'd like to clarify this. -- https://bugs.ruby-lang.org/
Issue #22192 has been updated by shugo (Shugo Maeda). Status changed from Assigned to Closed Eregon (Benoit Daloze) wrote in #note-3:
TruffleRuby also behaves like CRuby here. My understanding is method visibility is some state that only exists in methods and not in blocks (same as `$~`, etc).
There should already be some ruby/spec for that.
Thank you, I've found the following spec in spec/ruby/core/module/shared/set_visibility.rb: ```ruby it "sets the visibility outside the closure" do visibility = @method mod = Module.new { 1.times { send visibility } def test1() end } mod.send(:"#{@method}_instance_methods", false).should.include?(:test1) end ``` JRuby is aware of the incompatibility: it tags this spec as failing for Module#private and Module#protected. So' I'm closing this issue. ---------------------------------------- Misc #22192: Clarify the scope of default visibility changed inside a block https://bugs.ruby-lang.org/issues/22192#change-118080 * Author: shugo (Shugo Maeda) * Status: Closed * Assignee: matz (Yukihiro Matsumoto) ---------------------------------------- `private` etc. called with no arguments inside a block changes the default visibility of the enclosing lexical scope, and the change survives the block: ```ruby class C %i[foo bar].each do |name| private define_method(name) { } end def afterwards; end # also private end C.private_method_defined?(:foo) #=> true C.private_method_defined?(:afterwards) #=> true ``` When multiple Procs share the same lexical scope, `private` in a Proc affects all Procs: ```ruby class Host SET_PRIVATE = proc { private } DEFINE = proc { def probe; end } end Host::SET_PRIVATE.call Host::DEFINE.call Host.private_method_defined?(:probe) #=> true ``` Neither CRuby nor ruby/spec has corresponding tests. I assume this is intentional, but am I correct? It seems that the visibility change is effective only within the block on JRuby, so I'd like to clarify this. -- https://bugs.ruby-lang.org/
participants (2)
-
Eregon (Benoit Daloze) -
shugo (Shugo Maeda)