зеркало из https://github.com/github/ruby.git
Fix issue with super and forwarding arguments in prism_compile.c
Fixes [Bug #20720]
This commit is contained in:
Родитель
d4d6f1de83
Коммит
5d358b660d
4
parse.y
4
parse.y
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче