diff options
author | Takashi Kokubun <[email protected]> | 2024-07-08 16:08:42 -0700 |
---|---|---|
committer | Takashi Kokubun <[email protected]> | 2024-07-08 16:08:42 -0700 |
commit | 17e21d815583ef7d6be03f29e90a219602497626 (patch) | |
tree | 8d94cd4ef7fad0307f69ef03fbd3945e6eb07cf6 | |
parent | df8a08fb6a1f173a9c25db15fbe390096f39c2ff (diff) |
merge revision(s) fc33559c: [Backport #20570]
clear `kw_flag` if given hash is nil
https://bugs.ruby-lang.org/issues/20570 is caused I missed to
clear the `kw_flag` even if `keyword_hash` is nil.
-rw-r--r-- | test/ruby/test_keyword.rb | 18 | ||||
-rw-r--r-- | version.h | 2 | ||||
-rw-r--r-- | vm_args.c | 21 |
3 files changed, 34 insertions, 7 deletions
diff --git a/test/ruby/test_keyword.rb b/test/ruby/test_keyword.rb index 9aca787dff..bc816751fd 100644 --- a/test/ruby/test_keyword.rb +++ b/test/ruby/test_keyword.rb @@ -4432,6 +4432,24 @@ class TestKeywordArgumentsSymProcRefinements < Test::Unit::TestCase assert_equal({one: 1, two: 2}, f.call(one:, two:)) end + def m_bug20570(*a, **nil) + a + end + + def test_splat_arg_with_prohibited_keyword + assert_equal([], m_bug20570(*[])) + assert_equal([1], m_bug20570(*[1])) + assert_equal([1, 2], m_bug20570(*[1, 2])) + h = nil + assert_equal([], m_bug20570(*[], **h)) + assert_equal([1], m_bug20570(*[1], **h)) + assert_equal([1, 2], m_bug20570(*[1, 2], **h)) + + assert_equal([], m_bug20570(*[], **nil)) + assert_equal([1], m_bug20570(*[1], **nil)) + assert_equal([1, 2], m_bug20570(*[1, 2], **nil)) + end + private def one 1 end @@ -11,7 +11,7 @@ # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR #define RUBY_VERSION_TEENY 3 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR -#define RUBY_PATCHLEVEL 93 +#define RUBY_PATCHLEVEL 94 #include "ruby/version.h" #include "ruby/internal/abi.h" @@ -434,7 +434,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, unsigned int * kw_flag, VALUE * converted_keyword_hash) { - if (!RB_TYPE_P(keyword_hash, T_HASH)) { + if (keyword_hash == Qnil) { + goto ignore; + } + else if (!RB_TYPE_P(keyword_hash, T_HASH)) { keyword_hash = rb_to_hash_type(keyword_hash); } @@ -445,9 +448,17 @@ ignore_keyword_hash_p(VALUE keyword_hash, const rb_iseq_t * const iseq, unsigned keyword_hash = rb_hash_dup(keyword_hash); } *converted_keyword_hash = keyword_hash; - return !(ISEQ_BODY(iseq)->param.flags.has_kw) && - !(ISEQ_BODY(iseq)->param.flags.has_kwrest) && - RHASH_EMPTY_P(keyword_hash); + + if (!(ISEQ_BODY(iseq)->param.flags.has_kw) && + !(ISEQ_BODY(iseq)->param.flags.has_kwrest) && + RHASH_EMPTY_P(keyword_hash)) { + ignore: + *kw_flag &= ~(VM_CALL_KW_SPLAT | VM_CALL_KW_SPLAT_MUT); + return 1; + } + else { + return 0; + } } static VALUE @@ -577,7 +588,6 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co arg_rest_dup(args); rb_ary_pop(args->rest); given_argc--; - kw_flag &= ~(VM_CALL_KW_SPLAT | VM_CALL_KW_SPLAT_MUT); } else { if (rest_last != converted_keyword_hash) { @@ -608,7 +618,6 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co if (ignore_keyword_hash_p(last_arg, iseq, &kw_flag, &converted_keyword_hash)) { args->argc--; given_argc--; - kw_flag &= ~(VM_CALL_KW_SPLAT | VM_CALL_KW_SPLAT_MUT); } else { if (!(kw_flag & VM_CALL_KW_SPLAT_MUT)) { |