From beae6cbf0fd8b6619e5212552de98022d4c4d4d4 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Fri, 4 Oct 2019 12:51:57 -0700 Subject: 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(). --- thread.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'thread.c') diff --git a/thread.c b/thread.c index 16f3e1ffed..4faf04c1ce 100644 --- a/thread.c +++ b/thread.c @@ -681,7 +681,6 @@ thread_do_start(rb_thread_t *th) if (th->invoke_type == thread_invoke_type_proc) { VALUE args = th->invoke_arg.proc.args; int args_len = (int)RARRAY_LEN(args); - int kw_splat = th->invoke_arg.proc.kw_splat; const VALUE *args_ptr; VALUE procval = th->invoke_arg.proc.proc; rb_proc_t *proc; @@ -704,10 +703,11 @@ thread_do_start(rb_thread_t *th) args_ptr = RARRAY_CONST_PTR(args); } - rb_adjust_argv_kw_splat(&args_len, &args_ptr, &kw_splat); + vm_check_ints_blocking(th->ec); th->value = rb_vm_invoke_proc(th->ec, proc, args_len, args_ptr, - kw_splat, VM_BLOCK_HANDLER_NONE); + th->invoke_arg.proc.kw_splat, + VM_BLOCK_HANDLER_NONE); EXEC_EVENT_HOOK(th->ec, RUBY_EVENT_THREAD_END, th->self, 0, 0, 0, Qundef); } @@ -856,9 +856,7 @@ thread_create_core(VALUE thval, VALUE args, VALUE (*fn)(void *)) th->invoke_type = thread_invoke_type_proc; th->invoke_arg.proc.proc = rb_block_proc(); th->invoke_arg.proc.args = args; - th->invoke_arg.proc.kw_splat = rb_empty_keyword_given_p() ? - RB_PASS_EMPTY_KEYWORDS : - rb_keyword_given_p(); + th->invoke_arg.proc.kw_splat = rb_keyword_given_p(); } th->priority = current_th->priority; -- cgit v1.2.3