koukiblog

たぶんweb系の話題

Rubyのマイナーバージョンを上げたらSyntaxErrorになった件

あるプロジェクトのRubyのバージョンを 2.4.0 から2.4.3に上げたら今まで問題なかった構文がSyntaxErrorになるようになりました。経緯が気になって調べたのでそのメモです。

問題の構文は

let :product { create(product)}

のようなものです。(letの括弧を省略して、{}でブロックを渡している)

これが、Ruby 2.4.1までは、

$ruby -ce "m :a {}"
> Syntax OK

となってok 2.4.2(2.4.3と同じ挙動でした)に上げると

$ruby -ce "m :a {}"
>-e:1: syntax error, unexpected '{', expecting end-of-input
m :a {}
      ^

m(:a {}) と解釈されるみたいでエラー

マイナーバージョンアップで後方互換性壊すことなんてあるのかなーと思ってソースコードを見てみると、それっぽいコミットを発見しました。ちなみに僕は全くRubyのコードは読めません。ただ、構文解析周りだろうなーと思って2.4.1から2.4.2のparse.yに変更があったコミットを調べて見つけました。

github.com

このコミットから辿れるruby-coreがこれで

[ruby-core:81037] [Ruby trunk Bug#13547] [].delete 1 { 'NG' }

バグチケットがこれです

Bug #13547: [].delete 1 { 'NG' } - Ruby trunk - Ruby Issue Tracking System

内容を確認すると、2.4.2へのバージョンアップで壊れたのではなく、2.4.0, 2.4.1でだけ意図せず使えていたのがバグで、本来の挙動が文法エラーだったようです。

僕が遭遇した状況と同じようなバグチケットもいくつか確認できました。

Bug #13939: Ruby 2.4.2 has issue supporting Seattle.rb style for define_method - Ruby trunk - Ruby Issue Tracking System

Bug #13898: Block parsing regression - Ruby trunk - Ruby Issue Tracking System

Bug #14023: SyntaxError on array argument and block - Ruby trunk - Ruby Issue Tracking System

というわけで、対応としてはRubyはバージョンアップに問題はない。エラーになる構文は今まで通っていたのが間違いだったので全て修正する、ということに。

文法エラーになるようなバグに遭遇したのは初めてだったので、普段何気なく使っているRubyも日々いろんな方の労力で維持・開発されてるんだなーと実感できた出来事でした。 今後はまめにバージョンアップして、何かエラーがあれば報告するぐらいの貢献は行なっていきたい。