今週の気になった bugs.ruby のチケット

なんとなく書き溜めるようにしてみました。
内容は適当です。
今週と言っても今週みかけたチケットなだけでチケット自体は昔からあるやつもあります。

Feature #16828 Introduce find patterns

  • パターンマッチで条件にマッチした一部の要素だけ取得できる提案
case ["a", 1, "b", "c", 2, "d", "e", "f", 3]
in [*pre, String => x, String => y, *post]
  p pre  #=> ["a", 1]
  p x    #=> "b"
  p y    #=> "c"
  p post #=> [2, "d", "e", "f", 3]
end

Bug #16852 Refining Enumerable fails with ruby 2.7

  • 2.7 系の Refinements のバグ
  • refine M したあとに include M を行うといろいろとぶっ壊れるぽい
  • RSpec 関連で報告があったんですが、最小構成を調べてコメントしました
  • 最小構成は以下の通りで RSpec 関係なく再現しました。
module M; end
class X
  include M
end

module RefinementBug
  refine M do
    def refined_method
      puts "Called #refined_method"
    end
  end
end

class Y
  # Error if include M
  include M
end

using RefinementBug

puts "Using Ruby #{RUBY_VERSION}"

# error: undefined method `refined_method' for #<X:0x000055d4e22468c0> (NoMethodError)
X.new.refined_method

Bug #16932 defined? on refined method call returns non-nil even before using

  • Refinements で定義したメソッドが defined? に反映されていなかったバグ
  • 修正済み
class A
end

a = A.new
p defined?(a.x) #=> nil (OK)

m = Module.new do
  refine(A) do
    def x
    end
  end
end

a.x rescue p $! #=> NoMethodError: undefined method `x'
p defined?(a.x) #=> "method" (NG)

using m
p defined?(a.x) #=> "method" (OK)

Feature #14267 Lazy proc allocation introduced in #14045 creates regression

  • Proc 同士の比較が非互換になって RSpec で困ってる(いた?)らしい
  • チケット自体はかなり前
# regression.rb
def return_proc(&block)
  block
end

def return_procs(&block)
  block.inspect if ENV['INSPECT_BLOCK']

  proc_1 = return_proc(&block)
  proc_2 = return_proc(&block)

  return proc_1, proc_2
end

proc_1, proc_2 = return_procs { }

puts RUBY_VERSION
puts "Proc equality: #{proc_1 == proc_2}"
$ chruby 2.4
$ ruby regression.rb
2.4.2
Proc equality: true
$ chruby 2.5
$ ruby regression.rb
2.5.0
Proc equality: false
  • 2.5 当時のチケット

Feature #16928 Array#include_all? & Array#include_any?

# Array#include_all?(other_array)
[1, 2, 3, 4].include_all?([2, 4]) # returns true
[1, 2, 3, 4].include_all?([2, 4, 5]) # returns false
[1, 2, 3, 4].include_all?([]) # returns true
[1, 2, 3, 4].include_all?(nil) # returns false

# Array#include_any?(other_array)
[1, 2, 3, 4].include_any?([2, 4, 5]) # returns true
[1, 2, 3, 4].include_any?([6, 7]) # returns false
[1, 2, 3, 4].include_any?([]) # returns true
[1, 2, 3, 4].include_any?(nil) # returns false
  • どういうときに便利なんだろうか
  • 名前から期待する挙動がわかりづらい
  • 既存のコードでもっといい書き方ないかな

Feature #16924 instance_eval equivalent for RubyVM::InstructionSequence

  • iseq を任意のコンテキスト(レシーバ)で評価したいっていう提案
# ___path にかかれている Ruby のコードを ___dsl_object をレシーバにして実行したい
___dsl_object.instance_eval(File.read(___path),___path,0)

これを iseq 経由で実行するようにしたい

# ___path の中身を iseq に変換
iseq = RubyVM::InstructionSequence.compile_file(___path)
# その iseq を ___dsl_object をレシーバにして評価する
iseq.eval_in_instance(___dsl_object)

Bug #16919 IRB でマジックコメントの : の後に任意の文字を入力するとエラーが発生する

  • irb 上で #coding:u と入力して確定すると irb がクラッシュする
  • そもそも確定しなくても入力中にクラッシュする
    • #coding:utf-8 を入力中等
    • これは irb が入力毎に Ripper でパースしている為`