diff options
| -rw-r--r-- | parse.y | 4 | ||||
| -rw-r--r-- | prism_compile.c | 10 | ||||
| -rw-r--r-- | test/ruby/test_super.rb | 16 |
3 files changed, 24 insertions, 6 deletions
@@ -15132,11 +15132,11 @@ new_args_forward_call(struct parser_params *p, NODE *leading, const YYLTYPE *loc #ifndef FORWARD_ARGS_WITH_RUBY2_KEYWORDS NODE *kwrest = list_append(p, NEW_LIST(0, loc), NEW_LVAR(idFWD_KWREST, loc)); #endif - rb_node_block_pass_t *block = NEW_BLOCK_PASS(NEW_LVAR(idFWD_BLOCK, loc), loc); + rb_node_block_pass_t *block = NEW_BLOCK_PASS(NEW_LVAR(idFWD_BLOCK, loc), argsloc); NODE *args = leading ? rest_arg_append(p, leading, rest, argsloc) : NEW_SPLAT(rest, loc); block->forwarding = TRUE; #ifndef FORWARD_ARGS_WITH_RUBY2_KEYWORDS - args = arg_append(p, args, new_hash(p, kwrest, loc), loc); + args = arg_append(p, args, new_hash(p, kwrest, loc), argsloc); #endif return arg_blk_pass(args, block); } diff --git a/prism_compile.c b/prism_compile.c index d1c9d5431e..0be5c92078 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -1708,7 +1708,7 @@ pm_setup_args_core(const pm_arguments_node_t *arguments_node, const pm_node_t *b break; } - case PM_FORWARDING_ARGUMENTS_NODE: { + case PM_FORWARDING_ARGUMENTS_NODE: { // not counted in argc return value if (ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->param.flags.forwardable) { *flags |= VM_CALL_FORWARDING; @@ -9628,9 +9628,10 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } return; } - case PM_SUPER_NODE: { + case PM_SUPER_NODE: { // any super with arguments or `super()` + // super() // super(foo) - // ^^^^^^^^^^ + // super(...) const pm_super_node_t *cast = (const pm_super_node_t *) node; DECL_ANCHOR(args); @@ -9649,6 +9650,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, int flags = 0; struct rb_callinfo_kwarg *keywords = NULL; int argc = pm_setup_args(cast->arguments, cast->block, &flags, &keywords, iseq, ret, scope_node, &location); + bool is_forwardable = (cast->arguments != NULL) && PM_NODE_FLAG_P(cast->arguments, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_FORWARDING); flags |= VM_CALL_SUPER | VM_CALL_FCALL; if (cast->block && PM_NODE_TYPE_P(cast->block, PM_BLOCK_NODE)) { @@ -9668,7 +9670,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } PUSH_SEQ(ret, args); - if (ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->param.flags.forwardable) { + if (is_forwardable && ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->param.flags.forwardable) { flags |= VM_CALL_FORWARDING; PUSH_INSN2(ret, location, invokesuperforward, new_callinfo(iseq, 0, argc, flags, keywords, current_block != NULL), current_block); } diff --git a/test/ruby/test_super.rb b/test/ruby/test_super.rb index ce78e66c52..aa09f9e1b9 100644 --- a/test/ruby/test_super.rb +++ b/test/ruby/test_super.rb @@ -8,6 +8,7 @@ class TestSuper < Test::Unit::TestCase def array(*a) a end def optional(a = 0) a end def keyword(**a) a end + def forward(*a) a end end class Single1 < Base def single(*) super end @@ -63,6 +64,16 @@ class TestSuper < Test::Unit::TestCase [x, y] end end + class Forward < Base + def forward(...) + w = super() + x = super + y = super(...) + a = 1 + z = super(a, ...) + [w, x, y, z] + end + end def test_single1 assert_equal(1, Single1.new.single(1)) @@ -133,6 +144,11 @@ class TestSuper < Test::Unit::TestCase def test_keyword2 assert_equal([{foo: "changed1"}, {foo: "changed2"}], Keyword2.new.keyword) end + def test_forwardable(...) + assert_equal([[],[],[],[1]], Forward.new.forward()) + assert_equal([[],[1,2],[1,2],[1,1,2]], Forward.new.forward(1,2)) + assert_equal([[],[:test],[:test],[1,:test]], Forward.new.forward(:test, ...)) + end class A def tt(aa) |
