Fix unexpected node bug for shareable_constant_value: literal
[Bug #20339] [Bug #20341] `const_decl_path` changes the value of `NODE **dest`, LHS of an assignment, with `NODE_LIT` created by `const_decl_path`. `shareable_literal_constant` calls `const_decl_path` via `ensure_shareable_node` multiple times if RHS of an assignment is array or hash. This means `NODE **dest` argument of `const_decl_path` can be `NODE_LIT` from the second time then causes `[BUG] unexpected node: NODE_LIT` in `rb_node_const_decl_val`. This commit change to not update `NODE **dest` in `const_decl_path` to fix the issue.
This commit is contained in:
parent
6650b3aecf
commit
8ba4d7d75f
20
parse.y
20
parse.y
@ -14068,13 +14068,13 @@ mark_lvar_used(struct parser_params *p, NODE *rhs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static NODE *
|
static NODE *
|
||||||
const_decl_path(struct parser_params *p, NODE **dest)
|
const_decl_path(struct parser_params *p, NODE *dest)
|
||||||
{
|
{
|
||||||
NODE *n = *dest;
|
NODE *n = dest;
|
||||||
if (!nd_type_p(n, NODE_CALL)) {
|
if (!nd_type_p(dest, NODE_CALL)) {
|
||||||
const YYLTYPE *loc = &n->nd_loc;
|
const YYLTYPE *loc = &dest->nd_loc;
|
||||||
VALUE path = rb_node_const_decl_val(n);
|
VALUE path = rb_node_const_decl_val(dest);
|
||||||
*dest = n = NEW_LIT(path, loc);
|
n = NEW_LIT(path, loc);
|
||||||
RB_OBJ_WRITTEN(p->ast, Qnil, RNODE_LIT(n)->nd_lit);
|
RB_OBJ_WRITTEN(p->ast, Qnil, RNODE_LIT(n)->nd_lit);
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
@ -14096,7 +14096,7 @@ make_shareable_node(struct parser_params *p, NODE *value, bool copy, const YYLTY
|
|||||||
}
|
}
|
||||||
|
|
||||||
static NODE *
|
static NODE *
|
||||||
ensure_shareable_node(struct parser_params *p, NODE **dest, NODE *value, const YYLTYPE *loc)
|
ensure_shareable_node(struct parser_params *p, NODE *dest, NODE *value, const YYLTYPE *loc)
|
||||||
{
|
{
|
||||||
NODE *fcore = NEW_LIT(rb_mRubyVMFrozenCore, loc);
|
NODE *fcore = NEW_LIT(rb_mRubyVMFrozenCore, loc);
|
||||||
NODE *args = NEW_LIST(value, loc);
|
NODE *args = NEW_LIST(value, loc);
|
||||||
@ -14147,7 +14147,7 @@ shareable_literal_value(struct parser_params *p, NODE *node)
|
|||||||
|
|
||||||
static NODE *
|
static NODE *
|
||||||
shareable_literal_constant(struct parser_params *p, enum shareability shareable,
|
shareable_literal_constant(struct parser_params *p, enum shareability shareable,
|
||||||
NODE **dest, NODE *value, const YYLTYPE *loc, size_t level)
|
NODE *dest, NODE *value, const YYLTYPE *loc, size_t level)
|
||||||
{
|
{
|
||||||
# define shareable_literal_constant_next(n) \
|
# define shareable_literal_constant_next(n) \
|
||||||
shareable_literal_constant(p, shareable, dest, (n), &(n)->nd_loc, level+1)
|
shareable_literal_constant(p, shareable, dest, (n), &(n)->nd_loc, level+1)
|
||||||
@ -14297,7 +14297,7 @@ shareable_constant_value(struct parser_params *p, enum shareability shareable,
|
|||||||
|
|
||||||
case shareable_literal:
|
case shareable_literal:
|
||||||
{
|
{
|
||||||
NODE *lit = shareable_literal_constant(p, shareable, &lhs, value, loc, 0);
|
NODE *lit = shareable_literal_constant(p, shareable, lhs, value, loc, 0);
|
||||||
if (lit) return lit;
|
if (lit) return lit;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
@ -14306,7 +14306,7 @@ shareable_constant_value(struct parser_params *p, enum shareability shareable,
|
|||||||
case shareable_copy:
|
case shareable_copy:
|
||||||
case shareable_everything:
|
case shareable_everything:
|
||||||
{
|
{
|
||||||
NODE *lit = shareable_literal_constant(p, shareable, &lhs, value, loc, 0);
|
NODE *lit = shareable_literal_constant(p, shareable, lhs, value, loc, 0);
|
||||||
if (lit) return lit;
|
if (lit) return lit;
|
||||||
return make_shareable_node(p, value, shareable == shareable_copy, loc);
|
return make_shareable_node(p, value, shareable == shareable_copy, loc);
|
||||||
}
|
}
|
||||||
|
@ -1526,6 +1526,24 @@ x = __ENCODING__
|
|||||||
assert_not_ractor_shareable(obj)
|
assert_not_ractor_shareable(obj)
|
||||||
assert_equal obj, a
|
assert_equal obj, a
|
||||||
assert !obj.equal?(a)
|
assert !obj.equal?(a)
|
||||||
|
|
||||||
|
bug_20339 = '[ruby-core:117186] [Bug #20339]'
|
||||||
|
bug_20341 = '[ruby-core:117197] [Bug #20341]'
|
||||||
|
a, b = eval_separately(<<~'end;')
|
||||||
|
# shareable_constant_value: literal
|
||||||
|
foo = 1
|
||||||
|
bar = 2
|
||||||
|
A = { foo => bar }
|
||||||
|
B = [foo, bar]
|
||||||
|
[A, B]
|
||||||
|
end;
|
||||||
|
|
||||||
|
assert_ractor_shareable(a)
|
||||||
|
assert_ractor_shareable(b)
|
||||||
|
assert_equal([1], a.keys, bug_20339)
|
||||||
|
assert_equal([2], a.values, bug_20339)
|
||||||
|
assert_equal(1, b[0], bug_20341)
|
||||||
|
assert_equal(2, b[1], bug_20341)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_shareable_constant_value_nested
|
def test_shareable_constant_value_nested
|
||||||
|
Loading…
x
Reference in New Issue
Block a user