Bug #2346
closedArray(nil) fails after redefining NilClass.method_missing to throw NoMethodError
Description
=begin
Given the following script:
print "Array(nil) => ", Array(nil).inspect, "\n"
print "Array.try_convert(nil) => ", Array.try_convert(nil).inspect, "\n"
class NilClass
private
def method_missing(method, *args, &block)
raise NoMethodError
end
end
print "Array(nil) => ", Array(nil).inspect, "\n"
print "Array.try_convert(nil) => ", Array.try_convert(nil).inspect, "\n"
Ruby 1.9.2dev returns this:
$ ruby -v
ruby 1.9.2dev (2009-11-08 trunk 25690) [i386-mswin32_90]
$ ruby nil_ary.rb
Array(nil) => []
Array.try_convert(nil) => nil
nil_ary.rb:6:in method_missing': NoMethodError (NoMethodError) from nil_ary.rb:9:in
Array'
from nil_ary.rb:9:in `'
while for Ruby 1.8.8dev it is ok:
$ ruby -v
ruby 1.8.8dev (2009-10-31 revision 25583) [i386-mswin32_90]
$ ruby nil_ary.rb
Array(nil) => []
Array.try_convert(nil) => nil
Array(nil) => []
Array.try_convert(nil) => nil
Ruby 1.9.1-p0 (Windows) also runs fine. I don't understand what is happening here, but the behavior change breaks Rails 2.3.4 because active_support/whiny_nil.rb redefines NilClass.method_missing with code equivalent to the above one.
=end
Updated by matz (Yukihiro Matsumoto) over 15 years ago
=begin
Hi,
In message "Re: [ruby-core:26628] [Bug #2346] Array(nil) fails after redefining NilClass.method_missing to throw NoMethodError"
on Mon, 9 Nov 2009 01:56:47 +0900, Romulo Ceccon [email protected] writes:
|Given the following script:
|
| print "Array(nil) => ", Array(nil).inspect, "\n"
| print "Array.try_convert(nil) => ", Array.try_convert(nil).inspect, "\n"
| class NilClass
| private
| def method_missing(method, *args, &block)
| raise NoMethodError
| end
| end
| print "Array(nil) => ", Array(nil).inspect, "\n"
| print "Array.try_convert(nil) => ", Array.try_convert(nil).inspect, "\n"
|
|Ruby 1.9.2dev returns this:
|
| $ ruby -v
| ruby 1.9.2dev (2009-11-08 trunk 25690) [i386-mswin32_90]
|
| $ ruby nil_ary.rb
| Array(nil) => []
| Array.try_convert(nil) => nil
| nil_ary.rb:6:in method_missing': NoMethodError (NoMethodError) | from nil_ary.rb:9:in
Array'
| from nil_ary.rb:9:in `'
Because 1.9 actually calls the conversion method, where 1.8 checks
method existence by respond_to? In other words, 1.9 respects duck
typing more thoroughly. This one is a side effect.
If you don't want see exception raised, use super from method_missing,
or you can do like the following (not recommended):
print "Array(nil) => ", Array(nil).inspect, "\n"
print "Array.try_convert(nil) => ", Array.try_convert(nil).inspect, "\n"
class NilClass
private
def method_missing(method, *args, &block)
raise NoMethodError.new("undefined method #{method}", method), caller(1)
end
end
print "Array(nil) => ", Array(nil).inspect, "\n"
print "Array.try_convert(nil) => ", Array.try_convert(nil).inspect, "\n"
matz.
=end
Updated by matz (Yukihiro Matsumoto) over 15 years ago
- Status changed from Open to Rejected
=begin
=end