【一人 bugs.ruby Advent Calendar 2020】[Feature #17292] id outputed by inspect and to_s output does not allow to find actual object_id and vice-versa【21日目】

一人 bugs.ruby Advent Calendar 2020 21日目の記事になります。

[Misc #17199] id outputed by inspect and to_s output does not allow to find actual object_id and vice-versa

Ruby 2.7 から #inspect ( #to_s ) と #__id__ が返すアドレスの関連性が一致しなくなったという報告チケットなります。
どういうことかというと Ruby 2.7 から以下のように #__id__ が返す値が変わりました。

obj = Object.new

# Ruby 2.7 から #__id__ の値が変わった
p "#__id__=#{obj.__id__}"
# Ruby 2.6 => "#__id__=47458875463160"
# Ruby 2.7 => "#__id__=60"

これと #inspect がどう関係あるのかというと #__id__ から #inspect で表示されるアドレスを推論できていたんですが、それが上記の変更でできなくなりました。

obj = Object.new
p "#inspect=#{obj.inspect}"
# => "#inspect=#<Object:0x00005653c2d3abf0>"

# Ruby 2.6 では __id__ の結果をシフトすると inspect に表示される id と同じになっていた
# しかし Ruby 2.7 ではできなくなっている
p "shifted_id=#{(obj.__id__ << 1).to_s(16)}"
# Ruby 2.6 => "shifted_id=5653c2d3abf0"
# Ruby 2.7 => "shifted_id=78"

これにより何が起きるのかというと例えば #inspect の出力の 0x00005653c2d3abf0 というアドレスから __id__ を推論する事ができたので次のように ObjectSpace._id2ref で実際のオブジェクトの値を取得する事ができていました。
しかし、 Ruby 2.7 の変更によりこれはできなりました。

o = Object.new
# 任意の __id__ からそのオブジェクトが取得できる
pp ObjectSpace._id2ref(o.__id__)

# inspect から id を取得してそれを元にしてオブジェクトを取得する事ができた
# これが Ruby 2.7 からは動作しなくなっている
id_from_inspect = o.inspect[/#<Object:(.*)>/, 1].to_i(16)
pp ObjectSpace._id2ref(id_from_inspect >> 1)

こんな仕様があったんですね…。
例えば Object#inspect をログ出力しているような場合にその出力されたアドレスから『実際のオブジェクトを参照したい』みたいな場合に利用できるのかなあ、とは思いました。