From: "mame (Yusuke Endoh) via ruby-core" Date: 2025-11-05T14:45:23+00:00 Subject: [ruby-core:123686] [Ruby Bug#21669] Thoroughly implement void value expression check Issue #21669 has been updated by mame (Yusuke Endoh). Eregon (Benoit Daloze) wrote in #note-1: > This check is getting more and more complicated and I wonder of the value of having it. IMO, the current is indeed complicated because it is inconsistent. I think the new behavior is consistent and thus simpler. At least it's explainable. I am a bit concerned about compatibility, though. Earlopain (Earlopain _) wrote in #note-3: > In prism, that whole check fits in about 130 lines As an aside, I noticed this inconsistency when Coverity Scan, a static analyzer for C, pointed out that the following branch in Prism was dead code: https://github.com/ruby/prism/blob/2ecd49dfeea1d0b00c3af609be82dd488d25c7f3/src/prism.c#L1075-L1077 At line 1067, `void_node = vn` is executed (and `vn` is guaranteed to be non-NULL on the line above), so it's impossible for `void_node` to be NULL at line 1075. Thus, it is indeed dead code. To remove the dead code, I started writing some test codes, and found these various inconsistencies. Incidentally, it wasn't a bug in Prism, but rather the result of perfectly replicating the inconsistent behavior in parse.y. ---------------------------------------- Bug #21669: Thoroughly implement void value expression check https://bugs.ruby-lang.org/issues/21669#change-115069 * Author: mame (Yusuke Endoh) * Status: Open * Assignee: prism * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- A void-value-expression check is a syntax check that raises a `SyntaxError` if an expression that cannot grammatically return a value (a "void value expression," such as a `return` expression) appears in a context where a value is expected (e.g., the right-hand side of an assignment, the argument of a method call, etc.). A typical example rejected by this check is `x = return`. However, it has become clear that this check is incomplete. This ticket summarizes the results of a discussion with @matz at the hackathon before RubyWorld Conference today. ## 1\. Expressions containing branches @matz said that an expression containing branches should be considered a void value expression only if it can be grammatically determined that all possible branches do not return a value. Based on this, both parse.y and prism currently reject the following code with a "void value expression" `SyntaxError`, but it should be accepted: ```ruby x = begin raise return rescue "OK" else return end # Expected: Code parses and executes successfully. # Actual: Rejected with "unexpected void value expression" SyntaxError. ``` Reason: The `rescue` clause can return a value ("OK"), so the entire `begin` expression is not void. Conversely, the following code is currently accepted by both parse.y and prism, but it should be rejected: ```ruby x = begin foo rescue return else return end # Expected: Rejected with SyntaxError. # Actual: Code parses and executes. ``` Reason: This expression always does `return`, so it is void whether `foo` raises an exception or not. Furthermore, `case` expressions must also be rejected similarly when all branches are void: ```ruby x = case when 1; return when 2; return else return end # Expected: Rejected with SyntaxError. # Actual: Code parses and executes. ``` Note that `if` expressions appear to be implemented correctly as intended: ```ruby x = if rand < 0.5 return else return end # Expected: Rejected with SyntaxError. # Actual: Rejected. (OK!) ``` ## 2\. Statement lists containing a void value expression @matz also said that if a statements node contains a void value expression, the entire statement list should be treated as a void value expression, even if the void expression is not the last one. Therefore, the following code is currently accepted but should be rejected: ```ruby x = begin return "NG" end # Expected: Rejected with SyntaxError. # Actual: Code parses and executes. ``` The same applies to branches within other expressions: ```ruby x = if rand < 0.5 return "NG" else return end # Expected: Rejected with SyntaxError. # Actual: Code parses and executes. ``` Note that if a return statement is inside a branch, that statement cannot be considered a void value expression, so the entire expression also cannot be a void value expression. ```ruby x = begin return if true "NG" end # Expected: Code parses and executes. # Actual: Code parses and executes as expected. (OK!) ``` --- This is considered a bug, but if it causes practical compatibility issues, it may be necessary to plan a migration path or revisit the specifications. (Both prism and parse.y need to be fixed, but I'll assign it to the prism team for now.) -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/