📌

[Bug #20643] Ruby 3.2 から private メソッドを yield self で呼び出したときの挙動が変わったバグ報告

2024/07/20に公開

[Bug #20643] Ruby 3.2 behavior change for protected and private methods when yield self

  • 以下のコードが Ruby 3.2 から挙動が変わったというバグ報告
class Foo
  def try
    yield self
  end

  private

  def bar
    "private method bar called"
  end
end

# 内部では :bar.to_proc.call(Foo.new) が呼び出される
pp Foo.new.try(&:bar)
# Ruby 3.1 => "private method bar called"
# Ruby 3.2 => error: private method `bar' called for an instance of Foo (NoMethodError)
class X
  private

  def foo
    "foo"
  end
end

# X.new.foo が呼び出される
pp :foo.to_proc.call(X.new)
# => "foo"
  • しかし :foo.to_proc の期待する動作は lambda { |t| t.foo } であり、このときに privateprotected メソッドが呼ばれるのはおかしい、ということで Ruby 3.2 で修正されました
class X
  private

  def foo
    "foo"
  end
end

# X.new.foo が呼び出される
pp :foo.to_proc.call(X.new)
# Ruby 3.1 => "foo"
# Ruby 3.2 => error: private method `foo' called for #<X:0x00007149b83a8e50> (NoMethodError)
  • そういえばこういう修正があったなーと思い出したんですが NEWS には特に載ってなかったんですね
  • バグ修正ではあるけど非互換な変更ではあるので注意したい
GitHubで編集を提案

Discussion