【一人 bugs.ruby Advent Calendar 2021】[Bug #17571] prependしたArray#[] が反映されない【16日目】

一人 bugs.ruby Advent Calendar 2021 16日目の記事になります。
今日はArrayprepend してる #[] が呼び出されないバグの話です。

[Bug #17571] prependしたArray#[] が反映されない

以下のように Arrayprepend してる #[] が呼び出されないことがあるというバグ報告です。

module TestMod
  def [](*)
    :called
  end
end
Array.prepend TestMod

# 引数がある場合
# これは Array#[] が呼ばれる
p [1, 2, 3][1]
# => 2

# 引数がない場合
# これは TestMod#[] が呼ばれる
p [1, 2, 3][]
# => :called

# Method オブジェクトは TestMod を指している
p [1, 2, 3].method(:[])
# => #<Method: Array(TestMod)#[](*) /tmp/vud3mdg/27:2>

[1, 2, 3][1] が意図していない挙動になっています。
これは Array#[] を事前にメソッドキャッシュしており、そちらを優先して呼び出しているのが原因らしいです。
なので prepend しているメソッドは呼ばれなくなっていた。
更に引数がない場合は Array#[]シグネチャが異なるのでキャッシュされたメソッドではなくて prepend されたメソッドを呼び出しているので意図する挙動になっているようです。
これは Ruby 3.0 に存在しているバグで Ruby 3.1 では修正されています。