Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Module#module_eval defines all methods into private visibility #2089

Closed
kachick opened this Issue Dec 8, 2012 · 7 comments

Comments

Projects
None yet
3 participants
Member

kachick commented Dec 8, 2012

SetupCode

Foo = Class.new

Foo.module_eval do
  def func; end
  public   ; def public_func; end
  protected; def protected_func; end
  private  ; def private_func; end
end

foo = Foo.new

MRI

  • ruby 1.8.7 (2012-06-29 patchlevel 370) [i686-darwin11.4.0]
  • ruby 1.9.3p332 (2012-11-15 revision 37660) [x86_64-darwin11.4.2]
foo.func #=> nil
foo.public_func #=> nil
foo.protected_func #=> NoMethodError: protected method `protected_func' called for #<Foo:0x10798a230>
foo.private_func #=> NoMethodError: private method `private_func' called for #<Foo:0x10798a230>

Rubinius

  • rubinius 2.0.0rc1 (1.8.7 5088b79 2012-11-02 JI) [x86_64-apple-darwin11.4.2]
  • rubinius 2.0.0rc1 (1.9.3 5088b79 2012-11-02 JI) [x86_64-apple-darwin11.4.2]
foo.func #=> NoMethodError: private method `func' called on an instance of Foo.
foo.public_func #=> NoMethodError: private method `public_func' called on an instance of Foo.
foo.protected_func #=> NoMethodError: private method `protected_func' called on an instance of Foo.
foo.private_func #=> NoMethodError: private method `private_func' called on an instance of Foo.
Owner

dbussink commented Dec 10, 2012

Hmm, I only see this happening inside IRB, not if I run this as a regular script.

Member

kachick commented Dec 11, 2012

Sorry!
I guess, I tried on the IRB only.
Please replace example below.

Foo = Class.new

eval %q{
  Foo.module_eval do
    def func; __callee__ end
    public   ; def public_func; __callee__ end
    protected; def protected_func; __callee__ end
    private  ; def private_func; __callee__ end
  end
}

foo = Foo.new

p foo.func
p foo.public_func
p foo.protected_func
p foo.private_func

Peeja commented Dec 17, 2012

Here's a slightly more useful version, which rescues the errors so we can see the whole thing run:

Foo = Class.new

eval %q{
  Foo.module_eval do
    def func; __callee__ end
    public   ; def public_func; __callee__ end
    protected; def protected_func; __callee__ end
    private  ; def private_func; __callee__ end
  end
}

foo = Foo.new

def try
  yield
rescue Exception => e
  e
end

p(try { foo.func })
p(try { foo.public_func })
p(try { foo.protected_func })
p(try { foo.private_func })

Peeja commented Dec 17, 2012

On latest master, 7d908da:

peeja:rubinius/ (master✗) $ bin/ruby issue_2089.rb
#<NoMethodError: private method `func' called on an instance of Foo.>
#<NoMethodError: private method `public_func' called on an instance of Foo.>
#<NoMethodError: private method `protected_func' called on an instance of Foo.>
#<NoMethodError: private method `private_func' called on an instance of Foo.>
Member

kachick commented Dec 17, 2012

@Peeja Looks good! Thanks :)

Peeja commented Dec 17, 2012

Same result in both 1.8 and 1.9 modes.

It's not clear to me why using #eval is necessary, but it is:

# issue_2089_wo_eval.rb
Foo = Class.new

# eval %q{
  Foo.module_eval do
    def func; __callee__ end
    public   ; def public_func; __callee__ end
    protected; def protected_func; __callee__ end
    private  ; def private_func; __callee__ end
  end
# }

foo = Foo.new

def try
  yield
rescue Exception => e
  e
end

p(try { foo.func })
p(try { foo.public_func })
p(try { foo.protected_func })
p(try { foo.private_func })
peeja:rubinius/ (master✗) $ bin/ruby -X19 issue_2089_wo_eval.rb
:func
:public_func
#<NoMethodError: protected method `protected_func' called on an instance of Foo.>
#<NoMethodError: private method `private_func' called on an instance of Foo.>

dbussink added a commit that referenced this issue May 3, 2013

Setup top level visibility and script attributes
This creates a tag for a call frame indicating it's a top level script
or the top level for visibility checks. For this we also support a
boolean value on call_under definining whether to open a new visibility
top level or not.

This can be used to fix visibility checks and have methods defined
inside blocks have the proper visibility in Rubinius.

Fixes #2316 and #2089
Owner

dbussink commented May 23, 2013

This issue should have been fixed.

@dbussink dbussink closed this May 23, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment