2022/05/26 今回の気になった bugs.ruby のチケット

今週は Refinements で protected されたメソッドが呼び出せないバグ報告がありました。

[Bug #18806] protected methods defined by refinements can't be called

  • Refinements で定義された protected がメソッドが呼び出せないというバグ報告
class A
end

module MyRefine
  refine A do
    private def private_foo
      "refined"
    end

    def private_foo_in_refinement
      private_foo
    end

    protected def protected_foo
      "refined"
    end

    def protected_foo_in_refinement
      # この呼び出しがエラーになる
      protected_foo
    end
  end
end

class A
  using MyRefine

  def call_private
    private_foo
  end

  def call_private_through_refinement
    private_foo_in_refinement
  end

  def call_protected
    # この呼び出しがエラーになる
    protected_foo
  end

  def call_protected_through_refinement
    protected_foo_in_refinement
  end

  def is_defined
    # defined? だとメソッドが定義されているように振る舞う
    defined?(protected_foo)
  end
end

pp A.new.call_private
# => :refined

pp A.new.call_private_through_refinement
# => :refined

pp A.new.call_protected
# => NoMethodError: protected method `protected_foo' called for #<A:0x00007f23f35e9390>

pp A.new.call_protected_through_refinement
# => NoMethodError: protected method `protected_foo' called for #<A:0x00007f23f35e9390>

pp A.new.is_defined
# "method"
  • 久々に Refinement のバグみたな?
    • これ、今まで見つかってなかったんだ…
  • protected でも問題なく protected のメソッドとして呼び出せるのが期待する挙動な気がする

[Bug #18793] Select and Find behave differently for hashes

  • 以下のように Hash#selectHash#find で挙動が違うというバグ報告
# キーにマッチした結果が返ってくる
{ 1..10 => :a, 11 .. 20 => :b }.select { _1 === 12 }
# => {11..20=>:b}

# しかし find の場合は見つからない
{ 1..10 => :a, 11 .. 20 => :b }.find { _1 === 12 }
# => nil

# select の _1 はキーを受け取る
{ 1..10 => :a, 11 .. 20 => :b }.select { p _1 }
# => 1..10
#    11..20

# find は [キー, 要素] の配列を受け取る
{ 1..10 => :a, 11 .. 20 => :b }.find { p _1 }
# => [1..10, :a]
  • _1 ではなくて { |k,| } のように , を付けてブロックの引数を受け取ると配列の第一要素のみを受け取るので両方共同じ挙動になる
# キーにマッチした結果が返ってくる
p({ 1..10 => :a, 11 .. 20 => :b }.select { |k,| k === 12 })
# => {11..20=>:b}

# しかし find の場合は見つからない
p({ 1..10 => :a, 11 .. 20 => :b }.find { |k,| k === 12 })
# => [11..20, :b]

# select の _1 はキーを受け取る
{ 1..10 => :a, 11 .. 20 => :b }.select { |k,| p k }
# => 1..10
#    11..20

# find は [キー, 要素] の配列を受け取る
{ 1..10 => :a, 11 .. 20 => :b }.find { |k,| p k }
# => 1..10

[Bug #18771] IO.foreach/.readlines ignores the 4th positional argument

  • IO.readlines の引数シグネチャは以下のようになっている
readlines(name, sep, limit [, getline_args, open_args]) → array
  • 位置引数を3つ受け取って、残りはキーワード引数で受け取るが、位置引数を4つ渡してもエラーにならないというバグ報告
    • ArgumentError になるのが期待する挙動
File.readlines('file.txt', "\n", 10)
# => ["abc\n", "\n", "def\n"]
File.readlines('file.txt', "\n", 10, {})
# => ["abc\n", "\n", "def\n"]
File.readlines('file.txt', "\n", 10, {chomp: true})
# => ["abc\n", "\n", "def\n"]
File.readlines('file.txt', "\n", 10, false)
# => ["abc\n", "\n", "def\n"]
File.readlines('file.txt', "\n", 10, nil)
# => ["abc\n", "\n", "def\n"]
readlines(path, rs = $/, chomp: false, opts={}) -> [String]
readlines(path, limit, chomp: false, opts={}) -> [String]
readlines(path, rs, limit, chomp: false, opts={}) -> [String]
readlines(name, sep=$/ [, getline_args, open_args]) → array
readlines(name, limit [, getline_args, open_args]) → array
readlines(name, sep, limit [, getline_args, open_args]) → array
readlines(name, sep=$/ [, getline_args, open_args]) → array
readlines(name, limit [, getline_args, open_args]) → array
readlines(name, sep, limit [, getline_args, open_args]) → array

[Bug #18797] Third argument to Regexp.new is a bit broken

# OK
Regexp.new('abc', Regexp::NOENCODING)

# error: /.../n has a non escaped non ASCII character in non ASCII-8BIT script: /あああ/ (RegexpError)
Regexp.new('あああ', Regexp::NOENCODING)
re = Regexp.new('あああ', nil, 'n') # => /あああ/
pp re.options.anybits? Regexp::NOENCODING   # => true

pp re.encoding   # => #<Encoding:ASCII-8BIT>
pp re.source.encoding   # => #<Encoding:UTF-8>

# error: incompatible encoding regexp match (ASCII-8BIT regexp with UTF-8 string) (Encoding::CompatibilityError)
pp re =~ "あああ"
  • Regexp.new の引数でどう制御できるのか軽く調べてみたけどあんまりよくわからなかった…