diff options
| author | Earlopain <14981592+Earlopain@users.noreply.github.com> | 2025-08-29 22:35:51 +0200 |
|---|---|---|
| committer | git <svn-admin@ruby-lang.org> | 2025-09-11 15:55:55 +0000 |
| commit | f17405b69cb8b66feed289d9f857c38ce70bfe26 (patch) | |
| tree | 876094c14e0a2823dc8903f38f6abc24840d308e | |
| parent | e39fd456ac5c4c82e483431afc266b5066f00eba (diff) | |
[ruby/prism] Reject some cases with `return` and command calls
The same also applies to `break`/`next`.
https://bugs.ruby-lang.org/issues/21540
https://github.com/ruby/prism/commit/3a38b192e3
| -rw-r--r-- | lib/prism/translation/parser/lexer.rb | 2 | ||||
| -rw-r--r-- | prism/prism.c | 6 | ||||
| -rw-r--r-- | test/prism/errors/command_calls_32.txt | 19 | ||||
| -rw-r--r-- | test/prism/fixtures/break.txt | 4 | ||||
| -rw-r--r-- | test/prism/fixtures/next.txt | 4 | ||||
| -rw-r--r-- | test/prism/fixtures/return.txt | 3 |
6 files changed, 37 insertions, 1 deletions
diff --git a/lib/prism/translation/parser/lexer.rb b/lib/prism/translation/parser/lexer.rb index 222df74559..75c48ef667 100644 --- a/lib/prism/translation/parser/lexer.rb +++ b/lib/prism/translation/parser/lexer.rb @@ -203,7 +203,7 @@ module Prism # The following token types are listed as those classified as `tLPAREN`. LPAREN_CONVERSION_TOKEN_TYPES = Set.new([ :kBREAK, :tCARET, :kCASE, :tDIVIDE, :kFOR, :kIF, :kNEXT, :kRETURN, :kUNTIL, :kWHILE, :tAMPER, :tANDOP, :tBANG, :tCOMMA, :tDOT2, :tDOT3, - :tEQL, :tLPAREN, :tLPAREN2, :tLPAREN_ARG, :tLSHFT, :tNL, :tOP_ASGN, :tOROP, :tPIPE, :tSEMI, :tSTRING_DBEG, :tUMINUS, :tUPLUS + :tEQL, :tLPAREN, :tLPAREN2, :tLPAREN_ARG, :tLSHFT, :tNL, :tOP_ASGN, :tOROP, :tPIPE, :tSEMI, :tSTRING_DBEG, :tUMINUS, :tUPLUS, :tLCURLY ]) # Types of tokens that are allowed to continue a method call with comments in-between. diff --git a/prism/prism.c b/prism/prism.c index b7e2bdc1de..2f7ce0b986 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -19102,7 +19102,13 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_binding_power_t binding_power = pm_binding_powers[parser->current.type].left; if (binding_power == PM_BINDING_POWER_UNSET || binding_power >= PM_BINDING_POWER_RANGE) { + pm_token_t next = parser->current; parse_arguments(parser, &arguments, false, PM_TOKEN_EOF, (uint16_t) (depth + 1)); + + // Reject `foo && return bar`. + if (!accepts_command_call && arguments.arguments != NULL) { + PM_PARSER_ERR_TOKEN_FORMAT(parser, next, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(next.type)); + } } } diff --git a/test/prism/errors/command_calls_32.txt b/test/prism/errors/command_calls_32.txt new file mode 100644 index 0000000000..14488ca335 --- /dev/null +++ b/test/prism/errors/command_calls_32.txt @@ -0,0 +1,19 @@ +foo && return bar + ^~~ unexpected local variable or method, expecting end-of-input + +tap { foo && break bar } + ^~~ unexpected local variable or method, expecting end-of-input + +tap { foo && next bar } + ^~~ unexpected local variable or method, expecting end-of-input + +foo && return() + ^ unexpected '(', expecting end-of-input + +foo && return(bar) + ^ unexpected '(', expecting end-of-input + +foo && return(bar, baz) + ^~~~~~~~~~ unexpected write target + ^ unexpected '(', expecting end-of-input + diff --git a/test/prism/fixtures/break.txt b/test/prism/fixtures/break.txt index 5532322c5c..d823f866df 100644 --- a/test/prism/fixtures/break.txt +++ b/test/prism/fixtures/break.txt @@ -20,6 +20,10 @@ tap { break() } tap { break(1) } +tap { (break 1) } + +tap { foo && (break 1) } + foo { break 42 } == 42 foo { |a| break } == 42 diff --git a/test/prism/fixtures/next.txt b/test/prism/fixtures/next.txt index 2ef14c6304..0d2d6a11f5 100644 --- a/test/prism/fixtures/next.txt +++ b/test/prism/fixtures/next.txt @@ -22,3 +22,7 @@ tap { next tap { next() } tap { next(1) } + +tap { (next 1) } + +tap { foo && (next 1) } diff --git a/test/prism/fixtures/return.txt b/test/prism/fixtures/return.txt index a8b5b95fab..952fb80da8 100644 --- a/test/prism/fixtures/return.txt +++ b/test/prism/fixtures/return.txt @@ -22,3 +22,6 @@ return() return(1) +(return 1) + +foo && (return 1) |
