summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2019-10-26 02:15:18 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2019-10-26 12:52:50 +0900
commitcf9344131c3d0f5993c6d999c427a4c656df30a2 (patch)
tree40de7e8be0e445e174498ae0a3555aa2ffea6260
parentf14b754151c8b6a006871cff8f590b9b608a7697 (diff)
Raise on end-exclusive ranges [Feature #14784]
Raises an error on end-exclusive ranges unless endless, regardless the receiver.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/2613
-rw-r--r--compar.c15
-rw-r--r--test/ruby/test_comparable.rb12
2 files changed, 15 insertions, 12 deletions
diff --git a/compar.c b/compar.c
index 058d912..e9b1d4b 100644
--- a/compar.c
+++ b/compar.c
@@ -210,8 +210,8 @@ cmp_between(VALUE x, VALUE min, VALUE max)
* -20.clamp(0..) #=> 0
* 523.clamp(..100) #=> 100
*
- * When _range.end_ is excluded, and _obj_ is greater than or
- * equal to _range.end_, an exception is raised.
+ * When _range.end_ is excluded and not +nil+, an exception is
+ * raised.
*
* 100.clamp(0...100) # ArgumentError
*/
@@ -220,7 +220,7 @@ static VALUE
cmp_clamp(int argc, VALUE *argv, VALUE x)
{
VALUE min, max;
- int c, excl = 0, allow_nil = 0;
+ int c, excl = 0;
if (rb_scan_args(argc, argv, "11", &min, &max) == 1) {
VALUE range = min;
@@ -228,9 +228,13 @@ cmp_clamp(int argc, VALUE *argv, VALUE x)
rb_raise(rb_eTypeError, "wrong argument type %s (expected Range)",
rb_builtin_class_name(range));
}
- allow_nil = 1;
+ if (!NIL_P(max)) {
+ if (excl) rb_raise(rb_eArgError, "cannot clamp with an exclusive range");
+ if (!NIL_P(min) && cmpint(min, max) > 0) goto arg_error;
+ }
}
- if (!(allow_nil && (NIL_P(min) || NIL_P(max))) && cmpint(min, max) > 0) {
+ else if (cmpint(min, max) > 0) {
+ arg_error:
rb_raise(rb_eArgError, "min argument must be smaller than max argument");
}
@@ -241,7 +245,6 @@ cmp_clamp(int argc, VALUE *argv, VALUE x)
}
if (!NIL_P(max)) {
c = cmpint(x, max);
- if (excl && c >= 0) rb_raise(rb_eArgError, "cannot clamp with an exclusive range");
if (c > 0) return max;
}
return x;
diff --git a/test/ruby/test_comparable.rb b/test/ruby/test_comparable.rb
index e8a2ff1..b849217 100644
--- a/test/ruby/test_comparable.rb
+++ b/test/ruby/test_comparable.rb
@@ -99,22 +99,22 @@ class TestComparable < Test::Unit::TestCase
assert_equal(1, @o.clamp(1..1))
assert_equal(@o, @o.clamp(0..0))
- assert_equal(1, @o.clamp(1...2))
assert_equal(1, @o.clamp(1..))
assert_equal(1, @o.clamp(1...))
- assert_equal(@o, @o.clamp(0...2))
assert_equal(@o, @o.clamp(0..))
assert_equal(@o, @o.clamp(0...))
assert_equal(@o, @o.clamp(..2))
- assert_equal(@o, @o.clamp(...2))
assert_equal(-1, @o.clamp(-2..-1))
assert_equal(@o, @o.clamp(-2..0))
assert_equal(@o, @o.clamp(-2..))
assert_equal(@o, @o.clamp(-2...))
- assert_raise_with_message(ArgumentError, 'cannot clamp with an exclusive range') {
- @o.clamp(-1...0)
- }
+ exc = [ArgumentError, 'cannot clamp with an exclusive range']
+ assert_raise_with_message(*exc) {@o.clamp(1...2)}
+ assert_raise_with_message(*exc) {@o.clamp(0...2)}
+ assert_raise_with_message(*exc) {@o.clamp(-1...0)}
+ assert_raise_with_message(*exc) {@o.clamp(...2)}
+
assert_raise_with_message(ArgumentError, 'min argument must be smaller than max argument') {
@o.clamp(2..1)
}