Skip to content

Commit ca35402

Browse files
committed
[Bug #21513] Raise on converting endless range to set
ref: https://bugs.ruby-lang.org/issues/21513 Before this patch, trying to convert endless range (e.g. `(1..)`) to set (using `to_set`) would hang
1 parent 5723945 commit ca35402

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

range.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,6 +1017,30 @@ range_to_a(VALUE range)
10171017
return rb_call_super(0, 0);
10181018
}
10191019

1020+
/*
1021+
* call-seq:
1022+
* to_set -> set
1023+
*
1024+
* Returns a set containing the elements in +self+, if a finite collection;
1025+
* raises an exception otherwise.
1026+
*
1027+
* (1..4).to_set # => Set[1, 2, 3, 4]
1028+
* (1...4).to_set # => Set[1, 2, 3]
1029+
* ('a'..'d').to_set # => Set["a", "b", "c", "d"]
1030+
* (..'d').to_set # RangeError
1031+
* ('a'..).to_set # RangeError
1032+
*
1033+
*/
1034+
1035+
static VALUE
1036+
range_to_set(int argc, VALUE *argv, VALUE range)
1037+
{
1038+
if (NIL_P(RANGE_BEG(range)) || NIL_P(RANGE_END(range))) {
1039+
rb_raise(rb_eRangeError, "cannot convert infinite range to a set");
1040+
}
1041+
return rb_call_super(argc, argv);
1042+
}
1043+
10201044
static VALUE
10211045
range_enum_size(VALUE range, VALUE args, VALUE eobj)
10221046
{
@@ -2847,6 +2871,7 @@ Init_Range(void)
28472871
rb_define_method(rb_cRange, "entries", range_to_a, 0);
28482872
rb_define_method(rb_cRange, "to_s", range_to_s, 0);
28492873
rb_define_method(rb_cRange, "inspect", range_inspect, 0);
2874+
rb_define_method(rb_cRange, "to_set", range_to_set, -1);
28502875

28512876
rb_define_method(rb_cRange, "exclude_end?", range_exclude_end_p, 0);
28522877

test/ruby/test_range.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1541,4 +1541,16 @@ def test_overlap?
15411541
assert_not_operator((1...3), :overlap?, (3..4))
15421542
assert_not_operator((...3), :overlap?, (3..))
15431543
end
1544+
1545+
def test_to_set
1546+
assert_equal(Set[], (1..-1).to_set)
1547+
assert_equal(Set[1, 2, 3], (1..3).to_set)
1548+
assert_equal(Set['a', 'b', 'c'], ('a'..'c').to_set)
1549+
assert_equal(Set['a', 'b', 'c'], ('a'..'c').to_set(Set))
1550+
assert_equal(Set['b', 'c', 'd'], ('a'..'c').to_set(&:succ))
1551+
1552+
assert_raise(RangeError) { (239..).to_set }
1553+
assert_raise(RangeError) { (...239).to_set }
1554+
assert_raise(RangeError) { (nil...nil).to_set }
1555+
end
15441556
end

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy