summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2021-06-03 13:26:11 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2021-06-03 15:11:18 +0900
commit9f3888d6a3387773c8707b7971ce64c60df33d36 (patch)
treefae4b74a9d319ec899399d84cb9d6bd43c27a480
parent37eb5e74395f148782f7d67b5218fb2e66b113d7 (diff)
Warn more duplicate literal hash keys
Following non-special_const literals: * T_REGEXP
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/4548
-rw-r--r--compile.c5
-rw-r--r--internal/re.h2
-rw-r--r--parse.y1
-rw-r--r--re.c4
-rw-r--r--test/ruby/test_literal.rb1
5 files changed, 10 insertions, 3 deletions
diff --git a/compile.c b/compile.c
index 1b23d2133b..3139e9807f 100644
--- a/compile.c
+++ b/compile.c
@@ -2011,6 +2011,9 @@ rb_iseq_cdhash_cmp(VALUE val, VALUE lit)
const struct RComplex *comp2 = RCOMPLEX(lit);
return rb_iseq_cdhash_cmp(comp1->real, comp2->real) || rb_iseq_cdhash_cmp(comp1->imag, comp2->imag);
}
+ else if (tlit == T_REGEXP) {
+ return rb_reg_equal(val, lit) ? 0 : -1;
+ }
else {
UNREACHABLE_RETURN(-1);
}
@@ -2033,6 +2036,8 @@ rb_iseq_cdhash_hash(VALUE a)
return rb_rational_hash(a);
case T_COMPLEX:
return rb_complex_hash(a);
+ case T_REGEXP:
+ return NUM2LONG(rb_reg_hash(a));
default:
UNREACHABLE_RETURN(0);
}
diff --git a/internal/re.h b/internal/re.h
index 28fa3fb51c..a19ad934f7 100644
--- a/internal/re.h
+++ b/internal/re.h
@@ -18,6 +18,8 @@ VALUE rb_reg_check_preprocess(VALUE);
long rb_reg_search0(VALUE, VALUE, long, int, int);
VALUE rb_reg_match_p(VALUE re, VALUE str, long pos);
bool rb_reg_start_with_p(VALUE re, VALUE str);
+VALUE rb_reg_hash(VALUE re);
+VALUE rb_reg_equal(VALUE re1, VALUE re2);
void rb_backref_set_string(VALUE string, long pos, long len);
void rb_match_unbusy(VALUE);
int rb_match_count(VALUE match);
diff --git a/parse.y b/parse.y
index 0b69bc1d7e..e333730935 100644
--- a/parse.y
+++ b/parse.y
@@ -12189,7 +12189,6 @@ hash_literal_key_p(VALUE k)
{
switch (OBJ_BUILTIN_TYPE(k)) {
case T_NODE:
- case T_REGEXP:
return false;
default:
return true;
diff --git a/re.c b/re.c
index 5809d26bf3..64078aefd2 100644
--- a/re.c
+++ b/re.c
@@ -3009,7 +3009,7 @@ static st_index_t reg_hash(VALUE re);
* See also Object#hash.
*/
-static VALUE
+VALUE
rb_reg_hash(VALUE re)
{
st_index_t hashval = reg_hash(re);
@@ -3043,7 +3043,7 @@ reg_hash(VALUE re)
* /abc/u == /abc/n #=> false
*/
-static VALUE
+VALUE
rb_reg_equal(VALUE re1, VALUE re2)
{
if (re1 == re2) return Qtrue;
diff --git a/test/ruby/test_literal.rb b/test/ruby/test_literal.rb
index ed93b74cff..579a39dee8 100644
--- a/test/ruby/test_literal.rb
+++ b/test/ruby/test_literal.rb
@@ -484,6 +484,7 @@ class TestRubyLiteral < Test::Unit::TestCase
'1.0r',
'1.0i',
'1.72723e-77',
+ '//',
) do |key|
assert_warning(/key #{Regexp.quote(eval(key).inspect)} is duplicated/) do
eval("{#{key} => :bar, #{key} => :foo}")