Bug #21337
open
Using `not` on the RHS of a logical operator becomes valid syntax with Prism
Description
The following syntax behavior differs between Ruby 3.3 (parse.y by default) and Ruby 3.4 (Prism by default).
if true && not true; end
Expected¶
In Ruby 3.3 and earlier, the following code results in a syntax error. The default parser is parse.y
.
$ ruby -vce 'if true && not true; end'
ruby 3.3.8 (2025-04-09 revision b200bad6cd) [x86_64-darwin24]
-e:1: syntax error, unexpected `true', expecting '('
if true && not true; end
ruby: compile error (SyntaxError)
The key point is that not
is used on the right-hand side of a logical operator.
Actual¶
When the default parser is switched to Prism, it is accepted as valid syntax with Ruby 3.4+ (Prism by default):
$ ruby -vce 'if true && not true; end'
ruby 3.4.3 (2025-04-14 revision d0b7e5b6a0) +PRISM [x86_64-darwin24]
Syntax OK
$ ruby -vce 'if true && not true; end'
ruby 3.5.0dev (2025-05-13T02:05:19Z master 9b8c846bdf) +PRISM [x86_64-darwin24]
Syntax OK
Specifying parse.y causes a syntax error, as before 3.3 (parse.y by default):
$ ruby -vce 'if true && not true; end'
ruby 3.3.8 (2025-04-09 revision b200bad6cd) [x86_64-darwin24]
-e:1: syntax error, unexpected `true', expecting '('
if true && not true; end
ruby: compile error (SyntaxError)
$ ruby --parser=parse.y -vce 'if true && not true; end'
ruby 3.5.0dev (2025-05-13T02:05:19Z master 9b8c846bdf) [x86_64-darwin24]
-e:1: syntax error, unexpected 'true', expecting '('
if true && not true; end
ruby: compile error (SyntaxError)
The behavior seen in the parse.y producing a syntax error might be probably the expected one.
Any case, it is likely that users would not expect such a discrepancy between parsers.
This issue was noticed in the context of the following RuboCop issue:
https://github.com/rubocop/rubocop/issues/14177
Updated by byroot (Jean Boussier) about 1 month ago
- Assignee set to prism
Updated by Dan0042 (Daniel DeLorme) 25 days ago
I prefer the behavior of Prism here. Intuitively, true && not true
seems like it should be valid just like true and not true
Updated by hsbt (Hiroshi SHIBATA) 19 days ago
- Status changed from Open to Assigned
Updated by matz (Yukihiro Matsumoto) 10 days ago
I am against this prism behavior. It introduces ambiguity for not a && b
(might be not (a && b)
or (not a) && b
). I don't think we can have formal definition of this not
behavior.
Matz.
Updated by mame (Yusuke Endoh) 10 days ago
p(not 1)
is also allowed in Ruby 3.4, but this should also be prohibited, @matz (Yukihiro Matsumoto) said.
@kddnewton (Kevin Newton) @tenderlovemaking (Aaron Patterson) @eileencodes (Eileen Uchitelle) Can you fix this issue soon? We need to backport to 3.4 to stop Ruby 3.4 users writing such code.