2021/03/05 今週の気になった bugs.ruby のチケット

内容は適当です。
今週と言っても今週みかけたチケットなだけでチケット自体は昔からあるやつもあります。
あくまでも『わたしが気になったチケット』で全ての bugs.ruby のチケットを載せているわけではありません。

[Feature #17660] Expose information about which basic methods have been redefined

  • RubyVM.redefined_methods というメソッドを追加する提案
  • これは再定義されてた標準的なメソッドの一覧を返すようなメソッドになる
class Integer
  def +(x); x ** self; end
end

# 再定義された Integer#+ メソッドの情報を返す
p RubyVM.redefined_methods # => {Integer=>[:+]}
  • これによって再定義されてしまうことを防ぐことができるらしい
Minitest.after_run {
  fail "Basic methods have been redefine" if RubyVM.redefined_methods.any?
}

[Bug #17652] GC compaction crash on mprotect

  • GC compaction でクラッシュするというバグ報告
  • 以下のコードで再現
GC.auto_compact = true

times = 20_000_000
arr = Array.new(times)
times.times do |i|
  arr[i] = "#{i}"
end

arr = Array.new(1_000_000, 42)
GC.start

puts "ok"
  • こんなコードで再現するんだ… GC なんもわからねえ…

[Feature #17663] Enumerator#with, an alternative to Enumerator#with_object

  • Enumerator#with を追加する提案
  • #with に渡した引数を #with のブロックの引数として受け取る
    • Enumerator#with と似ているが戻り値がちょっと違う
class Enumerator
  def with(*options)
    return to_enum(:with, *options) unless defined? yield

    each do |entry|
      yield entry, *options
    end
  end
end


# each_with_object は each_with_object の引数を返す
pp (1..5).map.each_with_object(2) { |it, n| p it.to_s(n) }
# => 2

# with はそのままイテレーションの結果を返す
pp (1..5).map.with(2) { |it, n| it.to_s(n) }
# => ["1", "10", "11", "100", "101"]

# こうもかける
pp (1..5).map.with(2, &:to_s)
# => ["1", "10", "11", "100", "101"]
  • #each_with_object#map などでチェーンしたい場合はあるのでこれは普通に便利そう
  • まあ今なら素直にナンパラを使えばいいじゃん、という気もするが…
    • (1..5).map { _1.to_s(2) }

[Misc #17662] The heredoc pattern used in tests does not syntax highlight correctly in many editors

assert_ruby_status([], "#{<<-"begin;"}\n#{<<-'end;'}", bug)
begin;
  exit("1" == Thread.start(1, &:to_s).value)
end;
  • これは以下のような文字列になる
str = "#{<<-"begin;"}\n#{<<-'end;'}"
begin;
  exit("1" == Thread.start(1, &:to_s).value)
end;
pp str
# => "\n" + "  exit(\"1\" == Thread.start(1, &:to_s).value)\n"
  • この書き方だとエディタでハイライトされないことが多いので以下のように書き直そう、という提案
assert_ruby_status([], <<~'RUBY', bug)
  exit("1" == Thread.start(1, &:to_s).value)
RUBY
  • 手元の Vim だとうまくハイライトされなかった…うーん…

[Bug #17661] IO#each will segfault when if file is closed inside an each_byte block

  • 以下のように File#each_byte 内で File#close すると segv するというバグ報告
file = File.open(__FILE__)
file.each_byte do |byte|
  file.close
end

[Bug #17667] Module#name needs synchronization

  • Module#name は非同期処理に対応していないので以下のようにすると segv するというバグ報告
class C
  @iv = 1
end
Ractor.new {
  loop {
    C.name
  }
}

class C
  0.step { |i|
    instance_variable_set("@iv#{i}", i)
  }
end
  • Module#name 内でインスタンス変数にアクセスしたりしているんですかね?普通に踏みそう