Just to extract some relevant points because the manual is quite dense:
Vector{Number}
is a concrete type, and [1, 2, 3]
has type Vector{Int}
, which is also a concrete type. One concrete type is never a subtype of another concrete type, they are the leaves of the type tree.
Vector{Number}
is concrete, even though Number
is not a concrete type. That’s because it has a concrete implementation which can store all types that are subtypes of Number
, it has a specific memory layout etc. On the other hand, AbstractVector{Int}
is the other way around and not a concrete type, because the container is abstract even though the element is concrete.
What you can do instead is [1, 2, 3] isa Vector{<:Number}
which is true
. That’s because <:Number
is a sort of placeholder which means “any type which is a subtype of Number”. This is often needed for dispatching on containers where you want to allow set of element types. f(x::Vector{Number})
can take only arguments of type Vector{Number}
, whereas g(x::Vector{<:Number})
can take e.g. Vector{Int}
, Vector{Float64}
, Vector{Real}
, Vector{Number}
, etc.