📌
[Bug #20643] Ruby 3.2 から private メソッドを yield self で呼び出したときの挙動が変わったバグ報告
[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)
- これは [Bug #18826] Symbol#to_proc inconsistent, sometimes calls private methods の影響で意図する変更になります
- #18826 は
Symbol#to_proc
でprivate
やprotected
なメソッドも呼び出せるというバグ報告で Ruby 3.1 では以下のように動作していました
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 }
であり、このときにprivate
やprotected
メソッドが呼ばれるのはおかしい、ということで 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
には特に載ってなかったんですね - バグ修正ではあるけど非互換な変更ではあるので注意したい
Discussion