2021/03/18 今週の気になった bugs.ruby のチケット
内容は適当です。
今週と言っても今週みかけたチケットなだけでチケット自体は昔からあるやつもあります。
あくまでも『わたしが気になったチケット』で全ての bugs.ruby のチケットを載せているわけではありません。
[PR irb #202] process multi-line pastes as a single entity
- 現行の
irb
だと以下のようなコードをペーストするとエラーになる
class A def a; self; end def b; true; end end a = A.new a .a .b
irb(main):001:1* class A irb(main):002:1* def a; self; end irb(main):003:1* def b; true; end irb(main):004:0> end = > :b irb(main):005:0> irb(main):006:0> a = A.new = > #<A:0x00005588503197b8> irb(main):007:0> irb(main):008:0> a = > #<A:0x00005588503197b8> irb(main):009:0> .a /home/worker/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/irb-1.3.4/lib/irb/workspace.rb:116:in `eval': (irb):9: syntax error, unexpected '.' (SyntaxError) from /home/worker/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/irb-1.3.4/exe/irb:11:in `<top (required)>' from /home/worker/.rbenv/versions/3.0.0/bin/irb:23:in `load' from /home/worker/.rbenv/versions/3.0.0/bin/irb:23:in `<main>' irb(main):010:0> .b
- これはペーストしたタイミングで Ruby のコードが逐次的に評価され
.a
を呼び出した時にエラーになってしまっているため- 先に
a
のコードが評価され
- 先に
- これを回避するためにペーストして『最後に』コードを評価するようにする PR
- 個人的には落とし所としてはいいとは思う
[Bug #17571] prependしたArray#[] が反映されない
- 以下のように
Array
にprepend
してる#[]
が呼び出されないことがある
module TestMod def [](*) :called end end Array.prepend TestMod # これは Array#[] が呼ばれる p [1, 2, 3][1] # => 2 # これは TestMod#[] が呼ばれる p [1, 2, 3][] # => :called # Method オブジェクトは TestMod を指している p [1, 2, 3].method(:[]) # => #<Method: Array(TestMod)#[](*) /tmp/vud3mdg/27:2>
- これはおそらく
Array#[]
を事前にメソッドキャッシュしておりそちらを優先して呼び出しているのが原因ぽい?- なので
prepend
しているメソッドは呼ばれなくなっている - 引数がない場合は
Array#[]
とシグネチャが異なるのでキャッシュされたメソッドではなくてprepend
されたメソッドを呼び出しているので意図する挙動になっているみたい?
- なので
- これは Ruby 2.7 では問題なくて Ruby 3.0 から問題になっている
- Ruby 3.0 に上げるタイミングでなにか壊れるかもしれないので注意したい
- 原因っぽいコミット(と PR)
[Bug #17725] Prepend breaks ability to override optimized methods
- 以下のように
String.prepend
するとString#+
が上書きされたりされなかったりする
# これは上書きされる class String def + other 'blah blah' end end p 'a' + 'b' # => "blah blah"
# これは上書きされない String.prepend(Module.new) class String def + other 'blah blah' end end p 'a' + 'b' # => "ab"
[Bug #16996] Hash should avoid doing unnecessary rehash
Hash#dup
よりもHash#merge
の方が高速だというチケット- 3.5倍早いと書かれている
- これは
Hash#dup
は内部で再ハッシュを行っているがHash#merge
は行っていないのでその差になる - Ruby なにもわからない
Hash#replace/dup/initialize_copy
で再ハッシュを行わないようにする PR- 開発者会議でも承認されたっぽいのでマージされそう
- ちなみに
hash.select
よりもhash.merge.select!
のほうが高速らしいHash#select/reject
で再ハッシュしないようにする PR- https://github.com/ruby/ruby/pull/4273
[Bug #17719] Irregular evaluation order in hash literals
Hash
リテラルでキーが重複している場合に以下のような評価順になる
# 1個目と2個目の foo の要素が先に評価される $ ruby -e '{foo:p(1), bar:p(2), foo:p(3)}' -e:1: warning: key :foo is duplicated and overwritten on line 1 1 3 2
- これはバグのようなので修正するチケット
- 以下のような問題もあるしもうエラーにしちゃっていいんじゃないかなあ…。