【一人 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 が立ててました。珍しいものをみた。