summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryui-knk <[email protected]>2024-03-19 18:17:46 +0900
committerYuichiro Kaneko <[email protected]>2024-03-21 11:29:09 +0900
commit8ba4d7d75fd231b61727eb0561eb686c1d67bfd4 (patch)
tree219f536797366539ec276ba0d6c765a632bd2250
parent6650b3aecf6bd3f4bce10a9f1a615683020af186 (diff)
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.
-rw-r--r--parse.y20
-rw-r--r--test/ruby/test_parse.rb18
2 files changed, 28 insertions, 10 deletions
diff --git a/parse.y b/parse.y
index a9db3d4e6e..7b58134f0d 100644
--- a/parse.y
+++ b/parse.y
@@ -14068,13 +14068,13 @@ mark_lvar_used(struct parser_params *p, NODE *rhs)
}
static NODE *
-const_decl_path(struct parser_params *p, NODE **dest)
+const_decl_path(struct parser_params *p, NODE *dest)
{
- NODE *n = *dest;
- if (!nd_type_p(n, NODE_CALL)) {
- const YYLTYPE *loc = &n->nd_loc;
- VALUE path = rb_node_const_decl_val(n);
- *dest = n = NEW_LIT(path, loc);
+ NODE *n = dest;
+ if (!nd_type_p(dest, NODE_CALL)) {
+ const YYLTYPE *loc = &dest->nd_loc;
+ VALUE path = rb_node_const_decl_val(dest);
+ n = NEW_LIT(path, loc);
RB_OBJ_WRITTEN(p->ast, Qnil, RNODE_LIT(n)->nd_lit);
}
return n;
@@ -14096,7 +14096,7 @@ make_shareable_node(struct parser_params *p, NODE *value, bool copy, const YYLTY
}
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 *args = NEW_LIST(value, loc);
@@ -14147,7 +14147,7 @@ shareable_literal_value(struct parser_params *p, NODE *node)
static NODE *
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) \
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:
{
- 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;
return value;
}
@@ -14306,7 +14306,7 @@ shareable_constant_value(struct parser_params *p, enum shareability shareable,
case shareable_copy:
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;
return make_shareable_node(p, value, shareable == shareable_copy, loc);
}
diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb
index a4ca08ec27..62498170fd 100644
--- a/test/ruby/test_parse.rb
+++ b/test/ruby/test_parse.rb
@@ -1526,6 +1526,24 @@ x = __ENCODING__
assert_not_ractor_shareable(obj)
assert_equal obj, 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
def test_shareable_constant_value_nested