diff options
| author | Earlopain <14981592+Earlopain@users.noreply.github.com> | 2026-04-09 13:11:13 +0200 |
|---|---|---|
| committer | git <svn-admin@ruby-lang.org> | 2026-04-09 11:48:11 +0000 |
| commit | 51a3f0847782095340df5dbc8fb87450dbc1fbe7 (patch) | |
| tree | 1de1a1c4163fe6aef8934908762fd53f1f439c55 | |
| parent | 03757030d5b1663e68b4f6e6348a7a71b16ed6c8 (diff) | |
[ruby/prism] Reject `return` and similar with block pass argument
Same handling as for `yield`. Fixes [Bug #21988]
https://github.com/ruby/prism/commit/2dd20183ad
| -rw-r--r-- | prism/prism.c | 9 | ||||
| -rw-r--r-- | test/prism/errors/block_pass_return_value.txt | 33 |
2 files changed, 42 insertions, 0 deletions
diff --git a/prism/prism.c b/prism/prism.c index 72c49da6f2..3ae6ca3d7b 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -19685,6 +19685,15 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, u PM_PARSER_ERR_TOKEN_FORMAT(parser, &next, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_str(next.type)); } } + + // It's possible that we've parsed a block argument through our + // call to parse_arguments. If we found one, we should mark it + // as invalid and destroy it, as we don't have a place for it. + if (arguments.block != NULL) { + pm_parser_err_node(parser, arguments.block, PM_ERR_UNEXPECTED_BLOCK_ARGUMENT); + pm_node_unreference(parser, arguments.block); + arguments.block = NULL; + } } switch (keyword.type) { diff --git a/test/prism/errors/block_pass_return_value.txt b/test/prism/errors/block_pass_return_value.txt new file mode 100644 index 0000000000..c9d12281d9 --- /dev/null +++ b/test/prism/errors/block_pass_return_value.txt @@ -0,0 +1,33 @@ +return &b + ^ unexpected '&', expecting end-of-input + ^ unexpected '&', ignoring it + +return(&b) + ^ unexpected '&', ignoring it + ^ unexpected '&', expecting end-of-input + ^ unexpected '&', ignoring it + ^ expected a matching `)` + ^ unexpected '&', expecting end-of-input + ^ unexpected '&', ignoring it + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + +return a, &b + ^~ block argument should not be given + +return(a, &b) + ^~ unexpected write target + ^ unexpected '&', expecting end-of-input + ^ unexpected '&', ignoring it + ^ expected a matching `)` + ^ unexpected '&', expecting end-of-input + ^ unexpected '&', ignoring it + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + +tap { break a, &b } + ^~ block argument should not be given + +tap { next a, &b } + ^~ block argument should not be given + |
