diff --git a/prism_compile.c b/prism_compile.c index c71c1429b2..2ae6c1db9e 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -5164,6 +5164,20 @@ pm_compile_target_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *cons break; } + case PM_SPLAT_NODE: { + // Splat nodes capture all values into an array. They can be used + // as targets in assignments or for loops. + // + // for *x in []; end + // + const pm_splat_node_t *cast = (const pm_splat_node_t *) node; + + if (cast->expression != NULL) { + pm_compile_target_node(iseq, cast->expression, parents, writes, cleanup, scope_node, state); + } + + break; + } default: rb_bug("Unexpected node type: %s", pm_node_type_to_str(PM_NODE_TYPE(node))); break; @@ -5277,7 +5291,8 @@ pm_compile_for_node_index(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *c case PM_INSTANCE_VARIABLE_TARGET_NODE: case PM_CONSTANT_PATH_TARGET_NODE: case PM_CALL_TARGET_NODE: - case PM_INDEX_TARGET_NODE: { + case PM_INDEX_TARGET_NODE: + case PM_SPLAT_NODE: { // For other targets, we need to potentially compile the parent or // owning expression of this target, then retrieve the value, expand it, // and then compile the necessary writes. diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 819d0d35aa..86f7f0b14f 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1053,6 +1053,9 @@ module Prism assert_prism_eval("for foo, in [1,2,3] do end") assert_prism_eval("for i, j in {a: 'b'} do; i; j; end") + + # Test splat node as index in for loop + assert_prism_eval("for *x in [[1,2], [3,4]] do; x; end") end ############################################################################