summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--class.c70
-rw-r--r--cont.c12
-rw-r--r--enumerator.c14
-rw-r--r--eval.c8
-rw-r--r--ext/-test-/scan_args/scan_args.c10
-rw-r--r--include/ruby/ruby.h78
-rw-r--r--internal/vm.h1
-rw-r--r--object.c4
-rw-r--r--proc.c5
-rw-r--r--test/ruby/test_proc.rb10
-rw-r--r--thread.c10
-rw-r--r--vm.c7
-rw-r--r--vm_args.c383
-rw-r--r--vm_core.h12
-rw-r--r--vm_eval.c106
-rw-r--r--vm_insnhelper.c45
16 files changed, 96 insertions, 679 deletions
diff --git a/class.c b/class.c
index bc64ff7795..e42ee0821c 100644
--- a/class.c
+++ b/class.c
@@ -1970,7 +1970,6 @@ rb_scan_args_parse(int kw_flag, int argc, const VALUE *argv, const char *fmt, st
const char *p = fmt;
VALUE *tmp_buffer = arg->tmp_buffer;
int keyword_given = 0;
- int empty_keyword_given = 0;
int last_hash_keyword = 0;
memset(arg, 0, sizeof(*arg));
@@ -1979,16 +1978,11 @@ rb_scan_args_parse(int kw_flag, int argc, const VALUE *argv, const char *fmt, st
switch (kw_flag) {
case RB_SCAN_ARGS_PASS_CALLED_KEYWORDS:
- if (!(keyword_given = rb_keyword_given_p())) {
- empty_keyword_given = rb_empty_keyword_given_p();
- }
+ keyword_given = rb_keyword_given_p();
break;
case RB_SCAN_ARGS_KEYWORDS:
keyword_given = 1;
break;
- case RB_SCAN_ARGS_EMPTY_KEYWORDS:
- empty_keyword_given = 1;
- break;
case RB_SCAN_ARGS_LAST_HASH_KEYWORDS:
last_hash_keyword = 1;
break;
@@ -2023,67 +2017,13 @@ rb_scan_args_parse(int kw_flag, int argc, const VALUE *argv, const char *fmt, st
}
arg->n_mand = arg->n_lead + arg->n_trail;
- /* capture an option hash - phase 1: pop */
- /* Ignore final positional hash if empty keywords given */
- if (argc > 0 && !(arg->f_hash && empty_keyword_given)) {
+ if (arg->f_hash && argc > 0) {
VALUE last = argv[argc - 1];
- if (arg->f_hash && arg->n_mand < argc) {
- if (keyword_given) {
- if (!RB_TYPE_P(last, T_HASH)) {
- rb_warn("Keyword flag set when calling rb_scan_args, but last entry is not a hash");
- }
- else {
- arg->hash = last;
- }
- }
- else if (NIL_P(last)) {
- /* For backwards compatibility, nil is taken as an empty
- option hash only if it is not ambiguous; i.e. '*' is
- not specified and arguments are given more than sufficient.
- This will be removed in Ruby 3. */
- if (!arg->f_var && arg->n_mand + arg->n_opt < argc) {
- rb_warn("The last argument is nil, treating as empty keywords");
- argc--;
- }
- }
- else {
- arg->hash = rb_check_hash_type(last);
- }
-
- /* Ruby 3: Remove if branch, as it will not attempt to split hashes */
- if (!NIL_P(arg->hash)) {
- VALUE opts = rb_extract_keywords(&arg->hash);
-
- if (!(arg->last_hash = arg->hash)) {
- if (!keyword_given && !last_hash_keyword) {
- /* Warn if treating positional as keyword, as in Ruby 3,
- this will be an error */
- rb_warn("Using the last argument as keyword parameters is deprecated");
- }
- argc--;
- }
- else {
- /* Warn if splitting either positional hash to keywords or keywords
- to positional hash, as in Ruby 3, no splitting will be done */
- rb_warn("The last argument is split into positional and keyword parameters");
- arg->last_idx = argc - 1;
- }
- arg->hash = opts ? opts : Qnil;
- }
+ if (keyword_given || (last_hash_keyword && RB_TYPE_P(last, T_HASH))) {
+ arg->hash = rb_hash_dup(last);
+ argc--;
}
- else if (arg->f_hash && keyword_given && arg->n_mand == argc) {
- /* Warn if treating keywords as positional, as in Ruby 3, this will be an error */
- rb_warn("Passing the keyword argument as the last hash parameter is deprecated");
- }
- }
- if (arg->f_hash && arg->n_mand == argc+1 && empty_keyword_given) {
- VALUE *ptr = rb_alloc_tmp_buffer2(tmp_buffer, argc+1, sizeof(VALUE));
- memcpy(ptr, argv, sizeof(VALUE)*argc);
- ptr[argc] = rb_hash_new();
- argc++;
- *(&argv) = ptr;
- rb_warn("Passing the keyword argument as the last hash parameter is deprecated");
}
arg->argc = argc;
diff --git a/cont.c b/cont.c
index 2365406d9e..d4a2bf9353 100644
--- a/cont.c
+++ b/cont.c
@@ -1790,8 +1790,6 @@ rb_fiber_new(rb_block_call_func_t func, VALUE obj)
static void rb_fiber_terminate(rb_fiber_t *fiber, int need_interrupt);
-#define PASS_KW_SPLAT (rb_empty_keyword_given_p() ? RB_PASS_EMPTY_KEYWORDS : rb_keyword_given_p())
-
void
rb_fiber_start(void)
{
@@ -1809,7 +1807,6 @@ rb_fiber_start(void)
rb_context_t *cont = &VAR_FROM_MEMORY(fiber)->cont;
int argc;
const VALUE *argv, args = cont->value;
- int kw_splat = cont->kw_splat;
GetProcPtr(fiber->first_proc, proc);
argv = (argc = cont->argc) > 1 ? RARRAY_CONST_PTR(args) : &args;
cont->value = Qnil;
@@ -1818,8 +1815,7 @@ rb_fiber_start(void)
th->ec->root_svar = Qfalse;
EXEC_EVENT_HOOK(th->ec, RUBY_EVENT_FIBER_SWITCH, th->self, 0, 0, 0, Qnil);
- rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
- cont->value = rb_vm_invoke_proc(th->ec, proc, argc, argv, kw_splat, VM_BLOCK_HANDLER_NONE);
+ cont->value = rb_vm_invoke_proc(th->ec, proc, argc, argv, cont->kw_splat, VM_BLOCK_HANDLER_NONE);
}
EC_POP_TAG();
@@ -2163,7 +2159,7 @@ rb_fiber_alive_p(VALUE fiber_value)
static VALUE
rb_fiber_m_resume(int argc, VALUE *argv, VALUE fiber)
{
- return rb_fiber_resume_kw(fiber, argc, argv, PASS_KW_SPLAT);
+ return rb_fiber_resume_kw(fiber, argc, argv, rb_keyword_given_p());
}
/*
@@ -2249,7 +2245,7 @@ rb_fiber_m_transfer(int argc, VALUE *argv, VALUE fiber_value)
{
rb_fiber_t *fiber = fiber_ptr(fiber_value);
fiber->transferred = 1;
- return fiber_switch(fiber, argc, argv, 0, PASS_KW_SPLAT);
+ return fiber_switch(fiber, argc, argv, 0, rb_keyword_given_p());
}
/*
@@ -2265,7 +2261,7 @@ rb_fiber_m_transfer(int argc, VALUE *argv, VALUE fiber_value)
static VALUE
rb_fiber_s_yield(int argc, VALUE *argv, VALUE klass)
{
- return rb_fiber_yield_kw(argc, argv, PASS_KW_SPLAT);
+ return rb_fiber_yield_kw(argc, argv, rb_keyword_given_p());
}
/*
diff --git a/enumerator.c b/enumerator.c
index 790818064f..fa30a59819 100644
--- a/enumerator.c
+++ b/enumerator.c
@@ -384,8 +384,6 @@ enumerator_allocate(VALUE klass)
return enum_obj;
}
-#define PASS_KW_SPLAT (rb_empty_keyword_given_p() ? RB_PASS_EMPTY_KEYWORDS : rb_keyword_given_p())
-
static VALUE
enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *size_fn, VALUE size, int kw_splat)
{
@@ -480,7 +478,7 @@ enumerator_initialize(int argc, VALUE *argv, VALUE obj)
meth = *argv++;
--argc;
}
- kw_splat = PASS_KW_SPLAT;
+ kw_splat = rb_keyword_given_p();
}
return enumerator_init(obj, recv, meth, argc, argv, 0, size, kw_splat);
@@ -535,10 +533,10 @@ rb_enumeratorize_with_size(VALUE obj, VALUE meth, int argc, const VALUE *argv, r
/* Similar effect as calling obj.to_enum, i.e. dispatching to either
Kernel#to_enum vs Lazy#to_enum */
if (RTEST(rb_obj_is_kind_of(obj, rb_cLazy)))
- return lazy_to_enum_i(obj, meth, argc, argv, size_fn, PASS_KW_SPLAT);
+ return lazy_to_enum_i(obj, meth, argc, argv, size_fn, rb_keyword_given_p());
else
return enumerator_init(enumerator_allocate(rb_cEnumerator),
- obj, meth, argc, argv, size_fn, Qnil, PASS_KW_SPLAT);
+ obj, meth, argc, argv, size_fn, Qnil, rb_keyword_given_p());
}
VALUE
@@ -1892,7 +1890,7 @@ lazy_add_method(VALUE obj, int argc, VALUE *argv, VALUE args, VALUE memo,
static VALUE
enumerable_lazy(VALUE obj)
{
- VALUE result = lazy_to_enum_i(obj, sym_each, 0, 0, lazyenum_size, PASS_KW_SPLAT);
+ VALUE result = lazy_to_enum_i(obj, sym_each, 0, 0, lazyenum_size, rb_keyword_given_p());
/* Qfalse indicates that the Enumerator::Lazy has no method name */
rb_ivar_set(result, id_method, Qfalse);
return result;
@@ -1940,7 +1938,7 @@ lazy_to_enum(int argc, VALUE *argv, VALUE self)
if (RTEST((super_meth = rb_hash_aref(lazy_use_super_method, meth)))) {
meth = super_meth;
}
- lazy = lazy_to_enum_i(self, meth, argc, argv, 0, PASS_KW_SPLAT);
+ lazy = lazy_to_enum_i(self, meth, argc, argv, 0, rb_keyword_given_p());
if (rb_block_given_p()) {
enumerator_ptr(lazy)->size = rb_block_proc();
}
@@ -3318,7 +3316,7 @@ rb_arith_seq_new(VALUE obj, VALUE meth, int argc, VALUE const *argv,
VALUE beg, VALUE end, VALUE step, int excl)
{
VALUE aseq = enumerator_init(enumerator_allocate(rb_cArithSeq),
- obj, meth, argc, argv, size_fn, Qnil, PASS_KW_SPLAT);
+ obj, meth, argc, argv, size_fn, Qnil, rb_keyword_given_p());
rb_ivar_set(aseq, id_begin, beg);
rb_ivar_set(aseq, id_end, end);
rb_ivar_set(aseq, id_step, step);
diff --git a/eval.c b/eval.c
index 4770327a72..429ecbe0d9 100644
--- a/eval.c
+++ b/eval.c
@@ -924,14 +924,6 @@ rb_keyword_given_p(void)
return rb_vm_cframe_keyword_p(GET_EC()->cfp);
}
-/* -- Remove In 3.0 -- */
-int rb_vm_cframe_empty_keyword_p(const rb_control_frame_t *cfp);
-int
-rb_empty_keyword_given_p(void)
-{
- return rb_vm_cframe_empty_keyword_p(GET_EC()->cfp);
-}
-
VALUE rb_eThreadError;
/*! Declares that the current method needs a block.
diff --git a/ext/-test-/scan_args/scan_args.c b/ext/-test-/scan_args/scan_args.c
index 9c374da66f..8696aad3c7 100644
--- a/ext/-test-/scan_args/scan_args.c
+++ b/ext/-test-/scan_args/scan_args.c
@@ -260,15 +260,6 @@ scan_args_k_lead_opt_hash(int argc, VALUE *argv, VALUE self)
}
static VALUE
-scan_args_e_lead_opt_hash(int argc, VALUE *argv, VALUE self)
-{
- VALUE args[4];
- int n = rb_scan_args_kw(RB_SCAN_ARGS_EMPTY_KEYWORDS, argc, argv, "11:", args+1, args+2, args+3);
- args[0] = INT2NUM(n);
- return rb_ary_new_from_values(numberof(args), args);
-}
-
-static VALUE
scan_args_n_lead_opt_hash(int argc, VALUE *argv, VALUE self)
{
VALUE args[4];
@@ -310,6 +301,5 @@ Init_scan_args(void)
rb_define_singleton_method(module, "opt_var_trail_hash", scan_args_opt_var_trail_hash, -1);
rb_define_singleton_method(module, "lead_opt_var_trail_hash", scan_args_lead_opt_var_trail_hash, -1);
rb_define_singleton_method(module, "k_lead_opt_hash", scan_args_k_lead_opt_hash, -1);
- rb_define_singleton_method(module, "e_lead_opt_hash", scan_args_e_lead_opt_hash, -1);
rb_define_singleton_method(module, "n_lead_opt_hash", scan_args_n_lead_opt_hash, -1);
}
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index 9b7c9842f8..d81c72e95b 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -1901,7 +1901,6 @@ VALUE rb_funcall_with_block_kw(VALUE, ID, int, const VALUE*, VALUE, int);
int rb_scan_args(int, const VALUE*, const char*, ...);
#define RB_SCAN_ARGS_PASS_CALLED_KEYWORDS 0
#define RB_SCAN_ARGS_KEYWORDS 1
-#define RB_SCAN_ARGS_EMPTY_KEYWORDS 2 /* Will be removed in 3.0 */
#define RB_SCAN_ARGS_LAST_HASH_KEYWORDS 3
int rb_scan_args_kw(int, int, const VALUE*, const char*, ...);
VALUE rb_call_super(int, const VALUE*);
@@ -1976,8 +1975,7 @@ VALUE rb_yield_splat_kw(VALUE, int);
VALUE rb_yield_block(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)); /* rb_block_call_func */
#define RB_NO_KEYWORDS 0
#define RB_PASS_KEYWORDS 1
-#define RB_PASS_EMPTY_KEYWORDS 2 /* Will be removed in 3.0 */
-#define RB_PASS_CALLED_KEYWORDS 3
+#define RB_PASS_CALLED_KEYWORDS rb_keyword_given_p()
int rb_keyword_given_p(void);
int rb_block_given_p(void);
void rb_need_block(void);
@@ -2331,9 +2329,6 @@ unsigned long ruby_strtoul(const char *str, char **endptr, int base);
PRINTF_ARGS(int ruby_snprintf(char *str, size_t n, char const *fmt, ...), 3, 4);
int ruby_vsnprintf(char *str, size_t n, char const *fmt, va_list ap);
-/* -- Remove In 3.0, Only public for rb_scan_args optimized version -- */
-int rb_empty_keyword_given_p(void);
-
#if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) && defined(HAVE_VA_ARGS_MACRO) && defined(__OPTIMIZE__)
# define rb_scan_args(argc,argvp,fmt,...) \
__builtin_choose_expr(__builtin_constant_p(fmt), \
@@ -2525,78 +2520,13 @@ rb_scan_args_set(int argc, const VALUE *argv,
int i, argi = 0, vari = 0, last_idx = -1;
VALUE *var, hash = Qnil, last_hash = 0;
const int n_mand = n_lead + n_trail;
- int keyword_given = rb_keyword_given_p();
- int empty_keyword_given = 0;
VALUE tmp_buffer = 0;
- if (!keyword_given) {
- empty_keyword_given = rb_empty_keyword_given_p();
+ if (f_hash && argc > 0 && rb_keyword_given_p()) {
+ hash = rb_hash_dup(argv[argc - 1]);
+ argc--;
}
- /* capture an option hash - phase 1: pop */
- /* Ignore final positional hash if empty keywords given */
- if (argc > 0 && !(f_hash && empty_keyword_given)) {
- VALUE last = argv[argc - 1];
-
- if (f_hash && n_mand < argc) {
- if (keyword_given) {
- if (!RB_TYPE_P(last, T_HASH)) {
- rb_warn("Keyword flag set when calling rb_scan_args, but last entry is not a hash");
- }
- else {
- hash = last;
- }
- }
- else if (NIL_P(last)) {
- /* For backwards compatibility, nil is taken as an empty
- option hash only if it is not ambiguous; i.e. '*' is
- not specified and arguments are given more than sufficient.
- This will be removed in Ruby 3. */
- if (!f_var && n_mand + n_opt < argc) {
- rb_warn("The last argument is nil, treating as empty keywords");
- argc--;
- }
- }
- else {
- hash = rb_check_hash_type(last);
- }
-
- /* Ruby 3: Remove if branch, as it will not attempt to split hashes */
- if (!NIL_P(hash)) {
- VALUE opts = rb_extract_keywords(&hash);
-
- if (!(last_hash = hash)) {
- if (!keyword_given) {
- /* Warn if treating positional as keyword, as in Ruby 3,
- this will be an error */
- rb_warn("Using the last argument as keyword parameters is deprecated");
- }
- argc--;
- }
- else {
- /* Warn if splitting either positional hash to keywords or keywords
- to positional hash, as in Ruby 3, no splitting will be done */
- rb_warn("The last argument is split into positional and keyword parameters");
- last_idx = argc - 1;
- }
- hash = opts ? opts : Qnil;
- }
- }
- else if (f_hash && keyword_given && n_mand == argc) {
- /* Warn if treating keywords as positional, as in Ruby 3, this will be an error */
- rb_warn("Passing the keyword argument as the last hash parameter is deprecated");
- }
- }
- if (f_hash && n_mand > 0 && n_mand == argc+1 && empty_keyword_given) {
- VALUE *ptr = (VALUE *)rb_alloc_tmp_buffer2(&tmp_buffer, argc+1, sizeof(VALUE));
- memcpy(ptr, argv, sizeof(VALUE)*argc);
- ptr[argc] = rb_hash_new();
- argc++;
- *(&argv) = ptr;
- rb_warn("Passing the keyword argument as the last hash parameter is deprecated");
- }
-
-
if (argc < n_mand) {
goto argc_error;
}
diff --git a/internal/vm.h b/internal/vm.h
index 1bd7a98f7a..c5986a1c24 100644
--- a/internal/vm.h
+++ b/internal/vm.h
@@ -138,7 +138,6 @@ VALUE rb_lambda_call(VALUE obj, ID mid, int argc, const VALUE *argv,
MJIT_SYMBOL_EXPORT_BEGIN
VALUE rb_vm_call0(struct rb_execution_context_struct *ec, VALUE recv, ID id, int argc, const VALUE *argv, const struct rb_callable_method_entry_struct *me, int kw_splat);
-VALUE rb_adjust_argv_kw_splat(int *argc, const VALUE **argv, int *kw_splat);
VALUE rb_vm_call_kw(struct rb_execution_context_struct *ec, VALUE recv, VALUE id, int argc, const VALUE *argv, const struct rb_callable_method_entry_struct *me, int kw_splat);
VALUE rb_make_no_method_exception(VALUE exc, VALUE format, VALUE obj, int argc, const VALUE *argv, int priv);
MJIT_SYMBOL_EXPORT_END
diff --git a/object.c b/object.c
index b5514322d2..f02b45af1c 100644
--- a/object.c
+++ b/object.c
@@ -4086,9 +4086,7 @@ rb_obj_dig(int argc, VALUE *argv, VALUE obj, VALUE notfound)
}
return rb_check_funcall_with_hook_kw(obj, id_dig, argc, argv,
no_dig_method, obj,
- rb_empty_keyword_given_p() ?
- RB_PASS_EMPTY_KEYWORDS :
- RB_NO_KEYWORDS);
+ RB_NO_KEYWORDS);
}
return obj;
}
diff --git a/proc.c b/proc.c
index 7094a021f3..5434e8daa7 100644
--- a/proc.c
+++ b/proc.c
@@ -955,14 +955,11 @@ rb_proc_call_kw(VALUE self, VALUE args, int kw_splat)
{
VALUE vret;
rb_proc_t *proc;
- VALUE v;
int argc = check_argc(RARRAY_LEN(args));
const VALUE *argv = RARRAY_CONST_PTR(args);
GetProcPtr(self, proc);
- v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
vret = rb_vm_invoke_proc(GET_EC(), proc, argc, argv,
kw_splat, VM_BLOCK_HANDLER_NONE);
- rb_free_tmp_buffer(&v);
RB_GC_GUARD(self);
RB_GC_GUARD(args);
return vret;
@@ -994,10 +991,8 @@ rb_proc_call_with_block_kw(VALUE self, int argc, const VALUE *argv, VALUE passed
rb_execution_context_t *ec = GET_EC();
VALUE vret;
rb_proc_t *proc;
- VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
GetProcPtr(self, proc);
vret = rb_vm_invoke_proc(ec, proc, argc, argv, kw_splat, proc_to_block_handler(passed_procval));
- rb_free_tmp_buffer(&v);
RB_GC_GUARD(self);
return vret;
}
diff --git a/test/ruby/test_proc.rb b/test/ruby/test_proc.rb
index 1f84b2eb84..fce1bd4a87 100644
--- a/test/ruby/test_proc.rb
+++ b/test/ruby/test_proc.rb
@@ -1087,6 +1087,16 @@ class TestProc < Test::Unit::TestCase
assert_equal([1,2,[3],4,5], r, "[ruby-core:19485]")
end
+ def test_proc_single_arg_with_keywords_accepted_and_yielded
+ def self.a
+ yield [], **{a: 1}
+ end
+ res = a do |arg, **opts|
+ [arg, opts]
+ end
+ assert_equal([[], {a: 1}], res)
+ end
+
def test_parameters
assert_equal([], proc {}.parameters)
assert_equal([], proc {||}.parameters)
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;
diff --git a/vm.c b/vm.c
index e432cb13aa..5dd78a5e83 100644
--- a/vm.c
+++ b/vm.c
@@ -119,13 +119,6 @@ rb_vm_cframe_keyword_p(const rb_control_frame_t *cfp)
return VM_FRAME_CFRAME_KW_P(cfp);
}
-/* -- Remove In 3.0 -- */
-int
-rb_vm_cframe_empty_keyword_p(const rb_control_frame_t *cfp)
-{
- return VM_FRAME_CFRAME_EMPTY_KW_P(cfp);
-}
-
VALUE
rb_vm_frame_block_handler(const rb_control_frame_t *cfp)
{
diff --git a/vm_args.c b/vm_args.c
index 7bf61cefe7..3558d6487f 100644
--- a/vm_args.c
+++ b/vm_args.c
@@ -187,124 +187,6 @@ args_rest_array(struct args_info *args)
return ary;
}
-#define KW_HASH_HAS_NO_KEYS 0
-#define KW_HASH_HAS_SYMBOL_KEY 1
-#define KW_HASH_HAS_OTHER_KEY 2
-#define KW_HASH_HAS_BOTH_KEYS 3
-
-static int
-keyword_hash_symbol_other_iter(st_data_t key, st_data_t val, st_data_t arg)
-{
- *(int*)arg |= SYMBOL_P((VALUE)key) ? KW_HASH_HAS_SYMBOL_KEY : KW_HASH_HAS_OTHER_KEY;
-
- if ((*(int*)arg & KW_HASH_HAS_BOTH_KEYS) == KW_HASH_HAS_BOTH_KEYS) {
- return ST_STOP;
- }
-
- return ST_CONTINUE;
-}
-
-static int
-keyword_hash_symbol_other(VALUE hash)
-{
- int symbol_other = KW_HASH_HAS_NO_KEYS;
- rb_hash_stlike_foreach(hash, keyword_hash_symbol_other_iter, (st_data_t)(&symbol_other));
- return symbol_other;
-}
-
-static int
-keyword_hash_split_iter(st_data_t key, st_data_t val, st_data_t arg)
-{
- if (SYMBOL_P((VALUE)key)) {
- rb_hash_aset((VALUE)arg, (VALUE)key, (VALUE)val);
- return ST_DELETE;
- }
-
- return ST_CONTINUE;
-}
-
-static void
-keyword_hash_split(VALUE *kw_hash_ptr, VALUE *rest_hash_ptr)
-{
- *kw_hash_ptr = rb_hash_new();
- rb_hash_stlike_foreach(*rest_hash_ptr, keyword_hash_split_iter, (st_data_t)(*kw_hash_ptr));
-}
-
-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) {
- switch (keyword_hash_symbol_other(*rest_hash_ptr)) {
- case KW_HASH_HAS_NO_KEYS:
- case KW_HASH_HAS_SYMBOL_KEY:
- break;
- case KW_HASH_HAS_OTHER_KEY:
- *kw_hash_ptr = Qnil;
- return FALSE;
- case KW_HASH_HAS_BOTH_KEYS:
- *rest_hash_ptr = rb_hash_dup(*rest_hash_ptr);
- keyword_hash_split(kw_hash_ptr, rest_hash_ptr);
- return TRUE;
- }
- }
- *kw_hash_ptr = *rest_hash_ptr;
- *rest_hash_ptr = Qfalse;
- return TRUE;
- }
- else {
- *kw_hash_ptr = Qnil;
- return FALSE;
- }
-}
-
-static VALUE
-args_pop_keyword_hash(struct args_info *args, VALUE *kw_hash_ptr, int check_only_symbol)
-{
- VALUE rest_hash;
-
- if (args->rest == Qfalse) {
- from_argv:
- VM_ASSERT(args->argc > 0);
- *kw_hash_ptr = args->argv[args->argc-1];
-
- if (keyword_hash_p(kw_hash_ptr, &rest_hash, check_only_symbol)) {
- if (rest_hash) {
- args->argv[args->argc-1] = rest_hash;
- }
- else {
- args->argc--;
- return TRUE;
- }
- }
- }
- else {
- long len = RARRAY_LEN(args->rest);
-
- if (len > 0) {
- *kw_hash_ptr = RARRAY_AREF(args->rest, len - 1);
-
- if (keyword_hash_p(kw_hash_ptr, &rest_hash, check_only_symbol)) {
- if (rest_hash) {
- RARRAY_ASET(args->rest, len - 1, rest_hash);
- }
- else {
- arg_rest_dup(args);
- rb_ary_pop(args->rest);
- return TRUE;
- }
- }
- }
- else {
- goto from_argv;
- }
- }
-
- return FALSE;
-}
-
static int
args_kw_argv_to_hash(struct args_info *args)
{
@@ -572,149 +454,10 @@ fill_keys_values(st_data_t key, st_data_t val, st_data_t ptr)
static inline int
ignore_keyword_hash_p(VALUE keyword_hash, const rb_iseq_t * const iseq)
{
- if (!(iseq->body->param.flags.has_kw) &&
- !(iseq->body->param.flags.has_kwrest)) {
- keyword_hash = rb_check_hash_type(keyword_hash);
-
- if (!NIL_P(keyword_hash) && RHASH_EMPTY_P(keyword_hash)) {
- return 1;
- }
- }
-
- return 0;
-}
-
-VALUE rb_iseq_location(const rb_iseq_t *iseq);
-
-/* -- Remove In 3.0 -- */
-
-/* This is a map from caller PC to a set of callee methods.
- * When a warning about keyword argument change is printed,
- * it keeps the pair of callee and caller.
- */
-static st_table *caller_to_callees = 0;
-
-static VALUE
-rb_warn_check(const rb_execution_context_t * const ec, const rb_iseq_t *const iseq)
-{
- if (!rb_warning_category_enabled_p(RB_WARN_CATEGORY_DEPRECATED)) return 1;
-
- if (!iseq) return 0;
-
- const st_data_t callee = (st_data_t)(iseq->body->iseq_unique_id * 2);
-
- const rb_control_frame_t * const cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
-
- if (!cfp) return 0;
-
- const st_data_t caller = (st_data_t)cfp->pc;
-
- if (!caller_to_callees) {
- caller_to_callees = st_init_numtable();
- }
-
- st_data_t val;
- if (st_lookup(caller_to_callees, caller, &val)) {
- st_table *callees;
-
- if (val & 1) {
- val &= ~(st_data_t)1;
- if (val == callee) return 1; /* already warned */
-
- callees = st_init_numtable();
- st_insert(callees, val, 1);
- }
- else {
- callees = (st_table *) val;
- if (st_is_member(callees, callee)) return 1; /* already warned */
- }
- st_insert(callees, callee, 1);
- st_insert(caller_to_callees, caller, (st_data_t) callees);
- }
- else {
- st_insert(caller_to_callees, caller, callee | 1);
- }
-
- return 0; /* not warned yet for the pair of caller and callee */
-}
-
-static inline void
-rb_warn_keyword_to_last_hash(rb_execution_context_t * const ec, struct rb_calling_info *calling, const struct rb_call_info *ci, const rb_iseq_t * const iseq)
-{
- if (rb_warn_check(ec, iseq)) return;
-
- VALUE name, loc;
- if (calling->recv == Qundef) {
- rb_warn("Passing the keyword argument as the last hash parameter is deprecated");
- return;
- }
- name = rb_id2str(ci->mid);
- loc = rb_iseq_location(iseq);
- if (NIL_P(loc)) {
- rb_warn("Passing the keyword argument for `%"PRIsVALUE"' as the last hash parameter is deprecated",
- name);
- }
- else {
- rb_warn("Passing the keyword argument as the last hash parameter is deprecated");
- if (name) {
- rb_compile_warn(RSTRING_PTR(RARRAY_AREF(loc, 0)), FIX2INT(RARRAY_AREF(loc, 1)),
- "The called method `%"PRIsVALUE"' is defined here", name);
- }
- else {
- rb_compile_warn(RSTRING_PTR(RARRAY_AREF(loc, 0)), FIX2INT(RARRAY_AREF(loc, 1)),
- "The called method is defined here");
- }
- }
-}
-
-static inline void
-rb_warn_split_last_hash_to_keyword(rb_execution_context_t * const ec, struct rb_calling_info *calling, const struct rb_call_info *ci, const rb_iseq_t * const iseq)
-{
- if (rb_warn_check(ec, iseq)) return;
-
- VALUE name, loc;
- name = rb_id2str(ci->mid);
- loc = rb_iseq_location(iseq);
- if (NIL_P(loc)) {
- rb_warn("Splitting the last argument for `%"PRIsVALUE"' into positional and keyword parameters is deprecated",
- name);
- }
- else {
- rb_warn("Splitting the last argument into positional and keyword parameters is deprecated");
- if (calling->recv != Qundef) {
- rb_compile_warn(RSTRING_PTR(RARRAY_AREF(loc, 0)), FIX2INT(RARRAY_AREF(loc, 1)),
- "The called method `%"PRIsVALUE"' is defined here", name);
- }
- else {
- rb_compile_warn(RSTRING_PTR(RARRAY_AREF(loc, 0)), FIX2INT(RARRAY_AREF(loc, 1)),
- "The called method is defined here");
- }
- }
-}
-
-static inline void
-rb_warn_last_hash_to_keyword(rb_execution_context_t * const ec, struct rb_calling_info *calling, const struct rb_call_info *ci, const rb_iseq_t * const iseq)
-{
- if (rb_warn_check(ec, iseq)) return;
-
- VALUE name, loc;
- name = rb_id2str(ci->mid);
- loc = rb_iseq_location(iseq);
- if (NIL_P(loc)) {
- rb_warn("Using the last argument for `%"PRIsVALUE"' as keyword parameters is deprecated; maybe ** should be added to the call",
- name);
- }
- else {
- rb_warn("Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call");
- if (calling->recv != Qundef) {
- rb_compile_warn(RSTRING_PTR(RARRAY_AREF(loc, 0)), FIX2INT(RARRAY_AREF(loc, 1)),
- "The called method `%"PRIsVALUE"' is defined here", name);
- }
- else {
- rb_compile_warn(RSTRING_PTR(RARRAY_AREF(loc, 0)), FIX2INT(RARRAY_AREF(loc, 1)),
- "The called method is defined here");
- }
- }
+ return !(iseq->body->param.flags.has_kw) &&
+ !(iseq->body->param.flags.has_kwrest) &&
+ RB_TYPE_P(keyword_hash, T_HASH) &&
+ RHASH_EMPTY_P(keyword_hash);
}
static int
@@ -727,7 +470,6 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
const int max_argc = (iseq->body->param.flags.has_rest == FALSE) ? min_argc + iseq->body->param.opt_num : UNLIMITED_ARGUMENTS;
int opt_pc = 0;
int given_argc;
- int kw_splat = FALSE;
unsigned int kw_flag = ci->flag & (VM_CALL_KWARG | VM_CALL_KW_SPLAT);
struct args_info args_body, *args;
VALUE keyword_hash = Qnil;
@@ -813,46 +555,47 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
if (kw_flag & VM_CALL_KW_SPLAT) {
if (len > 0 && ignore_keyword_hash_p(rest_last, iseq)) {
- if (given_argc != min_argc) {
- if (remove_empty_keyword_hash) {
- arg_rest_dup(args);
- rb_ary_pop(args->rest);
- given_argc--;
- kw_flag &= ~VM_CALL_KW_SPLAT;
- }
- else {
- flag_keyword_hash = rest_last;
- }
+ if (remove_empty_keyword_hash) {
+ arg_rest_dup(args);
+ rb_ary_pop(args->rest);
+ given_argc--;
+ kw_flag &= ~VM_CALL_KW_SPLAT;
}
else {
- rb_warn_keyword_to_last_hash(ec, calling, ci, iseq);
+ flag_keyword_hash = rest_last;
}
}
else if (!remove_empty_keyword_hash && rest_last) {
flag_keyword_hash = rest_last;
}
+ else if (iseq->body->param.flags.has_kw || iseq->body->param.flags.has_kwrest) {
+ arg_rest_dup(args);
+ rb_ary_pop(args->rest);
+ given_argc--;
+ keyword_hash = rest_last;
+ }
}
}
else {
if (kw_flag & VM_CALL_KW_SPLAT) {
VALUE last_arg = args->argv[args->argc-1];
if (ignore_keyword_hash_p(last_arg, iseq)) {
- if (given_argc != min_argc) {
- if (remove_empty_keyword_hash) {
- args->argc--;
- given_argc--;
- kw_flag &= ~VM_CALL_KW_SPLAT;
- }
- else {
- flag_keyword_hash = last_arg;
- }
+ if (remove_empty_keyword_hash) {
+ args->argc--;
+ given_argc--;
+ kw_flag &= ~VM_CALL_KW_SPLAT;
}
else {
- rb_warn_keyword_to_last_hash(ec, calling, ci, iseq);
+ flag_keyword_hash = last_arg;
}
}
else if (!remove_empty_keyword_hash) {
- flag_keyword_hash = args->argv[args->argc-1];
+ flag_keyword_hash = last_arg;
+ }
+ else if (iseq->body->param.flags.has_kw || iseq->body->param.flags.has_kwrest) {
+ args->argc--;
+ given_argc--;
+ keyword_hash = last_arg;
}
}
args->rest = Qfalse;
@@ -870,7 +613,7 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
case arg_setup_method:
break; /* do nothing special */
case arg_setup_block:
- if (given_argc == 1 &&
+ if (given_argc == (keyword_hash == Qnil ? 1 : 2) &&
(min_argc > 0 || iseq->body->param.opt_num > 1 ||
iseq->body->param.flags.has_kw || iseq->body->param.flags.has_kwrest) &&
!iseq->body->param.flags.ambiguous_param0 &&
@@ -882,60 +625,13 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
/* argc check */
if (given_argc < min_argc) {
- if (given_argc == min_argc - 1 && args->kw_argv) {
- args_stored_kw_argv_to_hash(args);
- given_argc = args_argc(args);
- }
- else {
- if (arg_setup_type == arg_setup_block) {
- CHECK_VM_STACK_OVERFLOW(ec->cfp, min_argc);
- given_argc = min_argc;
- args_extend(args, min_argc);
- }
- else {
- argument_arity_error(ec, iseq, given_argc, min_argc, max_argc);
- }
- }
- }
-
- if (kw_flag & VM_CALL_KW_SPLAT) {
- kw_splat = !iseq->body->param.flags.has_rest;
- }
- if ((iseq->body->param.flags.has_kw || iseq->body->param.flags.has_kwrest ||
- (kw_splat && given_argc > max_argc)) &&
- args->kw_argv == NULL) {
- if (given_argc > min_argc) {
- if (kw_flag) {
- int check_only_symbol = (kw_flag & VM_CALL_KW_SPLAT) &&
- iseq->body->param.flags.has_kw &&
- !iseq->body->param.flags.has_kwrest;
-
- if (args_pop_keyword_hash(args, &keyword_hash, check_only_symbol)) {
- given_argc--;
- }
- else if (check_only_symbol) {
- if (keyword_hash != Qnil) {
- rb_warn_split_last_hash_to_keyword(ec, calling, ci, iseq);
- }
- else {
- rb_warn_keyword_to_last_hash(ec, calling, ci, iseq);
- }
- }
- }
- else if (args_pop_keyword_hash(args, &keyword_hash, 1)) {
- /* Warn the following:
- * def foo(k:1) p [k]; end
- * foo({k:42}) #=> 42
- */
- rb_warn_last_hash_to_keyword(ec, calling, ci, iseq);
- given_argc--;
- }
- else if (keyword_hash != Qnil) {
- rb_warn_split_last_hash_to_keyword(ec, calling, ci, iseq);
- }
+ if (arg_setup_type == arg_setup_block) {
+ CHECK_VM_STACK_OVERFLOW(ec->cfp, min_argc);
+ given_argc = min_argc;
+ args_extend(args, min_argc);
}
- else if (given_argc == min_argc && kw_flag) {
- rb_warn_keyword_to_last_hash(ec, calling, ci, iseq);
+ else {
+ argument_arity_error(ec, iseq, given_argc, min_argc, max_argc);
}
}
@@ -1160,8 +856,6 @@ refine_sym_proc_call(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg))
const VALUE symbol = RARRAY_AREF(callback_arg, 0);
const VALUE refinements = RARRAY_AREF(callback_arg, 1);
int kw_splat = RB_PASS_CALLED_KEYWORDS;
- VALUE v;
- VALUE ret;
VALUE klass;
if (argc-- < 1) {
@@ -1182,15 +876,10 @@ refine_sym_proc_call(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg))
if (!NIL_P(blockarg)) {
vm_passed_block_handler_set(ec, blockarg);
}
- v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
if (!me) {
- ret = method_missing(obj, mid, argc, argv, MISSING_NOENTRY, kw_splat);
- }
- else {
- ret = rb_vm_call0(ec, obj, mid, argc, argv, me, kw_splat);
+ return method_missing(obj, mid, argc, argv, MISSING_NOENTRY, kw_splat);
}
- rb_free_tmp_buffer(&v);
- return ret;
+ return rb_vm_call0(ec, obj, mid, argc, argv, me, kw_splat);
}
static VALUE
diff --git a/vm_core.h b/vm_core.h
index 8807c23b6f..70575fa66b 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -1159,11 +1159,11 @@ typedef rb_control_frame_t *
enum {
/* Frame/Environment flag bits:
- * MMMM MMMM MMMM MMMM ____ FFFF FFFF EEEX (LSB)
+ * MMMM MMMM MMMM MMMM ____ _FFF FFFF EEEX (LSB)
*
* X : tag for GC marking (It seems as Fixnum)
* EEE : 3 bits Env flags
- * FF..: 8 bits Frame flags
+ * FF..: 7 bits Frame flags
* MM..: 15 bits frame magic (to check frame corruption)
*/
@@ -1188,7 +1188,6 @@ enum {
VM_FRAME_FLAG_LAMBDA = 0x0100,
VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM = 0x0200,
VM_FRAME_FLAG_CFRAME_KW = 0x0400,
- VM_FRAME_FLAG_CFRAME_EMPTY_KW = 0x0800, /* -- Remove In 3.0 -- */
/* env flag */
VM_ENV_FLAG_LOCAL = 0x0002,
@@ -1249,13 +1248,6 @@ VM_FRAME_CFRAME_KW_P(const rb_control_frame_t *cfp)
return VM_ENV_FLAGS(cfp->ep, VM_FRAME_FLAG_CFRAME_KW) != 0;
}
-/* -- Remove In 3.0 -- */
-static inline int
-VM_FRAME_CFRAME_EMPTY_KW_P(const rb_control_frame_t *cfp)
-{
- return VM_ENV_FLAGS(cfp->ep, VM_FRAME_FLAG_CFRAME_EMPTY_KW) != 0;
-}
-
static inline int
VM_FRAME_FINISHED_P(const rb_control_frame_t *cfp)
{
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
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 8cc47e15af..d69340b071 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -2486,9 +2486,8 @@ 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, struct rb_call_data *cd, int empty_kw_splat)
+vm_call_cfunc_with_frame(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, struct rb_call_data *cd)
{
const struct rb_call_info *ci = &cd->ci;
const struct rb_call_cache *cc = &cd->cc;
@@ -2506,9 +2505,6 @@ 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);
@@ -2536,16 +2532,11 @@ static VALUE
vm_call_cfunc(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, struct rb_call_data *cd)
{
const struct rb_call_info *ci = &cd->ci;
- int empty_kw_splat;
RB_DEBUG_COUNTER_INC(ccf_cfunc);
CALLER_SETUP_ARG(reg_cfp, calling, ci);
- empty_kw_splat = calling->kw_splat;
CALLER_REMOVE_EMPTY_KW_SPLAT(reg_cfp, calling, ci);
- if (empty_kw_splat && calling->kw_splat) {
- empty_kw_splat = 0;
- }
- return vm_call_cfunc_with_frame(ec, reg_cfp, calling, cd, empty_kw_splat);
+ return vm_call_cfunc_with_frame(ec, reg_cfp, calling, cd);
}
static VALUE
@@ -2935,12 +2926,7 @@ vm_call_method_each_type(rb_execution_context_t *ec, rb_control_frame_t *cfp, st
case VM_METHOD_TYPE_ATTRSET:
CALLER_SETUP_ARG(cfp, calling, ci);
- if (calling->argc == 1 && calling->kw_splat && RHASH_EMPTY_P(cfp->sp[-1])) {
- rb_warn_keyword_to_last_hash(ec, calling, ci, NULL);
- }
- else {
- CALLER_REMOVE_EMPTY_KW_SPLAT(cfp, calling, ci);
- }
+ CALLER_REMOVE_EMPTY_KW_SPLAT(cfp, calling, ci);
rb_check_arity(calling->argc, 1, 1);
cc->aux.index = 0;
@@ -3211,13 +3197,8 @@ vm_yield_with_cfunc(rb_execution_context_t *ec,
blockarg = rb_vm_bh_to_procval(ec, block_handler);
frame_flag = VM_FRAME_MAGIC_IFUNC | VM_FRAME_FLAG_CFRAME | (me ? VM_FRAME_FLAG_BMETHOD : 0);
- switch (kw_splat) {
- case 1:
- frame_flag |= VM_FRAME_FLAG_CFRAME_KW;
- break;
- case 2:
- frame_flag |= VM_FRAME_FLAG_CFRAME_EMPTY_KW;
- break;
+ if (kw_splat) {
+ frame_flag |= VM_FRAME_FLAG_CFRAME_KW;
}
vm_push_frame(ec, (const rb_iseq_t *)captured->code.ifunc,
@@ -3274,12 +3255,7 @@ vm_callee_setup_block_arg(rb_execution_context_t *ec, struct rb_calling_info *ca
VALUE arg0;
CALLER_SETUP_ARG(cfp, calling, ci);
- if (calling->kw_splat && calling->argc == iseq->body->param.lead_num + iseq->body->param.post_num && RHASH_EMPTY_P(cfp->sp[-1])) {
- rb_warn_keyword_to_last_hash(ec, calling, ci, iseq);
- }
- else {
- CALLER_REMOVE_EMPTY_KW_SPLAT(cfp, calling, ci);
- }
+ CALLER_REMOVE_EMPTY_KW_SPLAT(cfp, calling, ci);
if (arg_setup_type == arg_setup_block &&
calling->argc == 1 &&
@@ -3377,17 +3353,10 @@ vm_invoke_ifunc_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
{
VALUE val;
int argc;
- int kw_splat = calling->kw_splat;
CALLER_SETUP_ARG(ec->cfp, calling, ci);
CALLER_REMOVE_EMPTY_KW_SPLAT(ec->cfp, calling, ci);
- if (kw_splat && !calling->kw_splat) {
- kw_splat = 2;
- }
- else {
- kw_splat = calling->kw_splat;
- }
argc = calling->argc;
- val = vm_yield_with_cfunc(ec, captured, captured->self, argc, STACK_ADDR_FROM_TOP(argc), kw_splat, calling->block_handler, NULL);
+ val = vm_yield_with_cfunc(ec, captured, captured->self, argc, STACK_ADDR_FROM_TOP(argc), calling->kw_splat, calling->block_handler, NULL);
POPN(argc); /* TODO: should put before C/yield? */
return val;
}