2021/01/21 今週の気になった bugs.ruby のチケット
内容は適当です。
今週と言っても今週みかけたチケットなだけでチケット自体は昔からあるやつもあります。
あくまでも『わたしが気になったチケット』で全ての bugs.ruby のチケットを載せているわけではありません。
[Bug #17530] irb handles << incorrectly with variable as identifier
irb
で以下のように入力したら意図しないエラーになったというバグ報告
irb(main):001:0' s1 = 'testing' = > "testing" [2021-01-20 23:11] irb(main):002:0' s2 = 'this' = > "this" irb(main):003:0" s2 <<s1 irb(main):004:0" adding text here does not work irb(main):005:0" s1 Traceback (most recent call last): 3: from /home/centos/.rubies/ruby-3.0.0/bin/irb:23:in `<main>' 2: from /home/centos/.rubies/ruby-3.0.0/bin/irb:23:in `load' 1: from /home/centos/.rubies/ruby-3.0.0/lib/ruby/gems/3.0.0/gems/irb-1.3.0/exe/irb:11:in `<top (required)>' SyntaxError ((irb):4: syntax error, unexpected local variable or method, expecting '(') adding text here does not work ^~~~ irb(main):006:0>
- 意図としては 3行目の
s2 <<s1
はs2.<<(s1)
のようにString#<<
を呼んでほしい - しかし、
irb
上ではヒアドキュメントと解釈されてしまっており 4〜5行目はヒアドキュメントの複数行として扱われてしまう - なんですが 5行目で Ruby のコードが実行される場合はヒアドキュメント
s2.<<(s1)
と解釈されてしまいおかしいことになっています- 4行目がそのまま Ruby のコードとして実行されている
- この問題の本質としては
s2 <<s1
というコードは『s2
という変数が定義されているかどうか』で意味が変わってしまう点です- 変数が定義されていれば
s2.<<(s1)
と解釈され、そうでなければヒアドキュメントとして扱われる
- 変数が定義されていれば
- なので 3行目のコードを解析する際に変数の有無も考慮する必要があるのですが irb の実装としては1行ずつコードを解析しておりその前の行で
s2
変数が定義されていてもs2 <<s1
がディアドキュメントとして解釈されてしまっている、って感じです - これ、直してみたいんだけどどう治すのがいいのかなあ…
[Bug #17547] Fix Ripper.lex("a <<b")
Ripper.lex("a <<b")
が意図する結果を返してなかったというバグ報告- 必要なパース結果が含まれていなかった
- これですが先程の [Bug #17530] を調べている時に見つけたバグで直せそうだったので直してパッチ投げました
- Ripper なので実装が難しいのかなあ、と思っていたんですが問題になっていた箇所は Ruby で書かれていたので比較的簡単でした
require "ripper" p Ripper.lex("a <<b") # 期待する挙動 => [[[1, 0], :on_ident, "a", CMDARG], [[1, 1], :on_sp, " ", CMDARG], [[1, 2], :on_heredoc_beg, "<<b", CMDARG]] # 実際の挙動 => [[[1, 2], :on_heredoc_beg, "<<b", CMDARG]]
- この修正は既にマージ済みです
[Bug #17556] ruby 2.7.2 ::YAML.dump ArgumentError: invalid value for Integer(): "20210101_"
YAML.dump '20210101_'
するとInteger
と解釈されてエラーになるというバグ報告
require "yaml" p YAML::VERSION # => "3.1.0" # error: `Integer': invalid value for Integer(): "20210101_" (ArgumentError) p YAML.dump '20210101_'
- このバグは既に修正済みで手元だと
YAML::VERSION
が3.2.0
では問題なく動作していました
require "yaml" p YAML::VERSION # => "3.2.0" p YAML.dump '20210101_' # => "--- '20210101_'\n"
[Bug #17554] [PATCH] Fix ObjectSpace.dump to include singleton class name
- 次のように
ObjectSpace.dump
に特異クラスを渡した場合に Ruby 3.0 だと"name"
が含まれなくなっているというバグ報告
require "objspace" puts ObjectSpace.dump(Object.new.singleton_class) # 2.7 => {"address":"0x55adae76b630", "type":"CLASS", "class":"0x55adae7a76d0", "name":"Object", "references":["0x55adae7a9250", "0x55adae76b720"], "memsize":464, "flags":{"wb_protected":true}} # 3.0 => {"address":"0x55d9048e80e0", "type":"CLASS", "class":"0x55d90476d738", "references":["0x55d90476e8b8", "0x55d9048e8158"], "memsize":472, "flags":{"wb_protected":true}}
- なるほどね?
[Bug #17423] Prepend
should prepend a module before the class
- Ruby 3.0 では継承リスト周りの処理が色々と改善された結果
#prepend
が意図する挙動をしていないケースがありました
module M; end module A; end class B; include A; end A.prepend M B.prepend M # B に prepend M しているのに反映されてないように見える p B.ancestors # 2.7 => [M, B, A, Object, Kernel, BasicObject] # 3.0 => [B, M, A, Object, Kernel, BasicObject]
- これの対処として
[M, B, M, A, Object, Kernel, BasicObject]
を返す提案がされました - この場合は
M
が重複してしまいますが、次のようなコードでも重複するので問題ないとの判断
module M; end class A; end class B<A; end A.prepend M B.prepend M # これは Ruby 3.0 以前からこのような挙動になっている p B.ancestors # => [M, B, M, A, Object, Kernel, BasicObject]
- この変更は既にマージされました
- 今後は以下のような挙動になる予定です
module M; end module A; end class B; include A; end A.prepend M B.prepend M p B.ancestors # 2.7 => [M, B, A, Object, Kernel, BasicObject] # 3.0 => [B, M, A, Object, Kernel, BasicObject] # 3.1 => [M, B, M, A, Object, Kernel, BasicObject]
- このあたりはちょっと注意して使う必要がありそうですねえ