Ruby 3.1 でオブジェクトが生成された箇所が表示できるようになった

Ruby 3.1 の小ネタです。
Ruby 3.1 で objspace/trace というライブラリが追加されました。
このライブラリを require すると p で出力するときに『オブジェクトが生成された箇所』が一緒に表示されるようになります。

# このライブラリを require するとオブジェクトが生成された場所がトレースされるようになる
# require した後に生成されたオブジェクトが対象となる
require "objspace/trace"

obj = Object.new

# p する時に obj が生成された場所が表示される
p obj
# => #<Object:0x00007fce8b2ea778> @ /path/to/test.rb:5

# こういうのも表示される
str = 42.to_s
p str
# => "42" @ /path/to/test.rb:11


# クラス内で生成されたオブジェクトも取得できる
class X
  attr_accessor :value

  def initialize
    @value = "hoge"
  end

  def hoge
    self.value = "bar"
  end
end

x = X.new

p x.value
# => "hoge" @ /path/to/test.rb:22

x.hoge
p x.value
# => "hoge" @ /path/to/test.rb:26

こんな感じで各オブジェクトが生成された場所が生成されます。
また objspace/trace を使っている場合は objspace/trace is enabled が表示されます。

注意点

objspace/trace はあくまでも『オブジェクトが生成された場所』が表示されるのであって『変数が定義された場所ではない』という注意点があります。
なので、例えば次のように定数を変数に代入している場合は『定数が定義された位置』が表示されるようになります。

require "objspace/trace"

C = Object.new

obj = C

# これは obj 変数が定義された場所ではなくて C が定義された場所が出力される
p obj
# => #<Object:0x00007f6e1111e438> @ /path/to/test.rb:3

他には数値や nil などの値も表示されなかったり

require "objspace/trace"

obj = 1 + 2

p obj

obj2 = "42".to_i
p obj2

obj3 = nil
p obj3

# frozen_string_literal: true している場合は文字列リテラルの生成位置も表示されません。

require "objspace/trace"

str = "homu"

# これは表示される
p str
# => "homu" @ /path/to/test.rb:3
require "objspace/trace"

str = "homu"

# これは表示される
p str
# => "homu" @ /path/to/test.rb:3
# frozen_string_literal: true

require "objspace/trace"

str = "homu"

# これは表示されない
p str
# => "homu"

# リテラル以外で生成された文字列は表示される
str2 = str + str
p str2
# => "homuhomu" @ /path/to/test.rb:12

おまけ

メタプロ的に定義されている場合でも問題なく取得できた。

require "objspace/trace"

# 動的に生成している場合でも位置情報は取得できる
eval(<<~EOS, binding, __FILE__, __LINE__ + 1)
@value = "hoge"
def  hoge
  @value
end
EOS

p hoge
# => "hoge" @ /path/to/test.rb:5

# 動的に変数を定義した場合も取得できる
bind = binding
bind.local_variable_set(:value, "mami")

p bind.local_variable_get(:value)
# => "mami" @ /path/to/test.rb:14