From 9a5a11f3d0e5d9b595d51aafe8fdadfe384568ad Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 29 Jan 2024 09:47:52 -0500 Subject: [PATCH] [PRISM] Use the splatkw instruction Fixes ruby/prism#2272. --- prism_compile.c | 14 +++++++++----- test/ruby/test_compile_prism.rb | 22 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 88172716af..1d9f6f9e62 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2749,12 +2749,16 @@ pm_compile_call(rb_iseq_t *iseq, const pm_call_node_t *call_node, LINK_ANCHOR *c else if (!popped) { ADD_INSN1(ret, &dummy_line_node, setn, INT2FIX(orig_argc + 1)); } - - ADD_SEND_R(ret, &dummy_line_node, method_id, INT2FIX(orig_argc), block_iseq, INT2FIX(flags), kw_arg); - PM_POP_UNLESS_POPPED; } - else { - ADD_SEND_R(ret, &dummy_line_node, method_id, INT2FIX(orig_argc), block_iseq, INT2FIX(flags), kw_arg); + + if ((flags & VM_CALL_KW_SPLAT) && (flags & VM_CALL_ARGS_BLOCKARG) && !(flags & VM_CALL_KW_SPLAT_MUT)) { + ADD_INSN(ret, &dummy_line_node, splatkw); + } + + ADD_SEND_R(ret, &dummy_line_node, method_id, INT2FIX(orig_argc), block_iseq, INT2FIX(flags), kw_arg); + + if (pm_node->flags & PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE) { + PM_POP_UNLESS_POPPED; } if (call_node->base.flags & PM_CALL_NODE_FLAGS_SAFE_NAVIGATION) { diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index ff0a252b71..93dcd42450 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -827,6 +827,28 @@ module Prism o.bar(hello: "world") RUBY + + # Test that AssocSplatNode is evaluated before BlockArgumentNode using + # the splatkw instruction + assert_prism_eval(<<~RUBY) + o = Struct.new(:ary) do + def to_hash + ary << :to_hash + {} + end + + def to_proc + ary << :to_proc + -> {} + end + + def t(...); end + end.new + o.ary = [] + + o.t(**o, &o) + o.ary + RUBY end def test_HashNode