julia> methods(b4)
# 1 method for generic function "b4":
[1] b4(::Tuple{Vararg{var"#s6", n}} where var"#s6"<:Integer) where n in Main at REPL[15]:1
The compiler internally assigns a name to the integer part in b4’s signature. So it ends up being the same as a2 where the integer has to be the same concrete type.
The difference is subtle: a4 matches argument tuples of the type Tuple{Vararg{T} where T <: Integer}, while a5 narrows to Tuple{Vararg{T}} where T <: Integer. When called on two or more arguments, the latter is a diagonal type that restricts T to range over only concrete types, hence the MethodError.
OK, so it seems that I can call methods(my_function) to find out how the dispatch will behave for my function.
But does some consistent set of rules exist that I could learn to be able to predict this myself, because I’d like to avoid calling methods all the time?
EDIT: no, actually methods doesn’t even help me much, because it tells you almost nothing about a4, unlike with b4. And a4 is the surprising one for me.
The easiest way to test dispatch behavior is with subtyping relations. Julia’s dispatch rule is very simple and consistent in this respect: the method selected has the most specific type signature that your argument is a subtype of. For example:
Turns out that the mysteriousa4 was actually declared with a deprecated syntax, as shown by starting Julia with --depwarn=error:
$ julia --depwarn=error
_
_ _ _(_)_ | Documentation: https://docs.julialang.org
(_) | (_) (_) |
_ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
| | | | | | |/ _` | |
| | |_| | | | (_| | | Version 1.10.0-DEV.453 (2023-01-28)
_/ |\__'_|_|_|\__'_| | Commit 7d4309c9c31 (0 days old master)
|__/ |
julia> a4(::Vararg{<:Integer}) = nothing
ERROR: Wrapping `Vararg` directly in UnionAll is deprecated (wrap the tuple instead).
Stacktrace:
[1] UnionAll(v::TypeVar, t::Any)
@ Core ./boot.jl:257
I guess this revelation makes my questions from a few months ago moot, although it’s really too bad that Julia has to be started with a special flag to tell you this information.