world age issue in loading closure
While working at https://github.com/FluxML/model-zoo/pull/209, I encountered the following problem when loading a saved closure within the function train:
julia> import BSON
julia> function train()
model = x -> x
BSON.@save "model.bson" model
model = BSON.load("model.bson")[:model]
ŷ = model(1)
end
train (generic function with 1 method)
julia> train()
ERROR: MethodError: no method matching (::BSON.__deserialized_types__.var"#94#95")(::Int64)
The applicable method may be too new: running in world age 27203, while current world is 27204.
Closest candidates are:
#94(::Any) at REPL[73]:2 (method too new to be called from this world context.)
Stacktrace:
[1] train() at ./REPL[73]:5
[2] top-level scope at REPL[74]:1
Notice that if I just execute the body of the function in REPL, everything works fine:
julia> import BSON
julia> model = x -> x
#96 (generic function with 1 method)
julia> BSON.@save "model.bson" model
julia> model = BSON.load("model.bson")[:model]
#96 (generic function with 1 method)
julia> ŷ = model(1)
1
This is part of how Julia works:
julia> function test()
f = eval(:(x -> x))
f(1)
end
test (generic function with 1 method)
julia> test()
ERROR: MethodError: no method matching (::var"#3#4")(::Int64)
The applicable method may be too new: running in world age 26764, while current world is 26765.
So I'm not sure there's much we can do about it. I'd suggest that this is a bad code pattern and one should just stick to loading bson files at the toplevel.
If you really need it, you can use invokelatest.
I had similar problem too, I solved it by modifying the function I want to serialize in a way that all used variables are used as the input, so the function does not depend on the outer context. Then it works. Although it's a bit annoying, it's definitely less fragile.