summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Valentine-House <matt@eightbitraptor.com>2024-01-17 13:59:30 +0000
committerMatt Valentine-House <matt@eightbitraptor.com>2024-01-17 14:48:46 +0000
commitef4a08eb65ab00eb0101b8b64212bef613e4f833 (patch)
treea08aac45c4b491d280657184cb1b5b973bacfaf8
parente17c83e02c5019f7a8c31b31a567ab6de6d6c7f4 (diff)
[PRISM] Fix stack inconsistency in MultiWriteNode
-rw-r--r--prism_compile.c12
-rw-r--r--test/ruby/test_compile_prism.rb4
2 files changed, 13 insertions, 3 deletions
diff --git a/prism_compile.c b/prism_compile.c
index 722dabf8ab..55bc348492 100644
--- a/prism_compile.c
+++ b/prism_compile.c
@@ -5216,6 +5216,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
pm_multi_write_node_t *multi_write_node = (pm_multi_write_node_t *)node;
pm_node_list_t *lefts = &multi_write_node->lefts;
pm_node_list_t *rights = &multi_write_node->rights;
+ bool has_rest_expression = (multi_write_node->rest &&
+ PM_NODE_TYPE_P(multi_write_node->rest, PM_SPLAT_NODE));
size_t argc = 1;
// pre-process the left hand side of multi-assignments.
@@ -5313,9 +5315,13 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
PM_COMPILE(rights->nodes[index]);
}
}
- else if (rest_expression) {
- ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(0), INT2FIX(1));
- PM_COMPILE(rest_expression);
+ else if (has_rest_expression) {
+ if (rest_expression) {
+ ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(0), INT2FIX(1));
+ PM_COMPILE(rest_expression);
+ } else if (!lefts->size && !PM_NODE_TYPE_P(multi_write_node->value, PM_SPLAT_NODE)){
+ ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(0), INT2FIX(0));
+ }
}
return;
diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb
index bc9f0b3aba..9b4e998b27 100644
--- a/test/ruby/test_compile_prism.rb
+++ b/test/ruby/test_compile_prism.rb
@@ -543,6 +543,10 @@ module Prism
assert_prism_eval("_, {}[:foo], _ = 1")
assert_prism_eval("_, {}[:foo], _ = 1")
assert_prism_eval("_,{}[:foo], _, {}[:bar] = 1")
+ assert_prism_eval("* = :foo")
+ assert_prism_eval("* = *[]")
+ assert_prism_eval("a, * = :foo")
+
assert_prism_eval(<<~CODE)
class Foo