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) 10 months ago
          Updated by zverok (Victor Shepelev) 10 months 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) 10 months ago
          Updated by zverok (Victor Shepelev) 10 months ago
          
          
        
        
      
      Confirmed, looking into it.
        
           Updated by nobu (Nobuyoshi Nakada) 10 months ago
          Updated by nobu (Nobuyoshi Nakada) 10 months 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) 10 months ago
          Updated by johnnyshields (Johnny Shields) 10 months ago
          
          
        
        
      
      May I confirm this will be patched in Ruby 3.4.2?
        
           Updated by nobu (Nobuyoshi Nakada) 10 months ago
          Updated by nobu (Nobuyoshi Nakada) 10 months ago
          
          
        
        
      
      3.4.2 is not scheduled yet.
        
           Updated by johnnyshields (Johnny Shields) 9 months ago
          Updated by johnnyshields (Johnny Shields) 9 months 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) 8 months ago
          Updated by mame (Yusuke Endoh) 8 months 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) 8 months ago
          Updated by jamesst20 (James St-Pierre) 8 months ago
          
          
        
        
      
      According to the changelogs for v3.4.2, this wasn't included?
        
           Updated by Eregon (Benoit Daloze) 8 months ago
          Updated by Eregon (Benoit Daloze) 8 months 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
        
           Updated by ufuk (Ufuk Kayserilioglu) 8 months ago
          Updated by ufuk (Ufuk Kayserilioglu) 8 months ago
          
          
        
        
      
      - Backport changed from 3.1: DONTNEED, 3.2: DONTNEED, 3.3: DONTNEED, 3.4: REQUIRED to 3.1: DONTNEED, 3.2: DONTNEED, 3.3: DONTNEED, 3.4: DONE
        
           Updated by k0kubun (Takashi Kokubun) 8 months ago
          Updated by k0kubun (Takashi Kokubun) 8 months ago
          
          
        
        
      
      - Backport changed from 3.1: DONTNEED, 3.2: DONTNEED, 3.3: DONTNEED, 3.4: DONE to 3.1: DONTNEED, 3.2: DONTNEED, 3.3: DONTNEED, 3.4: REQUIRED
        
           Updated by k0kubun (Takashi Kokubun) 8 months ago
          Updated by k0kubun (Takashi Kokubun) 8 months ago
          
          
        
        
      
      - Backport changed from 3.1: DONTNEED, 3.2: DONTNEED, 3.3: DONTNEED, 3.4: REQUIRED to 3.1: DONTNEED, 3.2: DONTNEED, 3.3: DONTNEED, 3.4: DONE
ruby_3_4 6d2c7d4304bbf8450d31b624f5dc40a92e44f00b.
        
           Updated by jamesst20 (James St-Pierre) 6 months ago
          Updated by jamesst20 (James St-Pierre) 6 months ago
          
          
        
        
      
      jamesst20 (James St-Pierre) wrote in #note-8:
According to the changelogs for v3.4.2, this wasn't included?
To add more details, this fix was also not included in v3.4.3.
The fix: https://github.com/ruby/ruby/commit/f56f3eaae55cc6f8d9e79862ee73a9ffb53d6077
It appears to be included in v3.5.0 Preview 1, this probably mean Ruby v3.4 will be a forever buggy version to avoid.
        
           Updated by Eregon (Benoit Daloze) 6 months ago
          
          ยท Edited
          Updated by Eregon (Benoit Daloze) 6 months ago
          
          ยท Edited
        
        
      
      @jamesst20 https://github.com/ruby/ruby/commit/6d2c7d4304bbf8450d31b624f5dc40a92e44f00b is in 3.4.3 though.
And I don't see any revert in https://github.com/ruby/ruby/compare/v3_4_2...v3_4_3
Are you sure it's not fixed in 3.4.3?
It's even mentioned in https://github.com/ruby/ruby/releases/tag/v3_4_3
If you just looked at the tag info on https://github.com/ruby/ruby/commit/f56f3eaae55cc6f8d9e79862ee73a9ffb53d6077 on GitHub, that's not the whole story, backport commits are cherry-picked not merged.
        
           Updated by johnnyshields (Johnny Shields) 6 months ago
          Updated by johnnyshields (Johnny Shields) 6 months ago
          
          
        
        
      
      I also verified the fix in 3.4.3 in my app. The behavior is correct.