diff --git a/src/MethodAnalysis.jl b/src/MethodAnalysis.jl index d471480..2db9ab2 100644 --- a/src/MethodAnalysis.jl +++ b/src/MethodAnalysis.jl @@ -66,17 +66,36 @@ equal(p1::Pair, p2::Pair) = p1.second == p2.second && equal(p1.first, p2.first) """ mi = instance(f, types) + mi = instance(tt::Type{<:Tuple}) -Return the `MethodInstance` `mi` for function `f` and the given `types`. +Return the `MethodInstance` `mi` for function `f` and the given `types`, +or for the complete signature `tt`. If no version compiled for these types exists, returns `nothing`. + +# Examples + +```jldoctest; setup=:(using MethodAnalysis) +julia> f(x, y::String) = 2x; f(x, y::Number) = x + y; + +julia> f(1, "hi"); f(1, 1.0); + +julia> instance(f, (Int, String)) +MethodInstance for f(::Int64, ::String) + +julia> instance(Tuple{typeof(f), Int, String}) +MethodInstance for f(::Int64, ::String) +``` """ -function instance(f, types) - m = which(f, types) +function instance(@nospecialize(f), @nospecialize(types)) + if types isa Tuple + m = which(f, types) + tt = Tuple{typeof(f), types...} + return instance(m, tt) + end inst = nothing - tt = Tuple{typeof(f), types...} - visit(m) do mi + visit(f) do mi if isa(mi, MethodInstance) - if mi.specTypes === tt + if mi.specTypes === types inst = mi end return false @@ -85,6 +104,11 @@ function instance(f, types) end return inst end +function instance(@nospecialize(types)) + f, argt = call_type(types) + m = which(f, argt) + return instance(m, types) +end AbstractTrees.children(mi::MethodInstance) = isdefined(mi, :backedges) ? mi.backedges : [] diff --git a/test/runtests.jl b/test/runtests.jl index 8a347f7..db2201e 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -13,6 +13,9 @@ module Outer f(x) = 1 callh(x) = Inner.h(x) callcallh(x) = callh(x) + + f2(x, y::String) = 2x + f2(x, y::Number) = x + y end @@ -84,6 +87,11 @@ end @test instance(Outer.callcallh, (Int,)) ∈ bes @test length(bes) == 5 + Outer.f2(1, "hello") + m = which(Outer.f2, (Int, String)) + tt = Tuple{typeof(Outer.f2),Int,String} + @test instance(Outer.f2, (Int, String)) === instance(m, tt) === instance(tt) + hbes = filter(mi->mi.def ∈ methods(Outer.Inner.h), bes) @test length(hbes) == 2 allhbes = with_all_backedges(hbes)