【一人 bugs.ruby Advent Calendar 2021】[Bug #17423] `Prepend` should prepend a module before the class【21日目】

一人 bugs.ruby Advent Calendar 2021 21日目の記事になります。
今日は prepend の挙動がちょっと変わる話です。

[Bug #17423] Prepend should prepend a module before the class

Ruby 3.0 では継承リスト周りの処理が色々と改善されました。
が、結果 #prepend が意図する挙動をしていないケースがありました。

module M; end
module A; end
class B; include A; end

A.prepend M
B.prepend M

# B に prepend M しているのに反映されてないように見える
p B.ancestors
# 2.7 => [M, B, A, Object, Kernel, BasicObject]
# 3.0 => [B, M, A, Object, Kernel, BasicObject]

これの対処として [M, B, M, A, Object, Kernel, BasicObject] を返すようにする、というのがこのチケットの内容です。
この場合は ancestors の結果に対して M が重複してしまうんですが、次のようなコードでも重複するので問題ないとのこと。

module M; end
class A; end
class B<A; end

A.prepend M
B.prepend M

# これは Ruby 3.0 以前からこのような挙動になっている
p B.ancestors # => [M, B, M, A, Object, Kernel, BasicObject]

これは既にマージされており、 Ruby 3.1 以降は以下のような挙動になる予定です。

module M; end
module A; end
class B; include A; end

A.prepend M
B.prepend M

p B.ancestors
# 2.7 => [M, B, A, Object, Kernel, BasicObject]
# 3.0 => [B, M, A, Object, Kernel, BasicObject]
# 3.1 => [M, B, M, A, Object, Kernel, BasicObject]

このあたりはちょっと注意して使う必要がありそうですねえ。
ちなみにこのチケットは matz が立ててました。珍しいものをみた。