How to get the current world age inside a generated function?

A generated function I’m writing needs to determine if its allowed to call a function its been passed, or if that would result in a world-age error (in which case it would fall back to something else). As part of this, I suppose I need to get the world-age that the generated function is currently running in and pass that to hasmethod, but this doesn’t seem to work. Here’s what I’ve tried:

defined_before() = "before"
@generated function try_call(func)
    if hasmethod(func.instance, (), world=Base.get_world_counter())
        func.instance()
    else
        "cant call"
    end
end
defined_after() = "after"
try_call(defined_before) # returns "before"; good
try_call(defined_after) # should return "cant call", instead MethodErrors

Adding a print statement around the Base.get_world_counter() inside the generated function reveals that it returns the “current” world-age after everything’s been defined, rather than the world-age inside the generated function (ie I’m guessing this is not what get_world_counter is meant for):

Int(Base.get_world_counter()) = 29689
ERROR: LoadError: MethodError: no method matching defined_after()
The applicable method may be too new: running in world age 29688, while current world is 29689.

So is there any way to do this, without just trying to call func and catching the potential MethodError? Alternatively, is there a better way to determine if a function is callable in the current world age?

You are not allowed to do this in a generated function. Its world age is always frozen to the world age it is defined in, since it would otherwise need to be recompiled every time any new method is defined.

1 Like

Not allowed to do what? Even just check whether the call is allowed by the current world-age?

Yes, you can’t ask for the world age a generated function is called in or the current world age.

1 Like

I see, thanks. I guess I could maybe accept that. But it does seem wierd to me then that I can still check whether I’m allowed to call the function by just trying and catching the MethodError should it occur. It kind of seems like the fundamental thing I’m trying to do is still allowed, just in an uglier way.

Anyway, you don’t have to answer this, but I am slightly curious if theres a simple example of how it would break Julia’s compilation model if there existed a get_current_world_age function which was usable from a generated function, and/or if hasmethod respected the current world age.

You might want to take a look at what GitHub - oxinabox/Tricks.jl: Cunning tricks though the julia compiler internals does. It manually attaches MethodInstances as backedges to CodeInfo objects, so that the generated function gets recompiled every time that method could potentially have been redefined. Be warned that this is very much an internal API though.

2 Likes