Type Instability using StaticArrays that I dont get

Hello,
I have a type instability according to @code_warntype in the following code. To me it seems all types should be inferable though. What would I need to change to make it type stable?

using StaticArrays
import LinearAlgebra: norm

struct Line{T}
    p1::StaticVector{2, T}
    p2::StaticVector{2, T}
end

function closest_point_on_line(p::SVector{2, T}, line::Line{T}) where {T}
    length_squared = (line.p1[1]-line.p2[1])^2 + (line.p1[2]-line.p2[2])^2
    t = clamp(dot( p - line.p1, line.p2 - line.p1 )/length_squared, zero(T), one(T))
    return line.p1 + t*(line.p2 - line.p1)
end

@code_warntype closest_point_on_line(SVector(0.0, 1.0), Line(SVector(1.0, 0.0), SVector(1.0, 1.0)))
julia> isconcretetype(StaticVector{2, Float64})
false

julia> isconcretetype(SVector{2, Float64})
true
3 Likes

Oh ok, I somehow assumed StaticVector would be an alias of SVector. Thanks for that tip. One instability remains though. Apparently a dot product of 2 SVector s gives an Any. I guess there is not much i can do about that, except assert the type of the result?

It’s type stable for me

julia> @code_warntype dot(a, b)
MethodInstance for LinearAlgebra.dot(::SVector{2, Float64}, ::SVector{2, Float64})
  from dot(a::StaticArray, b::StaticArray) @ StaticArrays ~/.julia/packages/StaticArrays/oOCPP/src/linalg.jl:208
Arguments
  #self#::Core.Const(LinearAlgebra.dot)
  a::SVector{2, Float64}
  b::SVector{2, Float64}
Body::Float64
1 ─      nothing
β”‚   %2 = StaticArrays.same_size(a, b)::Core.Const(Size(2,))
β”‚   %3 = StaticArrays._vecdot(%2, a, b, StaticArrays.dot)::Float64
└──      return %3

Even if it would be type unstable, you could also implement is as a'b or using a loop etc., there would be plenty of options :wink:

You only imported norm from LinearAlgebra and forgot about dot.

2 Likes