Skip to content

Commit 597fe2c

Browse files
committed
Fix Range#bsearch and raise TypeError when range boundaries are non-numeric and block not passed
1 parent 2e95271 commit 597fe2c

File tree

3 files changed

+37
-4
lines changed

3 files changed

+37
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Bug fixes:
1515
* Run context cleanup such as showing the output of tools when `SignalException` and `Interrupt` escape (@eregon).
1616
* Handle a new variable inside the `case` target expression correctly (#3377, @eregon).
1717
* The arguments of `Thread.new(*args, &block)` need to be marked as shared between multiple threads (#3179, @eregon).
18+
* Fix `Range#bsearch` and raise `TypeError` when range boundaries are non-numeric and block not passed (@andrykonchin).
1819

1920
Compatibility:
2021

spec/ruby/core/range/bsearch_spec.rb

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727
-> { ("a".."e").bsearch { true } }.should raise_error(TypeError)
2828
end
2929

30+
it "raises TypeError when non-Numeric begin/end and block not passed" do
31+
-> { ("a".."e").bsearch }.should raise_error(TypeError)
32+
end
33+
3034
context "with Integer values" do
3135
context "with a block returning true or false" do
3236
it "returns nil if the block returns false for every element" do
@@ -94,6 +98,10 @@
9498
(4..2).bsearch { 0 }.should == nil
9599
(4..2).bsearch { -1 }.should == nil
96100
end
101+
102+
it "returns enumerator when block not passed" do
103+
(0...3).bsearch.kind_of?(Enumerator).should == true
104+
end
97105
end
98106

99107
context "with Float values" do
@@ -156,7 +164,6 @@
156164

157165
it "returns nil if the block returns greater than zero for every element" do
158166
(0.3..3.0).bsearch { |x| x <=> -1 }.should be_nil
159-
160167
end
161168

162169
it "returns nil if the block never returns zero" do
@@ -213,6 +220,10 @@
213220
(0...inf).bsearch { |x| x >= Float::MAX ? 0 : 1 }.should == Float::MAX
214221
end
215222
end
223+
224+
it "returns enumerator when block not passed" do
225+
(0.1...2.3).bsearch.kind_of?(Enumerator).should == true
226+
end
216227
end
217228

218229
context "with endless ranges and Integer values" do
@@ -250,6 +261,10 @@
250261
[1, 2, 3].should include(result)
251262
end
252263
end
264+
265+
it "returns enumerator when block not passed" do
266+
eval("(-2..)").bsearch.kind_of?(Enumerator).should == true
267+
end
253268
end
254269

255270
context "with endless ranges and Float values" do
@@ -327,8 +342,11 @@
327342
eval("(0.0...)").bsearch { 0 }.should != inf
328343
end
329344
end
330-
end
331345

346+
it "returns enumerator when block not passed" do
347+
eval("(0.1..)").bsearch.kind_of?(Enumerator).should == true
348+
end
349+
end
332350

333351
context "with beginless ranges and Integer values" do
334352
context "with a block returning true or false" do
@@ -361,6 +379,10 @@
361379
[1, 2, 3].should include(result)
362380
end
363381
end
382+
383+
it "returns enumerator when block not passed" do
384+
(..10).bsearch.kind_of?(Enumerator).should == true
385+
end
364386
end
365387

366388
context "with beginless ranges and Float values" do
@@ -432,5 +454,9 @@
432454
(...inf).bsearch { |x| 3 - x }.should == 3
433455
end
434456
end
457+
458+
it "returns enumerator when block not passed" do
459+
(..-0.1).bsearch.kind_of?(Enumerator).should == true
460+
end
435461
end
436462
end

src/main/ruby/truffleruby/core/range.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,6 @@ def eql?(other)
6666
end
6767

6868
def bsearch(&block)
69-
return to_enum :bsearch unless block_given?
70-
7169
start = self.begin
7270
stop = self.end
7371

@@ -99,6 +97,8 @@ def bsearch(&block)
9997
end
10098

10199
private def bsearch_float(&block)
100+
return to_enum :bsearch_float unless block_given?
101+
102102
normalized_begin = Primitive.nil?(self.begin) ? -Float::INFINITY : self.begin.to_f
103103
normalized_end = Primitive.nil?(self.end) ? Float::INFINITY : self.end.to_f
104104
normalized_end = normalized_end.prev_float if self.exclude_end?
@@ -187,6 +187,8 @@ def bsearch(&block)
187187
end
188188

189189
private def bsearch_endless(&block)
190+
return to_enum :bsearch_endless unless block_given?
191+
190192
min = self.begin
191193
cur = min
192194
diff = 1
@@ -207,6 +209,8 @@ def bsearch(&block)
207209
end
208210

209211
private def bsearch_beginless(&block)
212+
return to_enum :bsearch_beginless unless block_given?
213+
210214
max = self.end
211215
cur = max
212216
diff = 1
@@ -227,6 +231,8 @@ def bsearch(&block)
227231
end
228232

229233
private def bsearch_integer(&block)
234+
return to_enum :bsearch_integer unless block_given?
235+
230236
min = self.begin
231237
max = self.end
232238
max -= 1 if Primitive.is_a?(max, Integer) and exclude_end?

0 commit comments

Comments
 (0)