I found a newer example here in the Unitful docstring that makes me think it’s something to do with how this is implemented in Unitful.
Based on the Module docs here, a function __init__()
in a module is executed at runtime vs compile time… I’m not sure I quite understand this distinction because working this way I get the error at precompile time.
I tried defining a MyUnits.jl
file, per the Unitful.register
docstring linked above:
module MyUnits
using Unitful
@unit pt "pt" pt (1//72)*u"inch" false
const mm = u"mm"
const cm = u"cm"
const pt = u"pt"
function __init__()
Unitful.register(MyUnits)
end
end
Now I get the following error, instead.
julia> using MyUnits: mm, pt
[ Info: Precompiling MyUnits [top-level]
ERROR: LoadError: ArgumentError: Symbol pt could not be found in unit modules Module[Unitful]
Stacktrace:
[1] lookup_units(unitmods::Vector{Module}, sym::Symbol)
@ Unitful C:\Users\x\.julia\packages\Unitful\R4J37\src\user.jl:707
[2] var"@u_str"(__source__::LineNumberNode, __module__::Module, unit::Any)
@ Unitful C:\Users\x\.julia\packages\Unitful\R4J37\src\user.jl:639
[3] include
@ .\Base.jl:457 [inlined]
[4] include_package_for_output(pkg::Base.PkgId, input::String, depot_path::Vector{String}, dl_load_path::Vector{String}, load_path::Vector{String}, concrete_deps::Vector{Pair{Base.PkgId, UInt128}}, source::Nothing)
@ Base .\loading.jl:2049
[5] top-level scope
@ stdin:3
in expression starting at C:\Users\x\AppData\Local\Temp\jl_znDJGl\MyUnits.jl:8
in expression starting at C:\Users\x\AppData\Local\Temp\jl_znDJGl\MyUnits.jl:1
in expression starting at stdin:3
ERROR: Failed to precompile MyUnits [top-level] to "C:\\Users\\x\\.julia\\compiled\\v1.9\\jl_9F38.tmp".
Stacktrace:
[1] error(s::String)
@ Base .\error.jl:35
[2] compilecache(pkg::Base.PkgId, path::String, internal_stderr::IO, internal_stdout::IO, keep_loaded_modules::Bool)
@ Base .\loading.jl:2294
[3] compilecache
@ .\loading.jl:2167 [inlined]
[4] _require(pkg::Base.PkgId, env::String)
@ Base .\loading.jl:1805
[5] _require_prelocked(uuidkey::Base.PkgId, env::String)
@ Base .\loading.jl:1660
[6] macro expansion
@ .\loading.jl:1648 [inlined]
[7] macro expansion
@ .\lock.jl:267 [inlined]
[8] require(into::Module, mod::Symbol)
@ Base .\loading.jl:1611
I’m a moderate user of Unitful.jl and have made significant use of it in my own packages, but I’ve always been a little puzzled by the unit definition/registration system. Now, TIL __init__
module functions are a thing. The more you know, I guess.