The Julia JIT compiler compiles separate versions of generic functions for each unique function signature that gets called at the REPL. For example, if foo
is defined as
foo(x, y) = (x * y) ^ 2
then calling foo(2, 3)
and foo("a", "b")
will compile two different versions of foo
that correspond to the signatures foo(::Int, ::Int)
and foo(::String, ::String)
, respectively. Is there a way to get a list of the different function signatures that have been compiled for a generic function?
I know about the methods
function, but methods
only lists the methods of a generic function that have been written by the programmer. And, of course, as the foo
example above demonstrates, one method written by a programmer can spawn many separate compiled functions.
I'm just asking this for educational purposes. I don't have any code in which I plan to use the results of a hypothetical function that shows all the function signatures that have been compiled.
The MethodAnalysis package has tools for this and much more. For example:
julia> foo(x, y) = (x * y) ^ 2
foo (generic function with 1 method)
julia> foo(1,1); foo(1.0, 1);
julia> using MethodAnalysis
julia> methodinstances(foo)
2-element Vector{Core.MethodInstance}:
MethodInstance for foo(::Int64, ::Int64)
MethodInstance for foo(::Float64, ::Int64)
In some cases the specializations are not an svec
, methodinstances
makes it more straightforward to collect them in an easy-to-access format.
Perhaps there is a nicer way but this for sure works:
julia> foo(1,1);
julia> foo(1.0, 1);
julia> typeof(foo).name.mt.defs.func.specializations
svec(MethodInstance for foo(::Int64, ::Int64), MethodInstance for foo(::Float64, ::Int64), #undef, #undef, #undef, #undef, #undef, #undef)
Just to make sure it's mentioned here:
There is another package called LookingGlass.jl, which is quite similar to MethodAnalysis.jl, and provides a function for this too:
julia> foo(x, y) = (x * y) ^ 2
foo (generic function with 1 method)
julia> foo(1,1); foo(1.0, 1);
julia> using LookingGlass
julia> LookingGlass.func_specializations(foo)
Dict{Core.MethodInstance,Method} with 2 entries:
MethodInstance for foo(::Float64, ::Int64) => foo(x, y) in Main at REPL[4]:1
MethodInstance for foo(::Int64, ::Int64) => foo(x, y) in Main at REPL[4]:1
I've wanted to merge LookingGlass.jl together with MethodAnalysis.jl for quite some time, but always too busy. 😅
LookingGlass has other runtime reflection analysis tools, for modules, and functions, and methods, but I think the implementations in MethodAnalysis for this task are more robust, so @tholy's answer is probably best.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With