From: Yehuda Katz Date: 2009-12-19T09:26:22+09:00 Subject: [ruby-core:27219] [Bug #2494] Bug in th->method_missing_reason produces strange behavior with coercion Bug #2494: Bug in th->method_missing_reason produces strange behavior with coercion http://redmine.ruby-lang.org/issues/show/2494 Author: Yehuda Katz Status: Open, Priority: High Category: core ruby -v: ruby 1.9.2dev (2009-12-18 trunk 26119) [x86_64-darwin10.2.0] Currently, Ruby uses check_funcall as part of its coercion behavior. That function calls check_funcall_exec, which calls method_missing without first setting th->method_missing_reason. As a result, the internal method_missing raises a NameError or NoMethodError based upon the LAST call to method_missing. If the last call was a vcall, the internal method_missing raises a NameError, which is *not* rescued by check_funcall. You can see this bug in the following code: class Blah def setup_vcall # Force th->method_missing_reason to be set to a vcall not_there rescue nil end def method_missing(meth, *args) puts "trying #{meth}" super end end b = Blah.new b.setup_vcall p [b].flatten The patch is at http://gist.github.com/raw/259216/0a5749ab27a4bf7510cccb5cd52b793a82dcef1a/gistfile2.diff. This patch sets th->method_missing_reason, which will cause the internal call to method_missing to *always* raise a NoMethodError, which will be correctly rescued by check_funcall. This bug caused problems in ActiveSupport (http://github.com/rails/rails/blob/master/activesupport/lib/active_support/whiny_nil.rb#L47-48), which we resolved by explicitly looking for :to_ary and raising NoMethodError. This should not have been needed, because calling super in method_missing would have raised NoMethodError if th->method_missing_reason was set correctly. ---------------------------------------- http://redmine.ruby-lang.org