📌
[Bug #20188] autoload 中に `Module#const_source_location の値が正しく取得できない
[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
- そこから複数のスレッドから
autoload
(やrequire
)が呼び出された時にどうするのか、みたいな話に発展しています - ザッと読んだんですがスレッド周りなど思ったよりも話が深い…
Discussion