From: yves.senn@... Date: 2015-08-19T11:43:44+00:00 Subject: [ruby-core:70460] [Ruby trunk - Bug #11465] [Open] `Array#flatten` calls `to_ary` on objects with `method_missing` even if `respond_to_missing?(:to_ary)` returns `false`. Issue #11465 has been reported by Yves Senn. ---------------------------------------- Bug #11465: `Array#flatten` calls `to_ary` on objects with `method_missing` even if `respond_to_missing?(:to_ary)` returns `false`. https://bugs.ruby-lang.org/issues/11465 * Author: Yves Senn * Status: Open * Priority: Normal * Assignee: * ruby -v: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin14] * Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN, 2.2: UNKNOWN ---------------------------------------- I noticed this behavior while working on an issue reported on the Rails tracker: https://github.com/rails/rails/issues/21296 I put up a reproduction along with some details about the issue in a Gist: https://gist.github.com/senny/02ee933cc75e7ac8093f The problem is that `Array#flatten` calls `to_ary` on objects with `method_missing` even if `respond_to_missing(:to_ary)` returns false. ~~~ruby class RespondToMissing def respond_to_missing?(method, stuff) return false if method == :to_ary super end def method_missing(*args) super end end trace = TracePoint.new(:raise) do |tp| p tp.raised_exception puts tp.raised_exception.backtrace.join("\n") puts end trace.enable RespondToMissing.new.respond_to? :to_ary # => false [RespondToMissing.new].flatten # OUTPUT: # false # #> # script.rb:10:in `method_missing' # script.rb:38:in `flatten' # script.rb:38:in `
' ~~~ If the objects with `method_missing` also define their own `respond_to?` it works as expected: ~~~ruby class RespondTo def respond_to?(method) super end def method_missing(*args) super end end trace = TracePoint.new(:raise) do |tp| p tp.raised_exception puts tp.raised_exception.backtrace.join("\n") puts end trace.enable p RespondTo.new.respond_to? :to_ary # => false [RespondTo.new].flatten # no internal exceptions are raised # OUTPUT: # false ~~~ ### Expected Behavior I expect `respond_to_missing?` to be considered (same as `respond_to?`) before `Array#flatten` calls `#to_ary`. ### Workaround As described above it's possible to work around this issue by also defining a `respond_to?` method. Another workaround is to define `to_ary` and return `nil`. -- https://bugs.ruby-lang.org/