Регрессия в методе Hash#reject версии Ruby 2.1.1

В Ruby 2.1.0 и ранее метод reject любого класса, отнаследованного от Hash, возвращал объект этого же класса. Однако, в Ruby 2.1.1 это поведение неожиданно изменилось, и метод всегда возвращает простой Hash, а не унаследованный класс.

class SubHash < Hash
end

p Hash.new.reject { }.class
#=> 2.1.0: Hash, 2.1.1: Hash
p SubHash.new.reject { }.class
#=> 2.1.0: SubHash, 2.1.1: Hash

(Если быть точным, то переменные инстанса тоже не копируются.)

Релиз Ruby 2.1.1 не должен был так менять поведение, так как с выхода 2.1.0 мы изменили политику версионирования, т.е. Ruby 2.1.1 является патч-релизом и не должен был ломать совместимость.

Эта регрессия затрагивает множество библиотек, например, рельсовые классы HashWithIndifferentAccess и OrderedHash оказались сломаны: баг #14188.

Это поведение будет возвращено назад в Ruby 2.1.2, но после релиза 2.2.0 станет обычным поведением Тикет #9223. Так что рекомендуется исправить код в соответствии с этим.

Баг произошел из-за лишнего коммита во время обратного портирования изменений. Для дальнейшей информации см. http://blog.sorah.jp/2014/03/10/hash-reject-regression-in-ruby211.

Приносим свои извинения за неудобства. Спасибо за вашу поддержку.