Project

General

Profile

Backport #8153

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

Added by mjtko (Mark Titorenko) over 7 years ago. Updated over 7 years ago.

Status:
Closed
Priority:
Normal
[ruby-core:53650]

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


Related issues

Related to Backport200 - Backport #8154: Remove/fix rb_check_block_callClosednagachika (Tomoyuki Chikanaga)03/23/2013Actions

Updated by drbrain (Eric Hodel) over 7 years ago

Is respond_to_missing? insufficient for your needs?

Updated by marcandre (Marc-Andre Lafortune) over 7 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!

#3

Updated by marcandre (Marc-Andre Lafortune) over 7 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]
#4

Updated by marcandre (Marc-Andre Lafortune) over 7 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 7 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. :)

#6

Updated by nagachika (Tomoyuki Chikanaga) over 7 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]

Also available in: Atom PDF