Project

General

Profile

Actions

Bug #21513

open

Converting endless range to set hangs

Added by viralpraxis (Iaroslav Kurbatov) 5 days ago. Updated 4 days ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:122773]

Description

Converting endless range to array raises:

ruby -e '(1..).to_a'
-e:1:in 'Range#to_a': cannot convert endless range to an array (RangeError)
	from -e:1:in '<main>'

but converting to set does not:

ruby -e '(1..).to_set # hangs'

I think it makes to raise in both cases for consistency. Something like this should do the trick:

diff --git i/prelude.rb w/prelude.rb
index f49cada637..11bfa3fc95 100644
--- i/prelude.rb
+++ w/prelude.rb
@@ -30,6 +30,10 @@ module Enumerable
   # Makes a set from the enumerable object with given arguments.
   # Passing arguments to this method is deprecated.
   def to_set(*args, &block)
+    if self.class == Range && self.end.nil?
+      raise RangeError, "cannot convert endless range to a set"
+    end
+
     klass = if args.empty?
       Set
     else
diff --git i/test/ruby/test_range.rb w/test/ruby/test_range.rb
index f875c0ab40..27b968641b 100644
--- i/test/ruby/test_range.rb
+++ w/test/ruby/test_range.rb
@@ -1541,4 +1541,11 @@ def test_overlap?
     assert_not_operator((1...3), :overlap?, (3..4))
     assert_not_operator((...3), :overlap?, (3..))
   end
+
+  def test_to_set
+    assert_equal(Set[], (1..-1).to_set)
+    assert_equal(Set[1, 2, 3], (1..3).to_set)
+
+    assert_raise(RangeError) { (239..).to_set }
+  end
 end

If this patch is accepted, I'll open a PR.

./ruby -v
ruby 3.5.0dev (2025-07-14T20:34:32Z master a6d483971a) +PRISM [x86_64-linux]

Updated by Dan0042 (Daniel DeLorme) 5 days ago

Raising an error should be the case for ANY endless range operations that result in an infinite loop and memory consumption. This is a very costly and hard to debug failure mode, and it happens for a large number of endless range methods.

Updated by nobu (Nobuyoshi Nakada) 4 days ago

Thank you, good catch.

I think that check should be in Range#to_set, as well as Range#to_a.

class Range
  # Makes a set from the range with given arguments, if a finite
  # collection; raises an exception otherwise.
  # Passing arguments to this method is deprecated.
  def to_set(...)
    if self.end.nil?
      raise RangeError, "cannot convert endless range to a set"
    end
    super
  end
end

Updated by nobu (Nobuyoshi Nakada) 4 days ago

I suspect this is a bug fix instead of a new feature, isn't it?

Actions #5

Updated by viralpraxis (Iaroslav Kurbatov) 4 days ago

  • Tracker changed from Feature to Bug
  • Backport set to 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN
Actions #6

Updated by viralpraxis (Iaroslav Kurbatov) 4 days ago

  • Subject changed from Raise on converting endless range to set to Converting endless range to set hangs

Updated by Dan0042 (Daniel DeLorme) 4 days ago

What's your opinion on adding the same raise/check for the following methods? They present the same infinite loop problem.

#count
#all?
#collect / #map
#collect_concat / #flat_map
#compact
#drop
#drop_while
#filter
#filter_map
#find_all / #select
#grep
#grep_v
#group_by
#inject / #reduce
#max_by / #min_by / #minmax_by
#none?
#one?
#partition
#sort / #sort_by
#sum
#tally
#to_h
#uniq

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0