Reputation: 7664
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.
Upvotes: 6
Views: 563
Reputation: 8056
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.
Upvotes: 4
Reputation: 12179
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.
Upvotes: 14
Reputation: 42214
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)
Upvotes: 7