ruby-changes:66303
From: nagachika <ko1@a...>
Date: Sat, 22 May 2021 17:09:37 +0900 (JST)
Subject: [ruby-changes:66303] 31816356ee (ruby_3_0): merge revision(s) 2bc293e899c9d32dcd794a73de8925c49ecf8f15,d0e6c6e682b9ba2b0309a5177933a0628e8ef316,cc0dc67bbbe1951ff90004bc987f78545625d772,e1eff837cf12a8e813de9d4ff2db50c9b68b86b5,0ab0b86c8491d639b9ff1335ddf35e341ecd867e,6911b4bc82889860ff7da4ecf975504cdc3e5314: [Backport #17854]
https://git.ruby-lang.org/ruby.git/commit/?id=31816356ee From 31816356eee6313fe968eecd4cd3ad9ac4848819 Mon Sep 17 00:00:00 2001 From: nagachika <nagachika@r...> Date: Sat, 22 May 2021 17:09:16 +0900 Subject: merge revision(s) 2bc293e899c9d32dcd794a73de8925c49ecf8f15,d0e6c6e682b9ba2b0309a5177933a0628e8ef316,cc0dc67bbbe1951ff90004bc987f78545625d772,e1eff837cf12a8e813de9d4ff2db50c9b68b86b5,0ab0b86c8491d639b9ff1335ddf35e341ecd867e,6911b4bc82889860ff7da4ecf975504cdc3e5314: [Backport #17854] cdhash_cmp: can take rational literals Rational literals are those integers suffixed with `r`. They tend to be a part of more complex expressions like `123/456r`, but in theory they can live alone. When such "bare" rational literals are passed to case-when branch, we have to take care of them. Fixes [Bug #17854] --- common.mk | 1 + compile.c | 7 +++++++ internal/rational.h | 1 + rational.c | 13 ++++++++++--- test/ruby/test_rational.rb | 7 +++++++ 5 files changed, 26 insertions(+), 3 deletions(-) cdhash_cmp: rational literals with fractions Nobu kindly pointed out that rational literals can have fractions. --- compile.c | 5 +++-- test/ruby/test_rational.rb | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) cdhash_cmp: can also take complex There are complex literals `123i`, which can also be a case condition. --- compile.c | 15 +++++++++++---- complex.c | 12 +++++++++--- internal/complex.h | 1 + test/ruby/test_rational.rb | 4 ++++ 4 files changed, 25 insertions(+), 7 deletions(-) cdhash_cmp: recursively apply For instance a rational's numerator can be a bignum. Comparison using C's == can be insufficient. --- compile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) cdhash_cmp: should use || cf: https://github.com/ruby/ruby/pull/4469#discussion_r628386707 --- compile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) test_cdhash: refactor change class It is now strange to test Complex in a class named Rational_Test. --- test/ruby/test_rational.rb | 15 --------------- test/ruby/test_syntax.rb | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 15 deletions(-) --- common.mk | 1 + compile.c | 15 +++++++++++++++ complex.c | 12 +++++++++--- internal/complex.h | 1 + internal/rational.h | 1 + rational.c | 13 ++++++++++--- test/ruby/test_syntax.rb | 15 +++++++++++++++ version.h | 2 +- 8 files changed, 53 insertions(+), 7 deletions(-) diff --git a/common.mk b/common.mk index 594c165..7a0068b 100644 --- a/common.mk +++ b/common.mk @@ -2803,6 +2803,7 @@ compile.$(OBJEXT): $(top_srcdir)/internal/hash.h https://github.com/ruby/ruby/blob/trunk/common.mk#L2803 compile.$(OBJEXT): $(top_srcdir)/internal/imemo.h compile.$(OBJEXT): $(top_srcdir)/internal/numeric.h compile.$(OBJEXT): $(top_srcdir)/internal/object.h +compile.$(OBJEXT): $(top_srcdir)/internal/rational.h compile.$(OBJEXT): $(top_srcdir)/internal/re.h compile.$(OBJEXT): $(top_srcdir)/internal/serial.h compile.$(OBJEXT): $(top_srcdir)/internal/static_assert.h diff --git a/compile.c b/compile.c index b78c7f2..502d12d 100644 --- a/compile.c +++ b/compile.c @@ -28,6 +28,7 @@ https://github.com/ruby/ruby/blob/trunk/compile.c#L28 #include "internal/hash.h" #include "internal/numeric.h" #include "internal/object.h" +#include "internal/rational.h" #include "internal/re.h" #include "internal/symbol.h" #include "internal/thread.h" @@ -1985,6 +1986,16 @@ cdhash_cmp(VALUE val, VALUE lit) https://github.com/ruby/ruby/blob/trunk/compile.c#L1986 else if (tlit == T_FLOAT) { return rb_float_cmp(lit, val); } + else if (tlit == T_RATIONAL) { + const struct RRational *rat1 = RRATIONAL(val); + const struct RRational *rat2 = RRATIONAL(lit); + return cdhash_cmp(rat1->num, rat2->num) || cdhash_cmp(rat1->den, rat2->den); + } + else if (tlit == T_COMPLEX) { + const struct RComplex *comp1 = RCOMPLEX(val); + const struct RComplex *comp2 = RCOMPLEX(lit); + return cdhash_cmp(comp1->real, comp2->real) || cdhash_cmp(comp1->imag, comp2->imag); + } else { UNREACHABLE_RETURN(-1); } @@ -2003,6 +2014,10 @@ cdhash_hash(VALUE a) https://github.com/ruby/ruby/blob/trunk/compile.c#L2014 return FIX2LONG(rb_big_hash(a)); case T_FLOAT: return rb_dbl_long_hash(RFLOAT_VALUE(a)); + case T_RATIONAL: + return rb_rational_hash(a); + case T_COMPLEX: + return rb_complex_hash(a); default: UNREACHABLE_RETURN(0); } diff --git a/complex.c b/complex.c index 560d978..27c1f13 100644 --- a/complex.c +++ b/complex.c @@ -1328,8 +1328,8 @@ nucomp_numerator(VALUE self) https://github.com/ruby/ruby/blob/trunk/complex.c#L1328 } /* :nodoc: */ -static VALUE -nucomp_hash(VALUE self) +st_index_t +rb_complex_hash(VALUE self) { st_index_t v, h[2]; VALUE n; @@ -1340,7 +1340,13 @@ nucomp_hash(VALUE self) https://github.com/ruby/ruby/blob/trunk/complex.c#L1340 n = rb_hash(dat->imag); h[1] = NUM2LONG(n); v = rb_memhash(h, sizeof(h)); - return ST2FIX(v); + return v; +} + +static VALUE +nucomp_hash(VALUE self) +{ + return ST2FIX(rb_complex_hash(self)); } /* :nodoc: */ diff --git a/internal/complex.h b/internal/complex.h index 6f63a9e..9eae804 100644 --- a/internal/complex.h +++ b/internal/complex.h @@ -25,5 +25,6 @@ struct RComplex { https://github.com/ruby/ruby/blob/trunk/internal/complex.h#L25 /* complex.c */ VALUE rb_dbl_complex_new_polar_pi(double abs, double ang); +st_index_t rb_complex_hash(VALUE comp); #endif /* INTERNAL_COMPLEX_H */ diff --git a/internal/rational.h b/internal/rational.h index e53ee7b..6bbd2a9 100644 --- a/internal/rational.h +++ b/internal/rational.h @@ -33,6 +33,7 @@ VALUE rb_rational_div(VALUE self, VALUE other); https://github.com/ruby/ruby/blob/trunk/internal/rational.h#L33 VALUE rb_lcm(VALUE x, VALUE y); VALUE rb_rational_reciprocal(VALUE x); VALUE rb_cstr_to_rat(const char *, int); +VALUE rb_rational_hash(VALUE self); VALUE rb_rational_abs(VALUE self); VALUE rb_rational_cmp(VALUE self, VALUE other); VALUE rb_rational_pow(VALUE self, VALUE other); diff --git a/rational.c b/rational.c index 872bcd7..d621773 100644 --- a/rational.c +++ b/rational.c @@ -1744,8 +1744,8 @@ nurat_rationalize(int argc, VALUE *argv, VALUE self) https://github.com/ruby/ruby/blob/trunk/rational.c#L1744 } /* :nodoc: */ -static VALUE -nurat_hash(VALUE self) +st_index_t +rb_rational_hash(VALUE self) { st_index_t v, h[2]; VALUE n; @@ -1756,9 +1756,16 @@ nurat_hash(VALUE self) https://github.com/ruby/ruby/blob/trunk/rational.c#L1756 n = rb_hash(dat->den); h[1] = NUM2LONG(n); v = rb_memhash(h, sizeof(h)); - return ST2FIX(v); + return v; +} + +static VALUE +nurat_hash(VALUE self) +{ + return ST2FIX(rb_rational_hash(self)); } + static VALUE f_format(VALUE self, VALUE (*func)(VALUE)) { diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb index e289eea..a0cdb5b 100644 --- a/test/ruby/test_syntax.rb +++ b/test/ruby/test_syntax.rb @@ -1730,6 +1730,21 @@ eom https://github.com/ruby/ruby/blob/trunk/test/ruby/test_syntax.rb#L1730 assert_equal [[4, 1, 5, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]} end + def test_cdhash + assert_separately([], <<-RUBY) + n = case 1 when 2r then false else true end + assert_equal(n, true, '[ruby-core:103759] [Bug #17854]') + RUBY + assert_separately([], <<-RUBY) + n = case 3/2r when 1.5r then true else false end + assert_equal(n, true, '[ruby-core:103759] [Bug #17854]') + RUBY + assert_separately([], <<-RUBY) + n = case 1i when 1i then true else false end + assert_equal(n, true, '[ruby-core:103759] [Bug #17854]') + RUBY + end + private def not_label(x) @result = x; @not_label ||= nil end diff --git a/version.h b/version.h index 643f264..eec5108 100644 --- a/version.h +++ b/version.h @@ -12,7 +12,7 @@ https://github.com/ruby/ruby/blob/trunk/version.h#L12 # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR #define RUBY_VERSION_TEENY 2 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR -#define RUBY_PATCHLEVEL 81 +#define RUBY_PATCHLEVEL 82 #define RUBY_RELEASE_YEAR 2021 #define RUBY_RELEASE_MONTH 5 -- cgit v1.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/