Bug #19392
Updated by zverok (Victor Shepelev) 9 months ago
**Initial description** [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" ``` **Additional cases of what seems to be the same problem** ```ruby def save = File.write(name, self.to_yaml) unless invalid? # Parsed as: (def save = File.write(name, self.to_yaml)) unless invalid? ``` ...which makes it very hard for the users to diagnose the real reason, see #19731 ```ruby def initialize(a, b) = @a, b = a, b # syntax error, unexpected ',', expecting end-of-input (SyntaxError) # def initialize(a, b) = @a, b = a, b # ^ # Again, parsed as (def initialize(a, b) = @a), b = a, b ``` While this one is at least diagnosed early, in pathological cases, it might lead to very subtle bugs: ```ruby private def start = @operation, @conversion = :print, :to_s ``` This code doesn't throw a syntax error, but its effect is very far from expected. Again, it is parsed as ```ruby private( (def start = @operation), @conversion = :print, :to_s ) ``` ...and ends up in: * defining a private method `start` * making private methods `:print` and `:to_s`