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(). --- enumerator.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'enumerator.c') 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); -- cgit v1.2.3