mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
merge revision(s) bf1a6771f305ea286a3ae575676924551c03e857,c1463625555b061a2b94c3b6c5581730b482a285: [Backport #17012] [Backport #17014]
Fix non-numeric exclusive Range#minmax bug
The implementation of Range#minmax added in d5c60214c4
causes the
following incorrect behaviour:
('a'...'c').minmax => ["a", ["a", "b"]]
instead of
('a'...'c').minmax => ["a", "b"]
This is because the C implementation of Range#minmax (range_minmax)
directly delegates to the C implementation of Range#min (range_min) and
Range#max (range_max), without changing the execution context.
Range#max's C implementation (range_max), when given a non-numeric
exclusive range, delegates to super, which is meant to call
Enumerable#max. However, because range_max is called directly by
range_minmax, super calls Enumerable#minmax instead, causing the
incorrect nesting.
Perhaps it is possible to change the execution context in an optimized
manner, but the simplest solution seems to be to just explicitly
delegate from Range#minmax to Range#min and Range#max.
Use static variables in Range#minmax
This commit is contained in:
parent
f43b8c4f73
commit
d24cce8e7f
3 changed files with 10 additions and 2 deletions
7
range.c
7
range.c
|
@ -22,6 +22,8 @@ VALUE rb_cRange;
|
|||
static ID id_beg, id_end, id_excl;
|
||||
#define id_cmp idCmp
|
||||
#define id_succ idSucc
|
||||
#define id_min idMin
|
||||
#define id_max idMax
|
||||
|
||||
static VALUE r_cover_p(VALUE, VALUE, VALUE, VALUE);
|
||||
|
||||
|
@ -1236,7 +1238,10 @@ range_minmax(VALUE range)
|
|||
if (rb_block_given_p()) {
|
||||
return rb_call_super(0, NULL);
|
||||
}
|
||||
return rb_assoc_new(range_min(0, NULL, range), range_max(0, NULL, range));
|
||||
return rb_assoc_new(
|
||||
rb_funcall(range, id_min, 0),
|
||||
rb_funcall(range, id_max, 0)
|
||||
);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -146,6 +146,9 @@ class TestRange < Test::Unit::TestCase
|
|||
assert_equal([nil, nil], (0...0).minmax)
|
||||
|
||||
assert_equal([2, 1], (1..2).minmax{|a, b| b <=> a})
|
||||
|
||||
assert_equal(['a', 'c'], ('a'..'c').minmax)
|
||||
assert_equal(['a', 'b'], ('a'...'c').minmax)
|
||||
end
|
||||
|
||||
def test_initialize_twice
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
|
||||
#define RUBY_VERSION_TEENY 1
|
||||
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
|
||||
#define RUBY_PATCHLEVEL 96
|
||||
#define RUBY_PATCHLEVEL 97
|
||||
|
||||
#define RUBY_RELEASE_YEAR 2020
|
||||
#define RUBY_RELEASE_MONTH 7
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue