Subtype vs Abstract type in function definition

Is there a difference between these two functions? Is it just a coincidence/fluke of Julia syntax, or is there a deeper meaning that separates them or reason for both of them to be permitted.

function f(a::AbstractVector{Int})
    a.*2
end

function g(a::T) where T<:AbstractVector{Int}
    a.*2
end

To me the first one reads “f takes arguments of type exactly AbstractVector{Int}”, while the second one reads “g takes arguments that are subtypes of AbstractVector{Int}”. Am I reading this wrong?

Yes, a little wrong I believe. Since AbstractVector is an abstract type, you can’t actually instantiate an object with that type. So there can’t be an argument of type exactly AbstractVector{Int}. The two do behave the same (as far as I know).

The parametric type syntax is just more flexible–there are bound to be things you can express in both ways. In the docs, you can see more sophisticated uses that you can’t express otherwise:

https://docs.julialang.org/en/v1/manual/methods/#Parametric-Methods-1