Issue #19392 has been updated by zverok (Victor Shepelev).
`and` is actually not alone.
The code like this is also parsed not the way one would intuitively expect:
```ruby
def save = File.write(name, self.to_yaml) unless invalid?
```
Actual parsing is this:
```ruby
(def save = File.write(name, self.to_yaml)) unless invalid?
```
I believe that combining postfix `if`/`unless` with one-line methods is extremely
possible, while intention to conditionally define methods with postfix condition is much
less so.
In general, I believe that
```ruby
def method
expression
end
```
and
```ruby
def method = expression
```
should be equivalent as long as it is humanly possible, because the simplification of
one-expression method to endless one is what many codebases would try to do, especially
for simple utility classes.
And if they can't be made equivalent (due to some parser complexities), the only other
acceptable behavior is an error or at least warning (though the latter is much less
desirable), not a silent change of semantics.
----------------------------------------
Bug #19392: Endless method vs and/or
https://bugs.ruby-lang.org/issues/19392#change-102110
* Author: zverok (Victor Shepelev)
* Status: Open
* Priority: Normal
* Backport: 2.7: DONTNEED, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN
----------------------------------------
[
Discovered](https://twitter.com/lucianghinda/status/1617783952353406977) by Lucian
Ghinda:
```ruby
def test = puts("foo") and puts("bar")
# prints "bar" immediately
test
# prints "foo"
```
It seems that it is a parser error, right?..
```ruby
RubyVM::AbstractSyntaxTree.parse('def test = puts("foo") and
puts("bar")')
# =>
# (SCOPE@1:0-1:38
# tbl: []
# args: nil
# body:
# (AND@1:0-1:38
# (DEFN@1:0-1:22
# mid: :test
# body:
# (SCOPE@1:0-1:22
# tbl: []
# args:
# (ARGS@1:0-1:8 pre_num: 0 pre_init: nil opt: nil first_post: nil post_num: 0
post_init: nil rest: nil kw: nil kwrest: nil block: nil)
# body: (FCALL@1:11-1:22 :puts (LIST@1:16-1:21 (STR@1:16-1:21 "foo")
nil))))
# (FCALL@1:27-1:38 :puts (LIST@1:32-1:37 (STR@1:32-1:37 "bar") nil))))
```
E.g. it is parsed as
```ruby
(def test = puts("foo")) and (puts("bar"))
```
...which is hardly intentional or have any practical use. The rightly parsed code in this
case _can_ have practical use, like
```ruby
def write(data) = File.write(@filename, data) == data.size or raise "Something went
wrong"
```
--
https://bugs.ruby-lang.org/