diff --git a/common.mk b/common.mk index 594c165ffd..7a0068bc73 100644 --- a/common.mk +++ b/common.mk @@ -2803,6 +2803,7 @@ compile.$(OBJEXT): $(top_srcdir)/internal/hash.h 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 b78c7f26d9..502d12d6c7 100644 --- a/compile.c +++ b/compile.c @@ -28,6 +28,7 @@ #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) 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) 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 560d9788b2..27c1f131e3 100644 --- a/complex.c +++ b/complex.c @@ -1328,8 +1328,8 @@ nucomp_numerator(VALUE self) } /* :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) 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 6f63a9ebeb..9eae804ddb 100644 --- a/internal/complex.h +++ b/internal/complex.h @@ -25,5 +25,6 @@ struct RComplex { /* 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 e53ee7b499..6bbd2a9810 100644 --- a/internal/rational.h +++ b/internal/rational.h @@ -33,6 +33,7 @@ VALUE rb_rational_div(VALUE self, VALUE other); 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 872bcd7e14..d621773838 100644 --- a/rational.c +++ b/rational.c @@ -1744,8 +1744,8 @@ nurat_rationalize(int argc, VALUE *argv, VALUE self) } /* :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) 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 e289eea2c2..a0cdb5b6fd 100644 --- a/test/ruby/test_syntax.rb +++ b/test/ruby/test_syntax.rb @@ -1730,6 +1730,21 @@ eom 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 643f264be4..eec5108707 100644 --- a/version.h +++ b/version.h @@ -12,7 +12,7 @@ # 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