📌

[Bug #20188] autoload 中に `Module#const_source_location の値が正しく取得できない

2024/02/20に公開

[Bug #20188] Module#const_source_location returns wrong information when real constant was defined but autoload is still ongoing

  • autoload 中に Module#const_source_location の値が正しく取得できないというバグ報告
# /tmp/autoload.rb
File.write("/tmp/const.rb", <<~RUBY)
module Const
  LOCATION = Object.const_source_location(:Const)
end
RUBY

autoload :Const, "/tmp/const"

p Const::LOCATION
# 期待する値 => ["/tmp/const.rb", 8]
# 実際の値   => ["/tmp/autoload.rb", 8]

# これは意図する位置を返す
p Object.const_source_location(:Const)
# => ["/tmp/const.rb", 1]
  • autoload のスレッドセーフを保つために autoload が完了するまでは他のスレッドに値を公開されないようにするためぽい?ってコメントがされています
  • その延長戦で autoload 中に例外が発生した場合は『そこで定義した定数が定義されない』みたいな話もあるみたいですね
# /tmp/foo.rb
File.write('/tmp/bar.rb', 'Bar = 1; raise')
autoload :Bar, '/tmp/bar'

# ここで Bar を呼び出しており autoload 経由で `/tmp/bar` が読み込まれる
# このときに内部で例外が発生する
Bar rescue nil

# 例外が発生すると Bar が定義されていない状態として扱われる
p Object.const_source_location(:Bar) # ["/tmp/foo.rb", 3]
p Object.autoload?(:Bar) # "/tmp/bar"

# なので再度 Bar を呼び出すと autoload が発火し、また例外が発生する
p Bar # raises
GitHubで編集を提案

Discussion