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

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

[PR irb #219] Add pry-like show_source command

  • irb に pry のような show_source コマンドが実装された
  • これは以下のようにメソッドなどの定義を表示してくれるコマンド
$ RBENV_VERSION=3.1.0-dev irb
irb(main):001:0> require "erb"
 => true
irb(main):002:0> show_source "ERB#result"

From: /home/worker/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/erb.rb:901

  def result(b=new_toplevel)
    unless @_init.equal?(self.class.singleton_class)
      raise ArgumentError, "not initialized"
    end
    eval(@src, b, (@filename || '(erb)'), @lineno)
  end

 => nil
irb(main):003:0> show_source "ERB.new('<%= hello %>').src"

From: /home/worker/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/erb.rb:843

  attr_reader :src

 => nil
irb(main):004:0> show_source "IRB::VERSION"

From: /home/worker/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/irb/version.rb:14

  VERSION = "1.3.5"

 => nil
irb(main):005:0>
  • どんどん irb がよくなっていって便利

[PR irb #202] process multi-line pastes as a single entity

class A
  def b; self; end
  def c; true; end
end

a = A.new

a
  .b
  # aaa
  .c

(a)
  &.b()


class A def b; self; end; def c; true; end; end;
a = A.new
a
  .b
  # aaa
  .c
(a)
  &.b()
$ irb
irb(main):001:1* class A
irb(main):002:1*   def b; self; end
irb(main):003:1*   def c; true; end
irb(main):004:0> end
 => :c
irb(main):005:0>
irb(main):006:0> a = A.new
 => #<A:0x00007fe44496c078>
irb(main):007:0>
irb(main):008:0> a
irb(main):009:0>   .b
irb(main):010:0>   # aaa
irb(main):011:0>   .c
 => true
irb(main):012:0>
irb(main):013:0> (a)
irb(main):014:0>   &.b()
 => #<A:0x00007fe44496c078>
irb(main):015:0>
irb(main):016:0>
irb(main):017:0> class A def b; self; end; def c; true; end; end;
 => :c
irb(main):018:0> a = A.new
 => #<A:0x00007fe444c7c880>
irb(main):019:0> a
irb(main):020:0>   .b
irb(main):021:0>   # aaa
irb(main):022:0>   .c
 => true
irb(main):023:0> (a)
irb(main):024:0>   &.b()
 => #<A:0x00007fe444c7c880>
irb(main):025:0>
  • こんな感じで評価できるようになって初めて irb 上でコードが実行されて次のコードがペーストされる
  • 途中のコードは途中で実行される点には注意する

[Feature #17773] Alias Numeric#zero? and Float#zero? as Numeric#empty? and Float#empty?

  • Numeric#zero?Float#zero?Numeric#empty?Float#empty?エイリアスにしようという提案
  • モチベーションとしては Web などの入力フィールドで 文字列などと同じように 0 を無効値として扱うために共通のメソッドとして #empty? がほしいという感じ
  • 0 自体は集合ではないし、 0 が意図的に入力された可能性もあるなど全体的には否定的なコメントが目立つ
  • ちなみに ActiveSupport#blank?0.blank? == false になる
  • 共有のメソッド名にするならもっと別の名前の方がよい気はするな〜

[Bug #17777] 2.6.7 fails to build on macOS: implicit declaration of function 'rb_native_mutex_destroy' is invalid in C99

  • macOSRuby 2.6.7 をビルドすると失敗するという報告
  • C99 で無効なコードを書いているのが原因ぽい?
  • ビルド前に export warnflags=-Wno-error=implicit-function-declaration をしておくことで回避することは可能
  • macOSRuby 2.6.7 をビルドする場合はご注意を

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

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

[Bug #17757] Hash#slice does not keep compare_by_identity on the results

  • Hash#compare_by_identity を使用するとレシーバの Hash をキーの一致判定をオブジェクトの同一性で判定するようにする
    • Object#object_id で判定するようにする
hash = { "a" => 1, b: 2 }

# デフォルトでは無効
p hash.compare_by_identity?  # => false

# OK
p hash["a"]  # => 1
p hash[:b]  # => 1

# Object#object_id で判定するようにする
hash.compare_by_identity
p hash.compare_by_identity?  # => true

# ハッシュのキーの "a" と 参照するときの "a" の object_id は異なるので参照できない
p hash["a"]  # => nil
# Symbol は同じ object_id なので参照できる
p hash[:b]  # => 2
  • この compare_by_identity だが特定のメソッドを経由して生成した Hash で compare_by_identity の性質を受け継いだりしなかったりするというバグ報告
hash = { "a" => 1, b: 2 }

# Object#object_id で判定するようにする
hash.compare_by_identity

# こっちは compare_by_identity を保持するが
p hash.except("a").compare_by_identity?
# => true

# こっちは compare_by_identity を保持しない
p hash.slice("a").compare_by_identity?
# => false
  • なるほど…?
  • compare_by_identity なんてものがあるの知らなかった

[Bug #17754] NoMethodError#to_s makes segmentation fault when Module#name returns non string value

  • 以下のように .name が文字列以外を返した場合に SEGV するというバグ報告
class C
  def self.name
    42
    # これなら OK
    # "42"
  end
end
# C に対して NoMethodError なエラーが発生すると SEGV する
C.this_method_does_not_exist

[Bug #17756] StringScanner#charpos makes segmentation fault when target.byteslice returns non string value

  • 以下のように StringScanner を使用すると SEGV するというバグ報告
    • byteslice を上書きして nil を返すと落ちるっぽい?
require 'strscan'
string = 'ruby'
scnanner = StringScanner.new(string)
pre = Module.new do
  def byteslice(*args)
  end
end
string.singleton_class.prepend(pre)
scnanner.charpos

[Feature #17753] Add Module#outer_scope

module A
  module B
    class C; end
    class D; end
  end
end

# C が定義されている箇所のスコープを返す
p A::B::C.outer_scope # => B
# ネストして呼び出したりとか
p A::B::C.outer_scope.outer_scope # => A
  • ユースケースとしては次のように同じスコープの定数を列挙したい場合に利用できる
A::B::C.outer_scope.constants # => [A::B::C, A::B::D]

ObjectSpace.each_object(Class) do |k|
  p siblings: k.outer_scope.constants
end
  • 現在は『outer_scope って名前じゃなくて namespace のほうがいいんじゃない?』と言われて Module#namespace って名前になっている

[Feature #17749] Const source location without name

module A
  class B
  end
end

p A::B.const_source_location
# => ["test.rb", 2]
# これと同じ意味
p A.const_source_location(:B)
# => ["test.rb", 2]

# ユースケース
# const_source_location に渡す定数名がわからない場合に利用できる
ObjectSpace.each_object(Class) do |k|
  p k.const_source_location
end
  • これは普通に前からほしいなーと思ってたのでうれしい
  • この機能自体は『定数』とは関係ないので const_source_location じゃなくて source_location という名前に変わっている

[Feature #17768] Proposal: Downward assignments

  • 次のように変数を下の行で定義する提案
# var = 42 と同じ
42
^^var

# 中間の式も代入できる
p(2 * 3 * 7)  #=> 42
  ^^^^^var

p var         #=> 6
while (line = gets) != nil
  p line
end

# ↓↓↓

while gets != nil
      ^^^^line
  p line
end
ary = [1, 2, 3, 4, 5]

ary.each {|elem| found = elem if elem.even? }

p found  #=> 4

# ↓↓↓

ary = [1, 2, 3, 4, 5]

ary.each {|elem| elem if elem.even? }
                 ^^^^found

p found  #=> 4
class C
  def initialize(foo, bar)
    @foo = foo
    @bar = bar
  end
end

# ↓↓↓

class C
  def initialize(foo,    bar)
                 ^^^@foo ^^^@bar
end
  • めっちゃ便利そうじゃん…(※もちろんこれはエイプリルフールネタです
  • ちゃんと patch ファイルも付いてて以下のコードは普通に動いてる
(2 * 3 * 7)
  ^^^^^var

p var


while gets != nil
      ^^^^line
  p line
end


ary = [1, 2, 3, 4, 5]

ary.each {|elem| elem if elem.even? }
                 ^^^^found

p found  #=> 4
  • どうやってやってるの…

[Feature #17769] Proposal: numeric coefficient syntax

  • 2x2 * x と解釈するようにする提案
irb(main):001:0> x = 3
 => 3
irb(main):002:0> 2x
 => 6
irb(main):003:0> def pi = Math::PI
 => :pi
irb(main):004:0> 2pi
 => 6.283185307179586

マージされたチケット

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

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

[PR irb #212] Complete require and require_relative

  • irbrequire のファイル名補完をする機能の追加
irb(main):001:0" require "irb/<Tab>  # <- Tab を押すとファイル名を補完してくれる
  • これは普通に便利そう

[PR irb #204] Add whereami command

  • irbprywhereami コマンドを追加する PR
    • whereami すると binding.irb した付近のコードを確認することができる
$ ruby /tmp/a.rb

From: /tmp/a.rb @ line 3 :

    1: a = 1
    2: @b = 2
 => 3: binding.irb

irb(main)[01:0]> a
 => 1
irb(main)[02:0]> @b
 => 2
irb(main)[03:0]> whereami

From: /tmp/a.rb @ line 3 :

    1: a = 1
    2: @b = 2
 => 3: binding.irb

 => nil
  • pry の whereami コマンド知らなかった
  • これはめっちゃ便利そう…

[PR irb #203] Implement pry-like ls command

  • irbpryls コマンドを追加する PR
    • ls すると引数オブジェクトのメソッド一覧やインスタンス一覧を出力してくれる
$ irb
irb(main):001:0> require "erb"
 => true
irb(main):002:0> ls ERB.new('test')
ERB#methods: 
  def_class  def_method     def_module  encoding          filename  filename=    lineno  lineno=
  location=  make_compiler  result      result_with_hash  run       set_eoutvar  src   
instance variables: @_init  @encoding  @filename  @frozen_string  @lineno  @src
 => nil
  • これも知らなかった
  • めっちゃ便利そう…

[Feature #17411] Allow expressions in pattern matching

  • 以下のように ^ を使ってパターンマッチに式をかけるようにする提案
user = { name: "homu", age: 14 }
case user
# 式を書く場合は ^() を使う
in { age: ^(7 + 7) }
end

[Bug #17738] Ruby can still freeze ENV

  • ENV は普通は freeze できないががんばれば freeze できるという報告
# これは error
ENV.freeze

# こうすると freeze できる
Kernel.instance_method(:freeze).bind(ENV).call()
p ENV.frozen? #=> true
  • Ruby むずかしい…

[Bug #17735] Hash#transform_keys! drops non evaluated keys

  • 以下のように Hash#transform_valies! のブロック内で raise するとレシーバは変わらない
# transform_values! はレシーバの要素を保持する
hash = {a: 1, b: 2, c: 3}
a = hash.transform_values! { raise } rescue
p hash #=> {:a=>1, :b=>2, :c=>3}
  • しかし Hash#transform_keys! の場合はレシーバが空になる
# transform_keys! はレシーバの要素が空になる
hash = {a: 1, b: 2, c: 3}
hash.transform_keys!(){ raise } rescue
p hash #=> {}

[Bug #17736] Destructive methods inconsistently handle receiver frozen state in given block

  • Array#select! のブロック内でレシーバを freeze するとレシーバが空の配列になる
array = [1, 2, 3, 42]
array.select! do
  array.freeze
  false
end
p array #=> []
  • Array#uniq! の場合は例外になりレシーバはそのままになる
array = [1, 2, 3, 42, 2, 3]
begin
  array.uniq! do |item|
    array.freeze
    item
  end
rescue => err
  p err #=> #<FrozenError: can't modify frozen Array: [1, 2, 3, 42, 2, 3]>
end

p array #=> [1, 2, 3, 42, 2, 3]
  • Array#select! の方はバグということで修正された
array = [1, 2, 3, 42]
# Ruby 3.1.0-dev だとエラー
# error: `select!': can't modify frozen Array: [1, 2, 3, 42] (FrozenError)
array.select! do
  array.freeze
  false
end

[Bug #17739] Array#sort! changes the order even if the receiver raises FrozenError in given block

  • Array#sort! のブロック内でレシーバを freeze すると例外が発生するがソート済みになっているというバグ報告
array = [1, 2, 3, 4, 5]
begin
  array.sort! do |a, b|
    array.freeze if a == 3
    1
  end
rescue => err
  # 例外が発生する
  p err #=> #<FrozenError: can't modify frozen Array: [5, 4, 3, 2, 1]>
end

# 例外が発生してもソート済みになっている
p array #=> [5, 4, 3, 2, 1]
  • ちなみに break した場合はそこまでのソートになっている
array = [1, 2, 3, 4, 5]
array.sort! do |a, b|
  break if a == 3
  1
end

# 途中までソートされた状態
p array #=> [3, 4, 2, 1, 5]
  • これはまだ未修正

[Feature #17743] Show argument types in backtrace

  • バックトレースに引数情報も追加する提案
  • 例えば以下のようなコードを実行すると
def say_hi(person)
  puts message(person)
end

def message(person)
  "hi: #{person.name}"
end

say_hi(nil)
  • 以下のようなバックトレースが出力される
/tmp/vTaZxJg/70:6:in `message': undefined method `name' for nil:NilClass (NoMethodError)
    from hi.rb:2:in `say_hi'
    from hi.rb:9:in `<main>'
  • これを以下のようにする提案
hi.rb:6:in `message': undefined method `name' for nil:NilClass (NoMethodError)
    from hi.rb:2:in `say_hi' called with NilClass
    from hi.rb:9:in `<main>' called with NilClass
  • どのような表記にするのか(クラスだけ?値は必要がない?複数の引数の場合は?)やパフォーマンス的な懸念点がないか議論されている

[Feature #17744] Accumulate Enumerable#tally results

  • 以下のように Enumerable#tally に引数を渡してそれに結果を集計していくような提案
h = {}
[:a,:b,:c].tally(h)
[:a,:b,:d].tally(h)

# 2個の tally の結果が h に蓄積される
p h #=> {:a=>2, :b=>2, :c=>1, :d=>1}
  • 便利な気がするけど引数が変更されてしまうのはなんかちょっと気持ち悪い…

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#[] が反映されない

  • 以下のように Arrayprepend してる #[] が呼び出されないことがある
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"
  • これは Ruby 3.0 で再現する
    • Ruby 2.7 では再現しない
    • Ruby 3.0 に上げると急にぶっ壊れるかもしれないので注意する…

[Bug #16996] Hash should avoid doing unnecessary rehash

[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

Ruby の Hash リテラルでキーが重複している場合の奇妙な動作

最近こういう動作を見つけたので覚書。

Hash リテラルでキーが重複しているとどうなるのか

Hash リテラルで Hash を定義した場合、キーの順番は『記述した順番』になります。

# ここで定義した順番になる
hash = { age: 14, name: "homu" }
pp hash
# => {:age=>14, :name=>"homu"}

hash = { name: "homu", age: 14 }
pp hash
# => {:name=>"homu", :age=>14}

では、この Hash リテラルでキーが重複しているとどうなるのかというと次のようになります。

# age が重複している場合
hash = { id: 1, age: 14, name: "homu", age: 20, age: 10 }
# キーの順番は age が先にくるが、値は最後に定義した値になる
pp hash
# => {:id=>1, :age=>10, :name=>"homu"}

こんな感じで

  • キーの位置は『最初に定義された位置』
  • キーの値は『最後に定義された値』

という挙動になります。
キーの位置と値が異なるのでちょっと混乱しますね。
このような書き方をすると警告もでますし、基本的に Hash リテラルではキーを重複して書かないようにしましょう。

# warning: key :age is duplicated and overwritten on line 2
hash = { id: 1, age: 14, name: "homu", age: 20, age: 10 }

関連

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

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

[Bug #16908] Strange behaviour of Hash#shift when used with default_proc.

  • 以下のように default_proc が設定されている状態で Hash#shift を呼ぶといと意図しない値が返ってくるよっていうチケット
    • Hash が空の時に shift を呼ぶと default_proc の値が返ってくる
hash = Hash.new{|k,v| k[v] = 0}

hash.shift # => 0
hash.shift # => [nil, 0]
  • 意図としては両方共 [nil, 0] が返ってきてほしい
  • もうちょっと詳細に説明するとこんな感じ
hash = Hash.new{|k,v| k[v] = 0}

# 空
p hash       # => {}

# ここは default_proc 値を返す
# ここが意図していないというチケット
p hash.shift # => 0

# hash,shift 後は中身が入ってる状態になる
p hash       # => {nil=>0}
# ので、これは [nil, 0] を返す
p hash.shift # => [nil, 0]
  • この挙動は確かに奇妙
  • チケットだと nil を返すほうがいい、みたいな意見もある

[Feature #17674] Proposal: Method#source_location or Method#owner for refined methods

# test.rb
module Cover
  refine Range do
    def cover?(value)
      return super unless value.is_a?(Range)

      super(value.first) && super(value.last)
    end
  end
end
using Cover

pp (1..10).method(:cover?).source_location
# Ruby 2.6 => nil
# Ruby 2.7 => ["/test.rb", 4]

pp (1..10).method(:cover?).owner
# Ruby 2.6 => Range
# Ruby 2.7 => #<refinement:Range@Cover>

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 内でインスタンス変数にアクセスしたりしているんですかね?普通に踏みそう