2021/08/13 今週の気になった bugs.ruby のチケット
今週は instance_exec
に Method#to_proc
を渡すと意図しない例外が返ってくるというバグ報告や Ruby 3.0.2 で Hash#transform_keys!
を呼び出すとメモリリークをするという報告がありました。
[Feature #18070] attr
should be removed
class User # getter のみ定義される attr :id # true を渡すと setter も定義される attr :name, true end
- 非推奨なのは第二引数の
true / false
を渡すことなのでattr
自体は特に問題なさそう?
[Feature #1806] instance_exec
is just ignored when the block is originally a method
Method#to_proc
の結果は元のコンテキスト情報を持っているので次のようなコードは失敗する
f = -> (x) { a + x } class A def a 1 end end # これは f 内の a は A#a を参照する A.new.instance_exec(1, &f) # => 2 class B def b(x) a + x end end # B#method の場合の場合は a が B#a を参照する proc = B.new.method(:b).to_proc # なのでエラーになる A.new.instance_exec(1, &proc) # => undefined local variable or method `a' for #<B:0x00007fdaf30480a0> (NameError)
- このチケットの提案自体は
NameError
になるのではなくてArgumentError
になるべきでは?という内容 - これ自体は期待する挙動らしい
- なぜなら
Method#to_proc
の実装は以下のようになっており結果的にMethod#call
を呼んでいるから
class Method def to_proc method = self ->(*args, **kwargs, &block) do # ここで `B#b` が呼ばれるため結果的に NameError になる method.call(*args, **kwargs, &block) end end end
- 今回の提案のように
Method#call
の挙動を変更すると挙動が壊れてしまうらしいModule.module_eval(&m)
みたいにmodule_eval
に渡したときの挙動が壊れてるぽい?- 実装: https://github.com/jeremyevans/ruby/commit/3e2db2f01281f2335c638142223f8b24531826bd
- コケてるテスト: https://github.com/jeremyevans/ruby/runs/3283493175
[Bug #18065] 3.0.2 - possible memory leak in Hash#transform_keys!
h = { value1: 1, value2: 2 } loop { h.transform_keys!(&:to_s) }
- この問題は既に最新版で修正済み