Backport #8153
closedProblems with Enumerable#zip caused by overriding Object#respond_to?
Description
If I override Object#respond_to? under Ruby 2.0.0, Enumerable#zip begins to misbehave. Here is the code and output in Ruby 2.0.0:
2.0.0p0 :001 > RUBY_VERSION
=> "2.0.0"
2.0.0p0 :002 > class Object
2.0.0p0 :003?> alias :_respond_to? :respond_to?
2.0.0p0 :004?> def respond_to?(*a)
2.0.0p0 :005?> _respond_to?(*a)
2.0.0p0 :006?> end
2.0.0p0 :007?> end
=> nil
2.0.0p0 :008 > [1,2,3].zip((1..3).each)
=> [[1, nil], [2, nil], [3, nil]]
Should be: [[1, 1], [2, 2], [3, 3]]
Here is the output I was expecting, generated in Ruby 1.9.3 -- ruby 1.9.3p392 (2013-02-22 revision 39386) [x86_64-darwin12.2.0]:
1.9.3p392 :001 > RUBY_VERSION
=> "1.9.3"
1.9.3p392 :002 > class Object
1.9.3p392 :003?> alias :_respond_to? :respond_to?
1.9.3p392 :004?> def respond_to?(*a)
1.9.3p392 :005?> _respond_to?(*a)
1.9.3p392 :006?> end
1.9.3p392 :007?> end
=> nil
1.9.3p392 :008 > [1,2,3].zip((1..3).each)
=> [[1, 1], [2, 2], [3, 3]]
1.9.3p392 :009 >
I'm not certain if this is the only method which is interfered with, but it's how I determined an issue was present initially.
For copy and paste convenience:
class Object
alias :_respond_to? :respond_to?
def respond_to?(*a)
_respond_to?(*a)
end
end
[1,2,3].zip((1..3).each)
FWIW, the same behaviour occurs if using a prepend-ed module and super:
module RespondToBug
def respond_to?(*a)
super
end
end
class Object
prepend RespondToBug
end
Updated by drbrain (Eric Hodel) over 11 years ago
Is respond_to_missing? insufficient for your needs?
Updated by marcandre (Marc-Andre Lafortune) over 11 years ago
- Category set to core
- Assignee set to marcandre (Marc-Andre Lafortune)
Indeed, using respond_to_missing?
is typically the preferred way, but that's a very odd bug!
Updated by marcandre (Marc-Andre Lafortune) over 11 years ago
- Status changed from Open to Closed
- % Done changed from 0 to 100
This issue was solved with changeset r39877.
Mark, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.
- array.c: Avoid zip bug by not using obsolete rb_check_block_call [Bug #8153]
Updated by marcandre (Marc-Andre Lafortune) over 11 years ago
- Tracker changed from Bug to Backport
- Project changed from Ruby master to Backport200
- Category deleted (
core) - Status changed from Closed to Open
- Assignee changed from marcandre (Marc-Andre Lafortune) to nagachika (Tomoyuki Chikanaga)
Updated by mjtko (Mark Titorenko) over 11 years ago
Thanks, glad to hear this has been fixed!
As for using respond_to_missing?
- I understand the purpose of respond_to_missing?
but, in my case, I was explicitly overriding respond_to?
in order to try and track down bad code that was still using the single-argument version for determining the presence of protected methods. This was working fine, but instead was causing other code to fail with the zip
bug as outlined above. :)
Updated by nagachika (Tomoyuki Chikanaga) over 11 years ago
- Status changed from Open to Closed
This issue was solved with changeset r40281.
Mark, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.
merge revision(s) 39877,39881: [Backport #8153] [Backport #8154]
* array.c: Avoid zip bug by not using obsolete rb_check_block_call
[Bug #8153]
* vm_eval.c (check_funcall_respond_to): preserve passed_block, which
is modified in vm_call0_body() via vm_call0(), and caused a bug of
rb_check_funcall() by false negative result of rb_block_given_p().
re-fix [ruby-core:53650] [Bug #8153].
[ruby-core:53653] [Bug #8154]