diff --git a/prism/diagnostic.c b/prism/diagnostic.c index 7cffce7c9f..925ccce4f0 100644 --- a/prism/diagnostic.c +++ b/prism/diagnostic.c @@ -255,6 +255,7 @@ static const char* const diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = { [PM_ERR_UNTIL_TERM] = "expected an `end` to close the `until` statement", [PM_ERR_VOID_EXPRESSION] = "unexpected void value expression", [PM_ERR_WHILE_TERM] = "expected an `end` to close the `while` statement", + [PM_ERR_WRITE_TARGET_IN_METHOD] = "dynamic constant assignment", [PM_ERR_WRITE_TARGET_READONLY] = "immutable variable as a write target", [PM_ERR_WRITE_TARGET_UNEXPECTED] = "unexpected write target", [PM_ERR_XSTRING_TERM] = "expected a closing delimiter for the `%x` or backtick string", diff --git a/prism/diagnostic.h b/prism/diagnostic.h index 079d409147..a1e0b6d0d8 100644 --- a/prism/diagnostic.h +++ b/prism/diagnostic.h @@ -247,6 +247,7 @@ typedef enum { PM_ERR_UNTIL_TERM, PM_ERR_VOID_EXPRESSION, PM_ERR_WHILE_TERM, + PM_ERR_WRITE_TARGET_IN_METHOD, PM_ERR_WRITE_TARGET_READONLY, PM_ERR_WRITE_TARGET_UNEXPECTED, PM_ERR_XSTRING_TERM, diff --git a/prism/prism.c b/prism/prism.c index 15195ea5cd..6f2f37113b 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -10685,6 +10685,9 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod return (pm_node_t *) pm_constant_path_write_node_create(parser, (pm_constant_path_node_t *) target, operator, value); case PM_CONSTANT_READ_NODE: { pm_constant_write_node_t *node = pm_constant_write_node_create(parser, (pm_constant_read_node_t *) target, operator, value); + if (context_def_p(parser)) { + pm_parser_err_node(parser, (pm_node_t *) node, PM_ERR_WRITE_TARGET_IN_METHOD); + } pm_node_destroy(parser, target); return (pm_node_t *) node; } diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index 906dbac594..9b6cf55fd5 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -1971,6 +1971,13 @@ module Prism end end + def test_constant_assignment_in_method + source = 'def foo();A=1;end' + assert_errors expression(source), source, [ + ['dynamic constant assignment', 10..13] + ] + end + private def assert_errors(expected, source, errors, compare_ripper: RUBY_ENGINE == "ruby")