😊

[Bug #21152] Range#reverse_each が Ruby 3.3 と 3.4 で挙動に差異があるというバグ報告

に公開

[Bug #21152] Enumerator's #size returned by Range#reverse_each raises an exception for endless Range

  • Range#reverse_each が Ruby 3.3 と 3.4 で挙動に差異があるというバグ報告
# Ruby 3.3
Range.new("a", nil).size # => nil
Range.new(1, nil).size   # => Infinity

Range.new("a", nil).reverse_each.size # => nil
Range.new(1, nil).reverse_each.size   # => Infinity
# Ruby 3.4

# こっちは変わらない
Range.new("a", nil).size # => nil
Range.new(1, nil).size   # => Infinity

Range.new("a", nil).reverse_each.size # can't iterate from NilClass (TypeError)
Range.new(1, nil).reverse_each.size   # can't iterate from NilClass (TypeError)
  • 上記の例はいずれも 終端無限 + #reverse_each の組み合わせで例外になります
  • また、同様に Range.new(nil, "a").size も Ruby 3.4 から挙動が変わるみたいですね
pp Range.new(nil, "a").size
# Ruby 3.3 => nil
# Ruby 3.4 => error: can't iterate from NilClass (TypeError)
  • いずれの例も『先端が無限の場合に例外になる』というような挙動になり、以下のようなコードも同様のエラーになります。
    • このエラー自体は Ruby 3.3 でも同様にエラーになる
# error: can't iterate from NilClass (TypeError)
Range.new(nil, 1).each do |x|
  p x
end
  • つまりは『終端無限の場合に #each するのは問題ないが先端無限の場合に #each するのは失敗する』みたいなのが期待する挙動みたいですね
    • Range.new(nil, 1).each がエラーになるなら Range.new(1, nil).reverse_each もエラーになるよね?みたいな期待値
  • このチケットではなにも対応されずに Close されています
  • 挙動自体は一応非互換な動きになるので注意する必要はありそうですかね
GitHubで編集を提案

Discussion