aboutsummaryrefslogtreecommitdiffstats
path: root/vm_eval.c
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2019-10-04 12:51:57 -0700
committerJeremy Evans <code@jeremyevans.net>2020-01-02 18:40:45 -0800
commitbeae6cbf0fd8b6619e5212552de98022d4c4d4d4 (patch)
treea926f619ed39569df4e93ec31157acdb78796379 /vm_eval.c
parent8ba261c7546e3cd12ff6870bb41dd0a0bee32ba8 (diff)
downloadruby-beae6cbf0fd8b6619e5212552de98022d4c4d4d4.tar.gz
Fully separate positional arguments and keyword arguments
This removes the warnings added in 2.7, and changes the behavior so that a final positional hash is not treated as keywords or vice-versa. To handle the arg_setup_block splat case correctly with keyword arguments, we need to check if we are taking a keyword hash. That case didn't have a test, but it affects real-world code, so add a test for it. This removes rb_empty_keyword_given_p() and related code, as that is not needed in Ruby 3. The empty keyword case is the same as the no keyword case in Ruby 3. This changes rb_scan_args to implement keyword argument separation for C functions when the : character is used. For backwards compatibility, it returns a duped hash. This is a bad idea for performance, but not duping the hash breaks at least Enumerator::ArithmeticSequence#inspect. Instead of having RB_PASS_CALLED_KEYWORDS be a number, simplify the code by just making it be rb_keyword_given_p().
Diffstat (limited to 'vm_eval.c')
-rw-r--r--vm_eval.c106
1 files changed, 17 insertions, 89 deletions
diff --git a/vm_eval.c b/vm_eval.c
index 24d8dcfdf6..cbed304e25 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -69,7 +69,6 @@ vm_call0_cfunc_with_frame(rb_execution_context_t* ec, struct rb_calling_info *ca
if (calling->kw_splat) {
if (argc > 0 && RB_TYPE_P(argv[argc-1], T_HASH) && RHASH_EMPTY_P(argv[argc-1])) {
- frame_flags |= VM_FRAME_FLAG_CFRAME_EMPTY_KW;
argc--;
}
else {
@@ -144,12 +143,7 @@ vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, struc
calling->argc > 0 &&
RB_TYPE_P(argv[calling->argc-1], T_HASH) &&
RHASH_EMPTY_P(argv[calling->argc-1])) {
- if (calling->argc == 1) {
- rb_warn("Passing the keyword argument as the last hash parameter is deprecated");
- }
- else {
- calling->argc--;
- }
+ calling->argc--;
}
rb_check_arity(calling->argc, 1, 1);
@@ -232,42 +226,10 @@ vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, struc
return ret;
}
-/* Caller should keep the reference to the return value until argv becomes useless. */
-MJIT_FUNC_EXPORTED VALUE
-rb_adjust_argv_kw_splat(int *argc, const VALUE **argv, int *kw_splat)
-{
- if (*kw_splat == RB_PASS_CALLED_KEYWORDS || *kw_splat == RB_PASS_EMPTY_KEYWORDS) {
- if (*kw_splat == RB_PASS_EMPTY_KEYWORDS || rb_empty_keyword_given_p()) {
- int n = *argc;
- VALUE v;
- VALUE *ptr = rb_alloc_tmp_buffer2(&v, n+1, sizeof(VALUE));
- if (n) memcpy(ptr, *argv, sizeof(VALUE)*n);
- ptr[n] = rb_hash_new();
- *argc = ++n;
- *argv = ptr;
- *kw_splat = 1;
- return v;
- }
- else {
- *kw_splat = rb_keyword_given_p();
- }
- }
-
- if (*kw_splat && (*argc == 0 || !RB_TYPE_P((*argv)[(*argc)-1], T_HASH))) {
- rb_warn("Keyword flag passed calling internal method, but last entry is not a hash, unsetting keyword flag");
- *kw_splat = 0;
- }
-
- return 0;
-}
-
MJIT_FUNC_EXPORTED VALUE
rb_vm_call_kw(rb_execution_context_t *ec, VALUE recv, VALUE id, int argc, const VALUE *argv, const rb_callable_method_entry_t *me, int kw_splat)
{
- VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
- VALUE ret = rb_vm_call0(ec, recv, id, argc, argv, me, kw_splat);
- rb_free_tmp_buffer(&v);
- return ret;
+ return rb_vm_call0(ec, recv, id, argc, argv, me, kw_splat);
}
static inline VALUE
@@ -961,10 +923,7 @@ rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
VALUE
rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
{
- VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
- VALUE ret = rb_call(recv, mid, argc, argv, kw_splat ? CALL_FCALL_KW : CALL_FCALL);
- rb_free_tmp_buffer(&v);
- return ret;
+ return rb_call(recv, mid, argc, argv, kw_splat ? CALL_FCALL_KW : CALL_FCALL);
}
/*!
@@ -985,10 +944,7 @@ rb_funcallv_public(VALUE recv, ID mid, int argc, const VALUE *argv)
VALUE
rb_funcallv_public_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
{
- VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
- VALUE ret = rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC);
- rb_free_tmp_buffer(&v);
- return ret;
+ return rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC);
}
/*!
@@ -1038,12 +994,8 @@ rb_funcall_passing_block(VALUE recv, ID mid, int argc, const VALUE *argv)
VALUE
rb_funcall_passing_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
{
- VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
- VALUE ret;
PASS_PASSED_BLOCK_HANDLER();
- ret = rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC);
- rb_free_tmp_buffer(&v);
- return ret;
+ return rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC);
}
VALUE
@@ -1063,10 +1015,7 @@ rb_funcall_with_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE
vm_passed_block_handler_set(GET_EC(), passed_procval);
}
- VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
- VALUE ret = rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC);
- rb_free_tmp_buffer(&v);
- return ret;
+ return rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC);
}
static VALUE *
@@ -1140,10 +1089,7 @@ send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope)
static VALUE
send_internal_kw(int argc, const VALUE *argv, VALUE recv, call_type scope)
{
- VALUE v=0, ret;
- int kw_splat = RB_PASS_CALLED_KEYWORDS;
- v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
- if (kw_splat) {
+ if (rb_keyword_given_p()) {
switch (scope) {
case CALL_PUBLIC:
scope = CALL_PUBLIC_KW;
@@ -1155,9 +1101,7 @@ send_internal_kw(int argc, const VALUE *argv, VALUE recv, call_type scope)
break;
}
}
- ret = send_internal(argc, argv, recv, scope);
- rb_free_tmp_buffer(&v);
- return ret;
+ return send_internal(argc, argv, recv, scope);
}
/*
@@ -1215,10 +1159,7 @@ rb_f_public_send(int argc, VALUE *argv, VALUE recv)
static inline VALUE
rb_yield_0_kw(int argc, const VALUE * argv, int kw_splat)
{
- VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
- VALUE ret = vm_yield(GET_EC(), argc, argv, kw_splat);
- rb_free_tmp_buffer(&v);
- return ret;
+ return vm_yield(GET_EC(), argc, argv, kw_splat);
}
static inline VALUE
@@ -1314,13 +1255,9 @@ rb_yield_force_blockarg(VALUE values)
VALUE
rb_yield_block(RB_BLOCK_CALL_FUNC_ARGLIST(val, arg))
{
- int kw_splat = RB_PASS_CALLED_KEYWORDS;
- VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
- VALUE ret = vm_yield_with_block(GET_EC(), argc, argv,
- NIL_P(blockarg) ? VM_BLOCK_HANDLER_NONE : blockarg,
- kw_splat);
- rb_free_tmp_buffer(&v);
- return ret;
+ return vm_yield_with_block(GET_EC(), argc, argv,
+ NIL_P(blockarg) ? VM_BLOCK_HANDLER_NONE : blockarg,
+ rb_keyword_given_p());
}
static VALUE
@@ -1486,15 +1423,12 @@ rb_block_call_kw(VALUE obj, ID mid, int argc, const VALUE * argv,
{
struct iter_method_arg arg;
- VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
arg.obj = obj;
arg.mid = mid;
arg.argc = argc;
arg.argv = argv;
arg.kw_splat = kw_splat;
- VALUE ret = rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
- rb_free_tmp_buffer(&v);
- return ret;
+ return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
}
VALUE
@@ -1839,9 +1773,6 @@ yield_under(VALUE under, VALUE self, int argc, const VALUE *argv, int kw_splat)
const VALUE *ep = NULL;
rb_cref_t *cref;
int is_lambda = FALSE;
- VALUE v = 0, ret;
-
- v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
if (block_handler != VM_BLOCK_HANDLER_NONE) {
again:
@@ -1861,10 +1792,9 @@ yield_under(VALUE under, VALUE self, int argc, const VALUE *argv, int kw_splat)
block_handler = vm_proc_to_block_handler(VM_BH_TO_PROC(block_handler));
goto again;
case block_handler_type_symbol:
- ret = rb_sym_proc_call(SYM2ID(VM_BH_TO_SYMBOL(block_handler)),
- argc, argv, kw_splat, VM_BLOCK_HANDLER_NONE);
- rb_free_tmp_buffer(&v);
- return ret;
+ return rb_sym_proc_call(SYM2ID(VM_BH_TO_SYMBOL(block_handler)),
+ argc, argv, kw_splat,
+ VM_BLOCK_HANDLER_NONE);
}
new_captured.self = self;
@@ -1874,9 +1804,7 @@ yield_under(VALUE under, VALUE self, int argc, const VALUE *argv, int kw_splat)
}
cref = vm_cref_push(ec, under, ep, TRUE);
- ret = vm_yield_with_cref(ec, argc, argv, kw_splat, cref, is_lambda);
- rb_free_tmp_buffer(&v);
- return ret;
+ return vm_yield_with_cref(ec, argc, argv, kw_splat, cref, is_lambda);
}
VALUE