[前][次][番号順一覧][スレッド一覧]

ruby-changes:62271

From: nagachika <ko1@a...>
Date: Sun, 19 Jul 2020 12:16:51 +0900 (JST)
Subject: [ruby-changes:62271] d24cce8e7f (ruby_2_7): merge revision(s) bf1a6771f305ea286a3ae575676924551c03e857,c1463625555b061a2b94c3b6c5581730b482a285: [Backport #17012] [Backport #17014]

https://git.ruby-lang.org/ruby.git/commit/?id=d24cce8e7f

From d24cce8e7f48b0b45f726f5f1ac7ff796f46ba72 Mon Sep 17 00:00:00 2001
From: nagachika <nagachika@r...>
Date: Sun, 19 Jul 2020 12:16:37 +0900
Subject: merge revision(s)
 bf1a6771f305ea286a3ae575676924551c03e857,c1463625555b061a2b94c3b6c5581730b482a285:
 [Backport #17012] [Backport #17014]

	Fix non-numeric exclusive Range#minmax bug

	The implementation of Range#minmax added in d5c60214c45 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

diff --git a/range.c b/range.c
index bf14c0c..2deb495 100644
--- a/range.c
+++ b/range.c
@@ -22,6 +22,8 @@ VALUE rb_cRange; https://github.com/ruby/ruby/blob/trunk/range.c#L22
 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) https://github.com/ruby/ruby/blob/trunk/range.c#L1238
     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
diff --git a/test/ruby/test_range.rb b/test/ruby/test_range.rb
index b37dbbc..3953b3e 100644
--- a/test/ruby/test_range.rb
+++ b/test/ruby/test_range.rb
@@ -146,6 +146,9 @@ class TestRange < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_range.rb#L146
     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
diff --git a/version.h b/version.h
index ad01425..f7f94bf 100644
--- a/version.h
+++ b/version.h
@@ -2,7 +2,7 @@ https://github.com/ruby/ruby/blob/trunk/version.h#L2
 # 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
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]