diff options
author | Jeremy Evans <code@jeremyevans.net> | 2024-02-01 12:28:32 -0800 |
---|---|---|
committer | Jeremy Evans <code@jeremyevans.net> | 2024-03-01 12:36:19 -0800 |
commit | 99384bac28e10895623ecbc73fc09fd7d41fc897 (patch) | |
tree | b87147e42ea7515017a9f64a288b5bcf37f6e00e /vm_args.c | |
parent | 6da8f04e01fd85e54a641c6ec4816153b9557095 (diff) |
Correctly set anon_kwrest flag for def f(b: 1, **)
In cases where a method accepts both keywords and an anonymous
keyword splat, the method was not marked as taking an anonymous
keyword splat. Fix that in the compiler.
Doing that broke handling of nil keyword splats in yjit, so
update yjit to handle that.
Add a test to check that calling a method that accepts both
a keyword argument and an anonymous keyword splat does not
modify a passed keyword splat hash.
Move the anon_kwrest check from setup_parameters_complex to
ignore_keyword_hash_p, and only use it if the keyword hash
is already a hash. This should speed things up slightly as
it avoids a check previously used for all callers of
setup_parameters_complex.
Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
Diffstat (limited to 'vm_args.c')
-rw-r--r-- | vm_args.c | 11 |
1 files changed, 5 insertions, 6 deletions
@@ -504,6 +504,11 @@ ignore_keyword_hash_p(VALUE keyword_hash, const rb_iseq_t * const iseq, unsigned if (!RB_TYPE_P(keyword_hash, T_HASH)) { keyword_hash = rb_to_hash_type(keyword_hash); } + else if (UNLIKELY(ISEQ_BODY(iseq)->param.flags.anon_kwrest)) { + if (!ISEQ_BODY(iseq)->param.flags.has_kw) { + *kw_flag |= VM_CALL_KW_SPLAT_MUT; + } + } if (!(*kw_flag & VM_CALL_KW_SPLAT_MUT) && (ISEQ_BODY(iseq)->param.flags.has_kwrest || @@ -590,12 +595,6 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co } } - if (UNLIKELY(ISEQ_BODY(iseq)->param.flags.anon_kwrest)) { - if (kw_flag & VM_CALL_KW_SPLAT) { - kw_flag |= VM_CALL_KW_SPLAT_MUT; - } - } - if (kw_flag & VM_CALL_KWARG) { args->kw_arg = vm_ci_kwarg(ci); |