summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vm_args.c35
1 files changed, 29 insertions, 6 deletions
diff --git a/vm_args.c b/vm_args.c
index 35c435181a..9d5626ce97 100644
--- a/vm_args.c
+++ b/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