Backport #8153

Problems with Enumerable#zip caused by overriding Object#respond_to?

Added by Mark Titorenko about 1 year ago. Updated about 1 year ago.

[ruby-core:53650]
Status:Closed
Priority:Normal
Assignee:Tomoyuki Chikanaga

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 > RUBYVERSION
=> "2.0.0"
2.0.0p0 :002 > class Object
2.0.0p0 :003?> alias :
respondto? :respondto?
2.0.0p0 :004?> def respondto?(*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 > RUBYVERSION
=> "1.9.3"
1.9.3p392 :002 > class Object
1.9.3p392 :003?> alias :
respondto? :respondto?
1.9.3p392 :004?> def respondto?(*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 :respondto? :respondto?
def respond
to?(a)
respondto?(
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


Related issues

Related to Backport200 - Backport #8154: Remove/fix rb_check_block_call Closed 03/23/2013

Associated revisions

Revision 40281
Added by Tomoyuki Chikanaga about 1 year ago

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  [Bug #8153].
   [Bug #8154]

History

#1 Updated by Eric Hodel about 1 year ago

Is respondtomissing? insufficient for your needs?

#2 Updated by Marc-Andre Lafortune about 1 year ago

  • Category set to core
  • Assignee set to Marc-Andre Lafortune

Indeed, using respond_to_missing? is typically the preferred way, but that's a very odd bug!

#3 Updated by Marc-Andre Lafortune about 1 year 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 rbcheckblock_call [Bug #8153]

#4 Updated by Marc-Andre Lafortune about 1 year ago

  • Tracker changed from Bug to Backport
  • Project changed from ruby-trunk to Backport200
  • Category deleted (core)
  • Status changed from Closed to Open
  • Assignee changed from Marc-Andre Lafortune to Tomoyuki Chikanaga

#5 Updated by Mark Titorenko about 1 year 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. :)

#6 Updated by Tomoyuki Chikanaga about 1 year 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  [Bug #8153].
   [Bug #8154]

Also available in: Atom PDF