Bug #21030
closedBug: #step with Range<ActiveSupport::Duration> behavior broken on Ruby 3.4.1
Description
Issue also filed at: https://github.com/rails/rails/issues/54199
System configuration¶
Rails version: 7.1.5.1
Ruby version: 3.3.4 (works) vs 3.4.1 (broken)
What's broken¶
Calling #step
then #to_a
on a Range
whose beginning/end values are the same is expected to return an Array
wrapping the Range
's singular value. In other words, (x..x).step(n).to_a
should return [x]
-- note this is also the same as (x..x).to_a
The following case breaks on Ruby 3.4.1 related to ActiveSupport::Duration
class, where it returns an empty array. It works on Ruby 3.3. Both tested with Rails 7.1.5.1. It's very easy to reproduce.
I'm unsure if this is a Ruby bug or a Rails bug so I'm filing it in both places. The upgrade of Ruby is what produces the difference.
require 'active_support/all' # version 7.1.5.1
int = 100
dur = 100.seconds # ActiveSupport/Duration
# The bug
(dur..dur).step(10).to_a # => Ruby 3.3 returns [100 seconds] - CORRECT
# => Ruby 3.4 returns [] - INCORRECT
(int..dur).step(10).to_a # => Ruby 3.3 returns [100] - CORRECT
# => Ruby 3.4 returns [] - INCORRECT
# Note the following cases work correctly on both Ruby versions:
(int..int).step(10).to_a #=> [100]
(int..dur).to_a #=> [100]
# Range with non-equivalent values also works fine on different versions:
dur2 = 120.seconds
(dur..dur2).step(10).to_a #=> [100 seconds, 110 seconds, 120 seconds]
(int..dur2).step(10).to_a #=> [100, 110, 120]
Updated by zverok (Victor Shepelev) about 1 month ago
- Assignee set to zverok (Victor Shepelev)
- Backport changed from 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN to 3.1: DONTNEED, 3.2: DONTNEED, 3.3: DONTNEED, 3.4: UNKNOWN
Updated by zverok (Victor Shepelev) about 1 month ago
Confirmed, looking into it.
Updated by nobu (Nobuyoshi Nakada) about 1 month ago
- Status changed from Open to Closed
Applied in changeset git|f56f3eaae55cc6f8d9e79862ee73a9ffb53d6077.
[Bug #21030] Fix step for non-numeric range
When the end points of an inclusive range equal, Range#step
should
yields the element once.
Updated by johnnyshields (Johnny Shields) about 1 month ago
May I confirm this will be patched in Ruby 3.4.2?
Updated by nobu (Nobuyoshi Nakada) about 1 month ago
3.4.2 is not scheduled yet.
Updated by johnnyshields (Johnny Shields) 11 days ago
May we mark this as 3.4 backport? I'm hesitant to upgrade my app to 3.4 without this fix.
Updated by mame (Yusuke Endoh) 4 days ago
- Related to Bug #21147: [Breaking changes or Bug] DateTime Range#to_a behaves different between 3.3.7 and 3.4.1 added
Updated by jamesst20 (James St-Pierre) 1 day ago
According to the changelogs for v3.4.2, this wasn't included?
Updated by Eregon (Benoit Daloze) 1 day ago
- Backport changed from 3.1: DONTNEED, 3.2: DONTNEED, 3.3: DONTNEED, 3.4: UNKNOWN to 3.1: DONTNEED, 3.2: DONTNEED, 3.3: DONTNEED, 3.4: REQUIRED