About the type constraint of `where`

You’re mixing up the types in dispatch and the default element type promotion of array instantiation, which occur separately:

julia> function myappend(x::T, v::Vector{T}) where {T} # dispatch
         @info T, typeof(v), typeof(x)
         [v..., x] # array instantiation, element type promotion
       end
myappend (generic function with 1 method)

julia> myappend(true, Real[1, 2.0])
[ Info: (Real, Vector{Real}, Bool)
3-element Vector{Float64}:
 1.0
 2.0
 1.0

The function call was dispatched to the most fitting (and only) method. The static parameter T was inferred to be Real, as you provided v isa Vector{Real} and true isa Bool <: Real.

When you instantiated the result vector, you splat the elements of v and x, which are 1, 2.0, true. By default, array instantiation tries to promote numbers to one concrete type; in this case Float64, so 1 becomes 1.0, 2.0 stays, true becomes 1.0. Note that the promoted type is NOT a supertype of all the original types; Float64 is not a supertype of Int64 or Bool.

Again, these are two independent events, and method dispatch doesn’t promote types. The automatic promotion in the array instantiation wasn’t necessary either, you could have designated the static parameter as the element type of the array. The elements are unchanged:

julia> function ourappend(x::T, v::Vector{T}) where {T} # dispatch
         @info T, typeof(v), typeof(x)
         T[v..., x] # array instantiation, no promotion
       end
ourappend (generic function with 1 method)

julia> ourappend(true, Real[1, 2.0])
[ Info: (Real, Vector{Real}, Bool)
3-element Vector{Real}:
    1
    2.0
 true
3 Likes