Project

General

Profile

Actions

Bug #22385

open

Enumerator::Lazy#zip loses to_ary conversions when mixed with enumerable arguments

Bug #22385: Enumerator::Lazy#zip loses to_ary conversions when mixed with enumerable arguments

Added by afurm (Andrii Furmanets) about 5 hours ago.

Status:
Open
Assignee:
-
Target version:
-
ruby -v:
ruby 4.1.0dev (2026-09-26T04:24:02Z af/ruby-correctnes.. da3e1fcb68) +PRISM [arm64-darwin27]
[ruby-core:126864]

Description

Enumerator::Lazy#zip discards a successful to_ary conversion when a later argument requires Enumerable iteration. The equivalent eager Enumerable#zip call preserves the conversion.

Reproduction

array_like = Object.new
def array_like.to_ary
  [:a, :b]
end

p (1..3).zip(array_like, 10..12)
# => [[1, :a, 10], [2, :b, 11], [3, nil, 12]]

p (1..3).lazy.zip(array_like).force
# => [[1, :a], [2, :b], [3, nil]]

p (1..3).lazy.zip(array_like, 10..12).force
# => NoMethodError: undefined method 'each' for an Object

Expected behavior

The last expression should return [[1, :a, 10], [2, :b, 11], [3, nil, 12]], matching the eager call. Adding the range should not discard the earlier successful array conversion.

If the argument defines both to_ary and each with different values, the same defect silently uses the each values instead of the converted array.

Affected versions

Reproduced on unchanged Ruby master at da3e1fcb685864a2f58f113e82d9dc67d7fe9197 (Ruby 4.1.0dev) and on Ruby 3.3.1 (c56cd86388, arm64-darwin24).

Cause and patch

In lazy_zip, converted arguments are accumulated in ary. When a later argument does not convert to an Array, the fallback rebuilds ary from the original arguments, losing those conversions. Appending the remaining arguments to the converted prefix preserves the behavior of Enumerable#zip.

Patch and regression tests: https://github.com/ruby/ruby/pull/19063

Both new regression tests fail before the fix (one failure and one error) and pass afterward. They cover conversion precedence, nil padding and repeated enumeration. After rebasing the fix onto master at 6eab8427a849dfe2e121b75faa30a272a8e4a1b3, the related suites passed: 222 tests and 1,858 assertions (one skip for unavailable callcc), plus 439 specification examples with 687 expectations. The full Ruby test suite was not run.

I found no matching report in the GitHub all-state and Redmine all-status searches performed. Related #7706 concerns the earlier lazy zip optimization and invalid-argument handling, rather than this conversion-loss case.

No data to display

Actions

Also available in: PDF Atom