NameError is thrown by method_missing when using self #872

Closed
andrenpaes opened this Issue Jul 10, 2013 · 4 comments

Projects

None yet

3 participants

@andrenpaes

The method_missing method is throwing the NameError exception instead of NoMethodError when using self as the message receiver.

Here's an example

class Bug
  def method_missing(meth, *args, &block)
    super
  rescue NoMethodError
    puts "Catched Error!"
    args.first
  end

  def set_bug_type
    self.bug_type = 2
  end
end

Bug.new.bug_type = 1
Bug.new.set_bug_type

The expected output is (that's what I get in MRI 1.9.x):

Catched Error!
Catched Error!

The actual output is:

Catched Error!
NameError: undefined local variable or method `bug_type=' for #<Bug:0x37867b45>
  method_missing at org/jruby/RubyBasicObject.java:1670
  method_missing at app/models/bug.rb:5
    set_bug_type at app/models/bug.rb:12
          (root) at app/models/bug.rb:17

This is happening using both JRuby 1.7.3 and 1.7.4.
The platform is a mac running MacOS X 10.8.4.

@BanzaiMan
Member

This looks like a duplicate of #540. Please close this if you agree.

@andrenpaes

Seems like different issues to me.

@headius
Member
headius commented Jul 11, 2013

The relationship between NoMethodError and NameError is a little weird. In general I'd recommend sticking to NameError for these things, since depending on how something's parsed it might be one or the other.

That said, this appears to be specific to attribute assignment (and possible access), since we do the right thing for normal calls:

system ~/projects/jruby $ jruby -e "self.foo = 1"
NameError: undefined local variable or method `foo=' for main:Object
  (root) at -e:1

system ~/projects/jruby $ jruby -e "self.foo(1)"
NoMethodError: undefined method `foo' for main:Object
  (root) at -e:1

Will investigate.

@headius headius added a commit that closed this issue Jul 11, 2013
@headius headius Changes for self-targeted attr assignment m_m (fixes #872).
* Use functional rather than variable site for self.x=.
* Statically choose site type (functional/normal) in interpreter
  too (already in compiler).
5e97e4e
@headius headius closed this in 5e97e4e Jul 11, 2013
@headius
Member
headius commented Jul 11, 2013

Fixed! We appear to match MRI for a full range of call types now:

system ~/projects/jruby $ jruby -X-C -e 'def foo=(a); end; a = self; a.foo = 1'
NoMethodError: private method `foo=' called for main:Object
  (root) at -e:1

system ~/projects/jruby $ jruby -X-C -e 'def foo=(a); end; a = self; a.foo = 1'
NoMethodError: private method `foo=' called for main:Object
  (root) at -e:1

system ~/projects/jruby $ jruby -X-C -e 'def foo=(a); end; self.foo = 1'

system ~/projects/jruby $ jruby -X+C -e 'def foo=(a); end; a = self; a.foo = 1'
NoMethodError: private method `foo=' called for main:Object
  (root) at -e:1

system ~/projects/jruby $ jruby -X+C -e 'def foo=(a); end; self.foo = 1'

system ~/projects/jruby $ ruby2.0.0 -e 'def foo=(a); end; a = self; a.foo = 1'
-e:1:in `<main>': private method `foo=' called for main:Object (NoMethodError)

system ~/projects/jruby $ ruby2.0.0 -e 'def foo=(a); end; self.foo = 1'

system ~/projects/jruby $ jruby -X-C -e 'self.foo = 1'
NoMethodError: undefined method `foo=' for main:Object
  (root) at -e:1

system ~/projects/jruby $ jruby -X-C -e 'self.foo(1)'
NoMethodError: undefined method `foo' for main:Object
  (root) at -e:1

system ~/projects/jruby $ jruby -X-C -e 'foo(1)'
NoMethodError: undefined method `foo' for main:Object
  (root) at -e:1

system ~/projects/jruby $ jruby -X-C -e 'foo'
NameError: undefined local variable or method `foo' for main:Object
  (root) at -e:1

system ~/projects/jruby $ jruby -X+C -e 'self.foo = 1'
NoMethodError: undefined method `foo=' for main:Object
  (root) at -e:1

system ~/projects/jruby $ jruby -X+C -e 'self.foo(1)'
NoMethodError: undefined method `foo' for main:Object
  (root) at -e:1

system ~/projects/jruby $ jruby -X+C -e 'foo(1)'
NoMethodError: undefined method `foo' for main:Object
  (root) at -e:1

system ~/projects/jruby $ jruby -X+C -e 'foo'
NameError: undefined local variable or method `foo' for main:Object
  (root) at -e:1

system ~/projects/jruby $ ruby2.0.0 -e 'self.foo = 1'
-e:1:in `<main>': undefined method `foo=' for main:Object (NoMethodError)

system ~/projects/jruby $ ruby2.0.0 -e 'self.foo(1)'
-e:1:in `<main>': undefined method `foo' for main:Object (NoMethodError)

system ~/projects/jruby $ ruby2.0.0 -e 'foo(1)'
-e:1:in `<main>': undefined method `foo' for main:Object (NoMethodError)

system ~/projects/jruby $ ruby2.0.0 -e 'foo'
-e:1:in `<main>': undefined local variable or method `foo' for main:Object (NameError)

Could you perhaps turn these into a RubySpec (https://github.com/rubyspec/rubyspec) or JRuby regression spec (under spec/regression in https://github.com/jruby/jruby)?

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