mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
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]
This commit is contained in:
parent
773c690f25
commit
2bc293e899
Notes:
git
2021-05-12 10:31:14 +09:00
5 changed files with 26 additions and 3 deletions
|
@ -2807,6 +2807,7 @@ compile.$(OBJEXT): $(top_srcdir)/internal/hash.h
|
||||||
compile.$(OBJEXT): $(top_srcdir)/internal/imemo.h
|
compile.$(OBJEXT): $(top_srcdir)/internal/imemo.h
|
||||||
compile.$(OBJEXT): $(top_srcdir)/internal/numeric.h
|
compile.$(OBJEXT): $(top_srcdir)/internal/numeric.h
|
||||||
compile.$(OBJEXT): $(top_srcdir)/internal/object.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/re.h
|
||||||
compile.$(OBJEXT): $(top_srcdir)/internal/serial.h
|
compile.$(OBJEXT): $(top_srcdir)/internal/serial.h
|
||||||
compile.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
|
compile.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "internal/hash.h"
|
#include "internal/hash.h"
|
||||||
#include "internal/numeric.h"
|
#include "internal/numeric.h"
|
||||||
#include "internal/object.h"
|
#include "internal/object.h"
|
||||||
|
#include "internal/rational.h"
|
||||||
#include "internal/re.h"
|
#include "internal/re.h"
|
||||||
#include "internal/symbol.h"
|
#include "internal/symbol.h"
|
||||||
#include "internal/thread.h"
|
#include "internal/thread.h"
|
||||||
|
@ -2004,6 +2005,10 @@ cdhash_cmp(VALUE val, VALUE lit)
|
||||||
else if (tlit == T_FLOAT) {
|
else if (tlit == T_FLOAT) {
|
||||||
return rb_float_cmp(lit, val);
|
return rb_float_cmp(lit, val);
|
||||||
}
|
}
|
||||||
|
else if (tlit == T_RATIONAL) {
|
||||||
|
/* Rational literals don't have fractions. */
|
||||||
|
return cdhash_cmp(val, rb_rational_num(lit));
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
UNREACHABLE_RETURN(-1);
|
UNREACHABLE_RETURN(-1);
|
||||||
}
|
}
|
||||||
|
@ -2022,6 +2027,8 @@ cdhash_hash(VALUE a)
|
||||||
return FIX2LONG(rb_big_hash(a));
|
return FIX2LONG(rb_big_hash(a));
|
||||||
case T_FLOAT:
|
case T_FLOAT:
|
||||||
return rb_dbl_long_hash(RFLOAT_VALUE(a));
|
return rb_dbl_long_hash(RFLOAT_VALUE(a));
|
||||||
|
case T_RATIONAL:
|
||||||
|
return rb_rational_hash(a);
|
||||||
default:
|
default:
|
||||||
UNREACHABLE_RETURN(0);
|
UNREACHABLE_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ VALUE rb_rational_div(VALUE self, VALUE other);
|
||||||
VALUE rb_lcm(VALUE x, VALUE y);
|
VALUE rb_lcm(VALUE x, VALUE y);
|
||||||
VALUE rb_rational_reciprocal(VALUE x);
|
VALUE rb_rational_reciprocal(VALUE x);
|
||||||
VALUE rb_cstr_to_rat(const char *, int);
|
VALUE rb_cstr_to_rat(const char *, int);
|
||||||
|
VALUE rb_rational_hash(VALUE self);
|
||||||
VALUE rb_rational_abs(VALUE self);
|
VALUE rb_rational_abs(VALUE self);
|
||||||
VALUE rb_rational_cmp(VALUE self, VALUE other);
|
VALUE rb_rational_cmp(VALUE self, VALUE other);
|
||||||
VALUE rb_rational_pow(VALUE self, VALUE other);
|
VALUE rb_rational_pow(VALUE self, VALUE other);
|
||||||
|
|
13
rational.c
13
rational.c
|
@ -1742,8 +1742,8 @@ nurat_rationalize(int argc, VALUE *argv, VALUE self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* :nodoc: */
|
/* :nodoc: */
|
||||||
static VALUE
|
st_index_t
|
||||||
nurat_hash(VALUE self)
|
rb_rational_hash(VALUE self)
|
||||||
{
|
{
|
||||||
st_index_t v, h[2];
|
st_index_t v, h[2];
|
||||||
VALUE n;
|
VALUE n;
|
||||||
|
@ -1754,9 +1754,16 @@ nurat_hash(VALUE self)
|
||||||
n = rb_hash(dat->den);
|
n = rb_hash(dat->den);
|
||||||
h[1] = NUM2LONG(n);
|
h[1] = NUM2LONG(n);
|
||||||
v = rb_memhash(h, sizeof(h));
|
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
|
static VALUE
|
||||||
f_format(VALUE self, VALUE (*func)(VALUE))
|
f_format(VALUE self, VALUE (*func)(VALUE))
|
||||||
{
|
{
|
||||||
|
|
|
@ -830,6 +830,13 @@ class Rational_Test < Test::Unit::TestCase
|
||||||
assert_raise(ZeroDivisionError) {Rational("1/0")}
|
assert_raise(ZeroDivisionError) {Rational("1/0")}
|
||||||
end
|
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
|
||||||
|
end
|
||||||
|
|
||||||
def test_Rational_with_invalid_exception
|
def test_Rational_with_invalid_exception
|
||||||
assert_raise(ArgumentError) {
|
assert_raise(ArgumentError) {
|
||||||
Rational("1/1", exception: 1)
|
Rational("1/1", exception: 1)
|
||||||
|
|
Loading…
Add table
Reference in a new issue