{"action":"created","issue":{"url":"https://api.github.com/repos/jruby/jruby/issues/540","labels_url":"https://api.github.com/repos/jruby/jruby/issues/540/labels{/name}","comments_url":"https://api.github.com/repos/jruby/jruby/issues/540/comments","events_url":"https://api.github.com/repos/jruby/jruby/issues/540/events","html_url":"https://github.com/jruby/jruby/issues/540","id":11137653,"number":540,"title":"Inconsistency between MRI and JRuby when private methods are called and method_missing is present","user":{"login":"jvshahid","id":297621,"avatar_url":"https://avatars.githubusercontent.com/u/297621?v=3","gravatar_id":"","url":"https://api.github.com/users/jvshahid","html_url":"https://github.com/jvshahid","followers_url":"https://api.github.com/users/jvshahid/followers","following_url":"https://api.github.com/users/jvshahid/following{/other_user}","gists_url":"https://api.github.com/users/jvshahid/gists{/gist_id}","starred_url":"https://api.github.com/users/jvshahid/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jvshahid/subscriptions","organizations_url":"https://api.github.com/users/jvshahid/orgs","repos_url":"https://api.github.com/users/jvshahid/repos","events_url":"https://api.github.com/users/jvshahid/events{/privacy}","received_events_url":"https://api.github.com/users/jvshahid/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/jruby/jruby/labels/core","name":"core","color":"02e10c"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":3,"created_at":"2013-02-19T01:10:51Z","updated_at":"2015-05-06T00:28:05Z","closed_at":null,"body":"```ruby\r\n#!/usr/bin/env ruby\r\nclass Foo\r\n  def method_missing name\r\n    super\r\n  end\r\n  private\r\n  def foo\r\n    'foo'\r\n  end\r\nend\r\n\r\nFoo.new.foo\r\n```\r\n\r\nthis code will generate an exception with different messages under MRI and JRuby.\r\n\r\nMRI:\r\n```\r\n/home/jvshahid/foo.rb:4:in `method_missing': private method `foo' called for #<Foo:0x00000001eed260> (NoMethodError)\r\n\tfrom /home/jvshahid/foo.rb:14:in `<main>'\r\n```\r\n\r\nJRuby:\r\n```\r\nNoMethodError: undefined method `foo' for #<Foo:0x64e137c0>\r\n  method_missing at org/jruby/RubyBasicObject.java:1652\r\n  method_missing at /home/jvshahid/foo.rb:4\r\n          (root) at /home/jvshahid/foo.rb:12\r\n```\r\n\r\nNotice that JRuby's exception doesn't mention that the method we're trying to access is private. This cause three specs to fail in rails since unfortunately they rely on the wording of the exception."},"comment":{"url":"https://api.github.com/repos/jruby/jruby/issues/comments/99271336","html_url":"https://github.com/jruby/jruby/issues/540#issuecomment-99271336","issue_url":"https://api.github.com/repos/jruby/jruby/issues/540","id":99271336,"user":{"login":"headius","id":10135,"avatar_url":"https://avatars.githubusercontent.com/u/10135?v=3","gravatar_id":"","url":"https://api.github.com/users/headius","html_url":"https://github.com/headius","followers_url":"https://api.github.com/users/headius/followers","following_url":"https://api.github.com/users/headius/following{/other_user}","gists_url":"https://api.github.com/users/headius/gists{/gist_id}","starred_url":"https://api.github.com/users/headius/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/headius/subscriptions","organizations_url":"https://api.github.com/users/headius/orgs","repos_url":"https://api.github.com/users/headius/repos","events_url":"https://api.github.com/users/headius/events{/privacy}","received_events_url":"https://api.github.com/users/headius/received_events","type":"User","site_admin":false},"created_at":"2015-05-06T00:28:05Z","updated_at":"2015-05-06T00:28:05Z","body":"Hmm...this is a very unusual case.\r\n\r\nIn MRI, it seems that the call through user-defined method_missing keeps some state around indicating the original reason for the method_missing call. This data is not visible to users except when that method_missing calls super.\r\n\r\nIn JRuby, once method_missing has dispatched, we do not track the original cause; either an error will be thrown, or we'll go back into userland for the user to handle it.\r\n\r\nIt gets even weirder (to me, at least). The error message is preserved:\r\n\r\n* when there are intervening calls before `super`,\r\n* when the super happens in a block, even if method_missing has returned,\r\n```ruby\r\n  def method_missing name\r\n    ->{super}\r\n  end\r\n```\r\n* and when there are multiple levels of method_missing calling super\r\n\r\nGiven that there can be many changes to the call stack and the cause is still preserved, it seems likely that MRI has special call logic for method_missing that carries this information along."}}