✨
[Bug #20716] Ruby 2.7 と Ruby 3.x で `instance_method` の挙動が異なっているというバグ報告
[Bug #20716] Different instance_method behavior in Ruby 2.7 and Ruby 3.x
- Ruby 2.7 と Ruby 3.x で
instance_method
の挙動が異なっているというバグ報告 - 最初に提示されていたのは以下のようなコード
module A
def test(*args)
super
end
end
module B
def test(a)
puts a
end
end
B.prepend(A)
class C
include B
end
# この呼び出しは問題ない
B.instance_method(:test).bind(C.new).call(1)
# Ruby 2.7: 1
# Ruby 3.0: 1
# Ruby 3.1: 1
# lambda で B#test を再定義すると意図しないエラーになる
a = lambda do
puts 'lambda'
end
B.module_exec do
define_method(:test, a)
end
B.instance_method(:test).bind(C.new).call
# Ruby 2.7: lambda
# Ruby 3.0: wrong number of arguments (given 0, expected 1) (ArgumentError)
# Ruby 3.1: wrong number of arguments (given 0, expected 1) (ArgumentError)
-
define_method(:test, a)
したときになにか意図しない動作になっているんですかね? - 実際には
instance_method
というよりかはsuper
のキャッシュのバグらしい - なので
define_method
やinstance_method
を使用しない以下のコードで再現するらしい- https://bugs.ruby-lang.org/issues/20716#note-3
- 特定の mixin を行っている際に
super
を呼び出した後に異なるシグネチャのメソッドを定義すると再現するみたい
module A
def test(*args)
super
end
end
module B
def test(a)
puts a
end
end
class C; end
B.prepend(A)
C.include(B)
# ここで super のシグネチャがキャッシュされている
# メソッドを上書きする前に呼ばれなければ再現しない
C.new.test 1
module B
def test
puts 'lambda'
end
end
C.new.test
- Ruby 3.0 から再現してたんですが今まで報告がなかったんですねー
- 修正PR はすでに作成されています
Discussion