今週の気になった bugs.ruby

内容は適当です。 今週と言っても今週みかけたチケットなだけでチケット自体は昔からあるやつもあります。

[Bug #11669] inconsitent behavior of refining frozen class

  • freeze されたクラスに対して Refinements で新しいメソッドを定義するとエラーになっていた
class X
  def foo
  end
end
X.freeze

using Module.new {
  refine X do
    # OK
    def foo
    end

    # error: can't modify frozen class: X (FrozenError)
    def bar
    end
  end
}
  • Ruby 2.8/3.0 からこれがエラーにならずに定義できるようになる

[Bug #9573] descendants of a module don't gain its future ancestors, but descendants of a class, do

  • モジュールの mixin が ancestors に反映されないケースがあった
  • 以下のように挙動が変更される
module M1
end

module M2
end

module M3
end

class C
end

p C.ancestors
#=> current: [C, Object, Kernel, BasicObject]
#=> fixed:   [C, Object, Kernel, BasicObject]

C.prepend M1

p C.ancestors
#=> current: [M1, C, Object, Kernel, BasicObject]
#=> fixed:   [M1, C, Object, Kernel, BasicObject]

M1.prepend M2

p C.ancestors
#=> current: [M1, C, Object, Kernel, BasicObject]
#=> fixed:   [M2, M1, C, Object, Kernel, BasicObject]

M2.prepend M3

p C.ancestors
#=> current: [M1, C, Object, Kernel, BasicObject]
#=> fixed:   [M3, M2, M1, C, Object, Kernel, BasicObject]

[Feature #15822] Add Hash#except

  • Hash#except が標準ライブラリ入りした
user = { id: 1, name: "homu", age: 14 }

# 引数の key を除いた Hash を返す
pp user.except(:name, :age)
# => {:id=>1}
  • ちょうど最近使いたいケースがあったのでめでたい
  • ActiveSupport には Hash#except! があるがこっちは標準には入ってない
    • これは Hash#slice! も同様

[Bug #16983] Bug #16983: RubyVM::AbstractSyntaxTree.of(method) returns meaningless node if the method is defined in eval - Ruby master - Ruby Issue Tracking System

  • RubyVM::AbstractSyntaxTree.ofeval で定義したメソッドオブジェクトを渡すと意図しない値が返ってくる、という報告
  • 以下はチケットに書いてあったコード
p 'blah'

eval <<~RUBY, binding, __FILE__, __LINE__ + 1
  def foo
  end
RUBY

method = method(:foo)
# ここで意図しない値が返ってくる
pp RubyVM::AbstractSyntaxTree.of(method)
# => (STR@3:5-3:12 "def foo\n" + "end\n")
  • p 'blah' があるかないかでも結果が変わってくるのでよくわからない…
  • 最近 RubyVM::AST をいじってるけど eval は試してなかったので知らなかった