When type inference falters (::Any
in @code_warntype
printout), my understanding is that function calls are dynamically dispatched. In other words, at run-time, the arguments' types are checked to find the specialization (MethodInstance
) for the concrete argument types. Needing to do this at run-time instead of compile-time incurs performance costs.
(EDIT: originally, I said "multiple dispatch finds the fitting method" between the type-checking and specialization-finding, but I don't actually know if this part happens at runtime. It seems that it only needs to happen if no valid specialization exists and one needs to be compiled.)
In cases where only one argument's concrete type needs to be checked, is it possible to do a faster dynamic single dispatch instead, like in some sort of lookup table of specializations? I just can't find a way to access and call MethodInstance
s as if they were functions.
When it comes to altering dispatch or specialization, I thought of invoke
and @nospecialize
. invoke
looks like it might skip right to a specified method, but checking multiple argument types and specialization must still happen. @nospecialize
doesn't skip any part of the dispatch process, just results in different specializations.
EDIT: A minimal example with comments that hopefully describe what I'm talking about.
struct Foo end
struct Bar end
# want to dispatch only on 1st argument
# still want to specialize on 2nd argument
baz(::Foo, ::Integer) = 1
baz(::Foo, ::AbstractFloat) = 1.0
baz(::Bar, ::Integer) = 1im
baz(::Bar, ::AbstractFloat) = 1.0im
x = Any[Foo(), Bar(), Foo()]
# run test1(x, 1) or test1(x, 1.0)
function test1(x, second)
# first::Any in @code_warntype printout
for first in x
# first::Any requires dynamic dispatch of baz
println(baz(first, second))
# Is it possible to only dispatch -baz- on -first- given
# the concrete types of the other arguments -second-?
end
end