summaryrefslogtreecommitdiff
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2019-09-05 19:25:34 -0700
committerJeremy Evans <code@jeremyevans.net>2019-09-06 19:41:23 -0700
commit37a2c660aa4f4aacfd6a56651b10124e3ac01321 (patch)
treee31ede184f37489e1cda4ae2400e6424a03ffb39 /vm_insnhelper.c
parent3fafc549ba909e986917f2b6b96eb14624c26329 (diff)
Convert keyword argument to required positional hash argument for Class#new, Method#call, UnboundMethod#bind_call
Also add keyword argument separation warnings for Class#new and Method#call. To allow for keyword argument to required positional hash converstion in cfuncs, add a vm frame flag indicating the cfunc was called with an empty keyword hash (which was removed before calling the cfunc). The cfunc can check this frame flag and add back an empty hash if it is passing its arguments to another Ruby method. Add rb_empty_keyword_given_p function for checking if called with an empty keyword hash, and rb_add_empty_keyword for adding back an empty hash to argv. All of this empty keyword argument support is only for 2.7. It will be removed in 3.0 as Ruby 3 will not convert empty keyword arguments to required positional hash arguments. Comment all of the relevent code to make it obvious this is expected to be removed. Add rb_funcallv_kw as an public C-API function, just like rb_funcallv but with a keyword flag. This is used by rb_obj_call_init (internals of Class#new). This also required expected call_type enum with CALL_FCALL_KW, similar to the recent addition of CALL_PUBLIC_KW. Add rb_vm_call_kw as a internal function, used by call_method_data (internals of Method#call and UnboundMethod#bind_call). Add tests for UnboundMethod#bind_call keyword handling.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/2432
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index c04c620b44..a83e3a952a 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -2206,8 +2206,9 @@ vm_method_cfunc_entry(const rb_callable_method_entry_t *me)
return UNALIGNED_MEMBER_PTR(me->def, body.cfunc);
}
+/* -- Remove empty_kw_splat In 3.0 -- */
static VALUE
-vm_call_cfunc_with_frame(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc)
+vm_call_cfunc_with_frame(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc, int empty_kw_splat)
{
VALUE val;
const rb_callable_method_entry_t *me = cc->me;
@@ -2223,6 +2224,9 @@ vm_call_cfunc_with_frame(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp
if (UNLIKELY(calling->kw_splat)) {
frame_type |= VM_FRAME_FLAG_CFRAME_KW;
}
+ else if (UNLIKELY(empty_kw_splat)) {
+ frame_type |= VM_FRAME_FLAG_CFRAME_EMPTY_KW;
+ }
RUBY_DTRACE_CMETHOD_ENTRY_HOOK(ec, me->owner, me->def->original_id);
EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, recv, me->def->original_id, ci->mid, me->owner, Qundef);
@@ -2249,10 +2253,14 @@ vm_call_cfunc_with_frame(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp
static VALUE
vm_call_cfunc(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc)
{
+ int empty_kw_splat = calling->kw_splat;
RB_DEBUG_COUNTER_INC(ccf_cfunc);
CALLER_SETUP_ARG(reg_cfp, calling, ci);
- return vm_call_cfunc_with_frame(ec, reg_cfp, calling, ci, cc);
+ if (empty_kw_splat && calling->kw_splat) {
+ empty_kw_splat = 0;
+ }
+ return vm_call_cfunc_with_frame(ec, reg_cfp, calling, ci, cc, empty_kw_splat);
}
static VALUE