2021/11/11 今回の気になった bugs.ruby のチケット

今週は Time.at のパフォーマンス低下の報告などがありました。

[Bug #18293] Time.at in master branch was 25% slower then Ruby 3.0

[Bug #18292] 3.1.0-dev include cause Module to be marked as initialized

  • 開発版だと次のコードでエラーになってしまうというバグ報告
    • Module を継承して include した後に super を呼ぶとエラーになってしまうぽい?
    • [#17048] が原因かも?と書かれてはいる
class Mod1 < Module
  def initialize(...)
    super
  end
end
p Mod1.new
# => #<Mod1:0x000055b6dc5a5d00>

class Mod2 < Module
  def initialize(...)
    include Enumerable
    super
  end
end
p Mod2.new
# 3.0.2     => #<Mod2:0x000055b6dc5a59e0>
# 3.1.0-dev => error: `initialize': already initialized module (TypeError)
  • ちなみに以下のコードだけでもエラーになったので include 後に Module#initialize を呼ぶとダメなのかも
class Mod2 < Module
  def initialize(...)
    include Enumerable
    super
  end
end
p Mod2.new
# 3.0.2     => #<Mod2:0x000055b6dc5a59e0>
# 3.1.0-dev => error: `initialize': already initialized module (TypeError)

[Bug #18329] Calling super to non-existent method dumps core

  • 存在しない super を呼び出すとコアダンプするというバグ報告
    • 次のコードを Ruby 3.0 以降で実行すると segv する
module Probes
  def self.included(base)
    base.extend(ClassMethods)
  end

  module ClassMethods
    def probe(*methods)
      prepend(probing_module(methods))
    end

    def probing_module(methods)
      Module.new do
        methods.each do |method|
          define_method(method) do |*args, **kwargs, &block|
            super(*args, **kwargs, &block)
          end
        end
      end
    end
  end
end

class Probed
  include Probes

  probe :danger!, :missing

  def danger!
    raise "BOOM"
  end
end

5.times do
  subject = Probed.new
  subject.danger! rescue RuntimeError
  subject.missing rescue NoMethodError
end
  • ちょっと分かりづらいので最小構成にすると以下のような感じ
class Probed
  def self.probing_module(methods)
    Module.new do
      methods.each do |method|
        define_method(method) do |*args, **kwargs, &block|
          super(*args, **kwargs, &block)
        end
      end
    end
  end

  prepend probing_module [:danger!, :missing]

  def danger!
  end
end

subject = Probed.new
subject.danger!

# ここで存在しない super を呼び出している
subject.missing rescue NoMethodError

# ここで segv
subject.danger!
  • なんもわからねえ

[Feature #16252] Hash#partition should return hashes

  • Hash#partition の戻り値は Array を返しているが Hash を返すようにする提案
{1=>2,3=>4}.partition{ |k,| k==1 }
# 期待する挙動 => [{1=>2}, {3=>4}]
# 実際の挙動   => [[[1, 2]], [[3, 4]]]
  • Hash#selectHash#rejectHash を返しているのでそれに合わせたいらしい
{ 1=>2,3=>4,5=>6 }.select{ |k, v| k == 1 }
# => {1=>2}
{ 1=>2,3=>4,5=>6 }.reject{ |k, v| k == 1 }
# => {3=>4, 5=>6}
  • #partitionEnumerable で実装されているけど #select#rejectHash で実装されているのでその差異ですかね?