mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Only promote last hash to keyword if all keys are symbols
If all keys are not symbols, then the non-symbol keys would not be treated as keywords in previous versions. It doesn't make sense to treat these hashes as keywords to break compatibility and warn about behavior changes in Ruby 2.7 when the Ruby 3.0 behavior will be the same as the Ruby 2.6 for these hashes.
This commit is contained in:
parent
e0b4599bba
commit
9c2e165f7d
Notes:
git
2019-08-31 04:40:17 +09:00
1 changed files with 29 additions and 6 deletions
35
vm_args.c
35
vm_args.c
|
@ -184,11 +184,34 @@ args_rest_array(struct args_info *args)
|
|||
}
|
||||
|
||||
static int
|
||||
keyword_hash_p(VALUE *kw_hash_ptr, VALUE *rest_hash_ptr)
|
||||
keyword_hash_symbol_p(st_data_t key, st_data_t val, st_data_t arg)
|
||||
{
|
||||
if (SYMBOL_P((VALUE)key)) {
|
||||
return ST_CONTINUE;
|
||||
}
|
||||
|
||||
*(VALUE*)arg = (VALUE)0;
|
||||
return ST_STOP;
|
||||
}
|
||||
|
||||
static int
|
||||
keyword_hash_only_symbol_p(VALUE hash)
|
||||
{
|
||||
VALUE all_symbols = (VALUE)(1);
|
||||
rb_hash_stlike_foreach(hash, keyword_hash_symbol_p, (st_data_t)(&all_symbols));
|
||||
return (int)all_symbols;
|
||||
}
|
||||
|
||||
static int
|
||||
keyword_hash_p(VALUE *kw_hash_ptr, VALUE *rest_hash_ptr, int check_only_symbol)
|
||||
{
|
||||
*rest_hash_ptr = rb_check_hash_type(*kw_hash_ptr);
|
||||
|
||||
if (!NIL_P(*rest_hash_ptr)) {
|
||||
if (check_only_symbol && !keyword_hash_only_symbol_p(*rest_hash_ptr)) {
|
||||
*kw_hash_ptr = Qnil;
|
||||
return FALSE;
|
||||
}
|
||||
*kw_hash_ptr = *rest_hash_ptr;
|
||||
*rest_hash_ptr = Qfalse;
|
||||
return TRUE;
|
||||
|
@ -200,7 +223,7 @@ keyword_hash_p(VALUE *kw_hash_ptr, VALUE *rest_hash_ptr)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
args_pop_keyword_hash(struct args_info *args, VALUE *kw_hash_ptr)
|
||||
args_pop_keyword_hash(struct args_info *args, VALUE *kw_hash_ptr, int check_only_symbol)
|
||||
{
|
||||
VALUE rest_hash;
|
||||
|
||||
|
@ -209,7 +232,7 @@ args_pop_keyword_hash(struct args_info *args, VALUE *kw_hash_ptr)
|
|||
VM_ASSERT(args->argc > 0);
|
||||
*kw_hash_ptr = args->argv[args->argc-1];
|
||||
|
||||
if (keyword_hash_p(kw_hash_ptr, &rest_hash)) {
|
||||
if (keyword_hash_p(kw_hash_ptr, &rest_hash, check_only_symbol)) {
|
||||
if (rest_hash) {
|
||||
args->argv[args->argc-1] = rest_hash;
|
||||
}
|
||||
|
@ -225,7 +248,7 @@ args_pop_keyword_hash(struct args_info *args, VALUE *kw_hash_ptr)
|
|||
if (len > 0) {
|
||||
*kw_hash_ptr = RARRAY_AREF(args->rest, len - 1);
|
||||
|
||||
if (keyword_hash_p(kw_hash_ptr, &rest_hash)) {
|
||||
if (keyword_hash_p(kw_hash_ptr, &rest_hash, check_only_symbol)) {
|
||||
if (rest_hash) {
|
||||
RARRAY_ASET(args->rest, len - 1, rest_hash);
|
||||
}
|
||||
|
@ -672,11 +695,11 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
|
|||
(kw_splat && given_argc > max_argc)) &&
|
||||
args->kw_argv == NULL) {
|
||||
if (((kw_flag & (VM_CALL_KWARG | VM_CALL_KW_SPLAT)) || !ec->cfp->iseq /* called from C */)) {
|
||||
if (args_pop_keyword_hash(args, &keyword_hash)) {
|
||||
if (args_pop_keyword_hash(args, &keyword_hash, 0)) {
|
||||
given_argc--;
|
||||
}
|
||||
}
|
||||
else if (args_pop_keyword_hash(args, &keyword_hash)) {
|
||||
else if (args_pop_keyword_hash(args, &keyword_hash, 1)) {
|
||||
/* Warn the following:
|
||||
* def foo(k:1) p [k]; end
|
||||
* foo({k:42}) #=> 42
|
||||
|
|
Loading…
Add table
Reference in a new issue