Bug #16092

[doc] precedence of modifier-rescue

Added by Dan0042 (Daniel DeLorme) about 1 year ago. Updated 10 months ago.

Target version:


The docs state that modifier-rescue has higher precedence than assignments which have higher precedence than modifier-if. This is true for
v = expr rescue $! if condition but not for
v = expr if condition rescue $! which is treated as
(v = expr if condition) rescue $! rather than
v = expr if (condition rescue $!)

This goes similarly for
defined? expr rescue $!
not expr rescue $!
expr1 and expr2 rescue $!
expr1 or expr2 rescue $!

So maybe the documentation should state that modifier-rescue has equal precedence to modifier-if & others, with an exception made for assignments? I'm not entirely sure how to describe that exception though.


modifier-statements.patch (3.74 KB) modifier-statements.patch Dan0042 (Daniel DeLorme), 08/09/2019 06:45 PM

Updated by mame (Yusuke Endoh) about 1 year ago

  • Status changed from Open to Rejected

The current doc about precedence is correct. The behavior you showed is not caused by precedence, but by the grammer itself.

The point is, that <stmt> rescue <stmt> is a statement, not an expression. The right side of modifier-if must be an expression, so <stmt> rescue <stmt> cannot be a right side of modifier-if. So, <stmt> if <stmt> rescue <stmt> can parse only as (<stmt> if <stmt>) rescue <stmt>.

defined? also requires an expression as its argument. So defined? expr rescue $! can parse only as defined? (expr rescue $!).

You can see the precedence by the following code: stmt if v = condition rescue $!. It can parse as both (stmt if v = condition) rescue $! and stmt if v = (condition rescue $!) but the second one is chosen because modifier-rescue has higher precedence than modifier-if.

Updated by Dan0042 (Daniel DeLorme) about 1 year ago

Ok, I'm starting to see. The difference between statements and expressions is why we get this

puts( 1 if 2 )   #=> SyntaxError
puts((1 if 2))   #=> 1
puts(if 2;1;end) #=> 1   ...interesting
puts( 1 rescue 2 ) #=> SyntaxError
puts((1 rescue 2)) #=> 1
defined?(1 rescue 2)  #=> SyntaxError
defined? (1 rescue 2) #=> "expression"

So a if b rescue c is parsed as ‹a if b› rescue c because a if ‹b rescue c› would be a SyntaxError.

In any case, even if the issue is not precedence itself, I think the documentation should be updated somehow, because it leads one to think that a if b rescue c is equivalent to a if (b rescue c)

Now that I understand the nature of the issue I've tried writing a documentation patch.


Updated by jeremyevans (Jeremy Evans) 10 months ago

  • Status changed from Feedback to Closed

Applied in changeset git|29c1e9a0d4c855781853f0ad41b0125f42cf504d.

Document the difference between expressions and statements [ci skip]

In the grammar, all expressions are statements, but not all
statements are expressions. Some parts of the grammar accept
expressions and not other types of statements, which causes
similar looking code to parse differently due to operator

Mostly from Dan0042 (Daniel DeLorme).

Fixes [Bug #16092]

Also available in: Atom PDF