diff --git a/prism/config.yml b/prism/config.yml index 17fff0431a..a8b1c84ca5 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -235,6 +235,7 @@ errors: - TERNARY_EXPRESSION_TRUE - UNARY_RECEIVER - UNDEF_ARGUMENT + - UNEXPECTED_BLOCK_ARGUMENT - UNEXPECTED_TOKEN_CLOSE_CONTEXT - UNEXPECTED_TOKEN_IGNORE - UNTIL_TERM diff --git a/prism/prism.c b/prism/prism.c index 9fabc5ec0c..55e703eb46 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -17601,6 +17601,16 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_arguments_t arguments = { 0 }; parse_arguments_list(parser, &arguments, false, accepts_command_call); + // It's possible that we've parsed a block argument through our + // call to parse_arguments_list. If we found one, we should mark it + // as invalid and destroy it, as we don't have a place for it on the + // yield node. + if (arguments.block != NULL) { + pm_parser_err_node(parser, arguments.block, PM_ERR_UNEXPECTED_BLOCK_ARGUMENT); + pm_node_destroy(parser, arguments.block); + arguments.block = NULL; + } + pm_node_t *node = (pm_node_t *) pm_yield_node_create(parser, &keyword, &arguments.opening_loc, arguments.arguments, &arguments.closing_loc); if (!parser->parsing_eval) parse_yield(parser, node); diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb index 924d9e6b3f..6275218cb1 100644 --- a/prism/templates/src/diagnostic.c.erb +++ b/prism/templates/src/diagnostic.c.erb @@ -317,6 +317,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_TERNARY_EXPRESSION_TRUE] = { "expected an expression after `?` in the ternary operator", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_UNDEF_ARGUMENT] = { "invalid argument being passed to `undef`; expected a bare word, constant, or symbol argument", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_UNARY_RECEIVER] = { "unexpected %s, expected a receiver for unary `%c`", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_UNEXPECTED_BLOCK_ARGUMENT] = { "block argument should not be given", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_UNEXPECTED_TOKEN_CLOSE_CONTEXT] = { "unexpected %s, assuming it is closing the parent %s", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_UNEXPECTED_TOKEN_IGNORE] = { "unexpected %s, ignoring it", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_UNTIL_TERM] = { "expected an `end` to close the `until` statement", PM_ERROR_LEVEL_SYNTAX }, diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index 0a06e4bd38..09f37eb5b3 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -2202,6 +2202,10 @@ module Prism refute_error_messages "case (); in [{a:1}, {a:2}]; end" end + def test_unexpected_block + assert_error_messages "def foo = yield(&:+)", ["block argument should not be given"] + end + private def assert_errors(expected, source, errors, check_valid_syntax: true)