Warn more duplicate literal hash keys
Following non-special_const literals: * T_BIGNUM * T_FLOAT (non-flonum) * T_RATIONAL * T_COMPLEX
This commit is contained in:
parent
a023db49bf
commit
37eb5e7439
Notes:
git
2021-06-03 15:11:39 +09:00
16
compile.c
16
compile.c
@ -1967,8 +1967,8 @@ iseq_set_local_table(rb_iseq_t *iseq, const ID *tbl)
|
|||||||
return COMPILE_OK;
|
return COMPILE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
cdhash_cmp(VALUE val, VALUE lit)
|
rb_iseq_cdhash_cmp(VALUE val, VALUE lit)
|
||||||
{
|
{
|
||||||
int tval, tlit;
|
int tval, tlit;
|
||||||
|
|
||||||
@ -2004,20 +2004,20 @@ cdhash_cmp(VALUE val, VALUE lit)
|
|||||||
else if (tlit == T_RATIONAL) {
|
else if (tlit == T_RATIONAL) {
|
||||||
const struct RRational *rat1 = RRATIONAL(val);
|
const struct RRational *rat1 = RRATIONAL(val);
|
||||||
const struct RRational *rat2 = RRATIONAL(lit);
|
const struct RRational *rat2 = RRATIONAL(lit);
|
||||||
return cdhash_cmp(rat1->num, rat2->num) || cdhash_cmp(rat1->den, rat2->den);
|
return rb_iseq_cdhash_cmp(rat1->num, rat2->num) || rb_iseq_cdhash_cmp(rat1->den, rat2->den);
|
||||||
}
|
}
|
||||||
else if (tlit == T_COMPLEX) {
|
else if (tlit == T_COMPLEX) {
|
||||||
const struct RComplex *comp1 = RCOMPLEX(val);
|
const struct RComplex *comp1 = RCOMPLEX(val);
|
||||||
const struct RComplex *comp2 = RCOMPLEX(lit);
|
const struct RComplex *comp2 = RCOMPLEX(lit);
|
||||||
return cdhash_cmp(comp1->real, comp2->real) || cdhash_cmp(comp1->imag, comp2->imag);
|
return rb_iseq_cdhash_cmp(comp1->real, comp2->real) || rb_iseq_cdhash_cmp(comp1->imag, comp2->imag);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
UNREACHABLE_RETURN(-1);
|
UNREACHABLE_RETURN(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static st_index_t
|
st_index_t
|
||||||
cdhash_hash(VALUE a)
|
rb_iseq_cdhash_hash(VALUE a)
|
||||||
{
|
{
|
||||||
switch (OBJ_BUILTIN_TYPE(a)) {
|
switch (OBJ_BUILTIN_TYPE(a)) {
|
||||||
case -1:
|
case -1:
|
||||||
@ -2039,8 +2039,8 @@ cdhash_hash(VALUE a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct st_hash_type cdhash_type = {
|
static const struct st_hash_type cdhash_type = {
|
||||||
cdhash_cmp,
|
rb_iseq_cdhash_cmp,
|
||||||
cdhash_hash,
|
rb_iseq_cdhash_hash,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cdhash_set_label_struct {
|
struct cdhash_set_label_struct {
|
||||||
|
@ -20,6 +20,8 @@ int rb_dvar_defined(ID, const struct rb_iseq_struct *);
|
|||||||
int rb_local_defined(ID, const struct rb_iseq_struct *);
|
int rb_local_defined(ID, const struct rb_iseq_struct *);
|
||||||
const char *rb_insns_name(int i);
|
const char *rb_insns_name(int i);
|
||||||
VALUE rb_insns_name_array(void);
|
VALUE rb_insns_name_array(void);
|
||||||
|
int rb_iseq_cdhash_cmp(VALUE val, VALUE lit);
|
||||||
|
st_index_t rb_iseq_cdhash_hash(VALUE a);
|
||||||
|
|
||||||
/* iseq.c */
|
/* iseq.c */
|
||||||
int rb_vm_insn_addr2insn(const void *);
|
int rb_vm_insn_addr2insn(const void *);
|
||||||
|
34
parse.y
34
parse.y
@ -12184,10 +12184,42 @@ append_literal_keys(st_data_t k, st_data_t v, st_data_t h)
|
|||||||
return ST_CONTINUE;
|
return ST_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
hash_literal_key_p(VALUE k)
|
||||||
|
{
|
||||||
|
switch (OBJ_BUILTIN_TYPE(k)) {
|
||||||
|
case T_NODE:
|
||||||
|
case T_REGEXP:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
literal_cmp(VALUE val, VALUE lit)
|
||||||
|
{
|
||||||
|
if (val == lit) return 0;
|
||||||
|
if (!hash_literal_key_p(val) || !hash_literal_key_p(lit)) return -1;
|
||||||
|
return rb_iseq_cdhash_cmp(val, lit);
|
||||||
|
}
|
||||||
|
|
||||||
|
static st_index_t
|
||||||
|
literal_hash(VALUE a)
|
||||||
|
{
|
||||||
|
if (!hash_literal_key_p(a)) return (st_index_t)a;
|
||||||
|
return rb_iseq_cdhash_hash(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct st_hash_type literal_type = {
|
||||||
|
literal_cmp,
|
||||||
|
literal_hash,
|
||||||
|
};
|
||||||
|
|
||||||
static NODE *
|
static NODE *
|
||||||
remove_duplicate_keys(struct parser_params *p, NODE *hash)
|
remove_duplicate_keys(struct parser_params *p, NODE *hash)
|
||||||
{
|
{
|
||||||
st_table *literal_keys = st_init_numtable_with_size(hash->nd_alen / 2);
|
st_table *literal_keys = st_init_table_with_size(&literal_type, hash->nd_alen / 2);
|
||||||
NODE *result = 0;
|
NODE *result = 0;
|
||||||
rb_code_location_t loc = hash->nd_loc;
|
rb_code_location_t loc = hash->nd_loc;
|
||||||
while (hash && hash->nd_head && hash->nd_next) {
|
while (hash && hash->nd_head && hash->nd_next) {
|
||||||
|
@ -480,6 +480,10 @@ class TestRubyLiteral < Test::Unit::TestCase
|
|||||||
'"a"',
|
'"a"',
|
||||||
'1000',
|
'1000',
|
||||||
'1.0',
|
'1.0',
|
||||||
|
'1_000_000_000_000_000_000_000',
|
||||||
|
'1.0r',
|
||||||
|
'1.0i',
|
||||||
|
'1.72723e-77',
|
||||||
) do |key|
|
) do |key|
|
||||||
assert_warning(/key #{Regexp.quote(eval(key).inspect)} is duplicated/) do
|
assert_warning(/key #{Regexp.quote(eval(key).inspect)} is duplicated/) do
|
||||||
eval("{#{key} => :bar, #{key} => :foo}")
|
eval("{#{key} => :bar, #{key} => :foo}")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user