Why this program have type issues?


#1

I have a small program here:

using StaticArrays
struct NoTBModel
    norbits::Int64
    lat::SMatrix{3,3,Float64}
    hoppings::Dict{SVector{3,Int64},SparseMatrixCSC{Complex{Float64},Int64}}
end
function calculatemodel(nm::NoTBModel, order::Tuple{Int64,Int64,Int64}, k::Vector{<:Real})
    dH = zeros(Complex128, nm.norbits, nm.norbits)
    for (R, hopping) in nm.hoppings
        Rc = nm.lat*R
        dH += (im*Rc[1])^(order[1])*(im*Rc[2])^(order[2])*(im*Rc[3])^(order[3])*
            exp(im*2*π*(k⋅R))*hopping
    end
    for iorbit in 1:nm.norbits
        dH[iorbit, iorbit] = real(dH[iorbit, iorbit])
    end
    return Hermitian(dH)
end

However, @code_warntype tells me there are some variables (Rc, dH and return value) whose types cannot be inferred:

nm = NoTBModel(92, eye(3), Dict())
@code_warntype(calculatemodel(nm, (0, 0, 0), [0.0, 0.0, 0.0]))
Variables:
  #self# <optimized out>
  nm::NoTBModel
  order::Tuple{Int64,Int64,Int64}
  k::Array{Float64,1}
  R::SVector{3,Int64}
  hopping::SparseMatrixCSC{Complex{Float64},Int64}
  #temp#@_7 <optimized out>
  Rc::Any
  #temp#@_9::Int64
  iorbit::Int64
  #temp#@_11::Int64
  dH::Any
  i::Int64
  eltypeTicolptr::Array{Int64,1}
  eltypeTirowval::Array{Int64,1}
  eltypeTvnzval::Array{Complex{Float64},1}
  Tv <optimized out>
  Ti <optimized out>

Body:
  begin 
      SSAValue(31) = (Core.getfield)(nm::NoTBModel, :norbits)::Int64
      SSAValue(32) = (Core.getfield)(nm::NoTBModel, :norbits)::Int64
      $(Expr(:inbounds, false))
      # meta: location array.jl zeros 265
      # meta: location array.jl zeros 263
      SSAValue(12) = SSAValue(31)
      SSAValue(13) = SSAValue(32)
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop))
      dH::Any = $(Expr(:invoke, MethodInstance for fill!(::Array{Complex{Float64},2}, ::Complex{Float64}), :(Base.fill!), :($(Expr(:foreigncall, :(:jl_alloc_array_2d), Array{Complex{Float64},2}, svec(Any, Int64, Int64), Array{Complex{Float64},2}, 0, SSAValue(12), 0, SSAValue(13), 0))), :($(Expr(:new, Complex{Float64}, :((Base.sitofp)(Float64, 0)::Float64), :((Base.sitofp)(Float64, 0)::Float64)))))) # line 9:
      SSAValue(0) = (Core.getfield)(nm::NoTBModel, :hoppings)::Dict{SVector{3,Int64},SparseMatrixCSC{Complex{Float64},Int64}}
      $(Expr(:inbounds, false))
      # meta: location dict.jl start 574
      i::Int64 = $(Expr(:invoke, MethodInstance for skip_deleted(::Dict{SVector{3,Int64},SparseMatrixCSC{Complex{Float64},Int64}}, ::Int64), :(Base.skip_deleted), SSAValue(0), :((Core.getfield)(SSAValue(0), :idxfloor)::Int64))) # line 575:
      (Core.setfield!)(SSAValue(0), :idxfloor, i::Int64)::Int64
      # meta: pop location
      $(Expr(:inbounds, :pop))
      #temp#@_9::Int64 = i::Int64
      22: 
      unless (Base.not_int)((Base.slt_int)((Base.arraylen)((Core.getfield)(SSAValue(0), :vals)::Array{SparseMatrixCSC{Complex{Float64},Int64},1})::Int64, #temp#@_9::Int64)::Bool)::Bool goto 78
      $(Expr(:inbounds, false))
      # meta: location dict.jl next 579
      SSAValue(15) = (Base.arrayref)((Core.getfield)(SSAValue(0), :keys)::Array{SVector{3,Int64},1}, #temp#@_9::Int64)::SVector{3,Int64}
      SSAValue(14) = (Base.arrayref)((Core.getfield)(SSAValue(0), :vals)::Array{SparseMatrixCSC{Complex{Float64},Int64},1}, #temp#@_9::Int64)::SparseMatrixCSC{Complex{Float64},Int64}
      # meta: location pair.jl Type 4
      # meta: location sparse\sparsematrix.jl convert 323
      eltypeTicolptr::Array{Int64,1} = (Core.getfield)(SSAValue(14), :colptr)::Array{Int64,1} # line 324:
      eltypeTirowval::Array{Int64,1} = (Core.getfield)(SSAValue(14), :rowval)::Array{Int64,1} # line 325:
      eltypeTvnzval::Array{Complex{Float64},1} = (Core.getfield)(SSAValue(14), :nzval)::Array{Complex{Float64},1}
      # meta: pop location
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop))
      SSAValue(33) = $(Expr(:new, Pair{SVector{3,Int64},SparseMatrixCSC{Complex{Float64},Int64}}, SSAValue(15), :($(Expr(:invoke, MethodInstance for SparseMatrixCSC{Complex{Float64},Int64}(::Int64, ::Int64, ::Array{Int64,1}, ::Array{Int64,1}, ::Array{Complex{Float64},1}), SparseMatrixCSC{Complex{Float64},Int64}, :((Core.getfield)(SSAValue(14), :m)::Int64), :((Core.getfield)(SSAValue(14), :n)::Int64), :(eltypeTicolptr), :(eltypeTirowval), :(eltypeTvnzval))))))
      SSAValue(34) = $(Expr(:invoke, MethodInstance for skip_deleted(::Dict{SVector{3,Int64},SparseMatrixCSC{Complex{Float64},Int64}}, ::Int64), :(Base.skip_deleted), SSAValue(0), :((Base.add_int)(#temp#@_9, 1)::Int64)))
      SSAValue(2) = SSAValue(33)
      SSAValue(35) = (Base.getfield)(SSAValue(2), 1)::SVector{3,Int64}
      SSAValue(36) = (Base.add_int)(1, 1)::Int64
      R::SVector{3,Int64} = SSAValue(35)
      SSAValue(37) = (Base.getfield)(SSAValue(2), 2)::SparseMatrixCSC{Complex{Float64},Int64}
      SSAValue(38) = (Base.add_int)(2, 1)::Int64
      hopping::SparseMatrixCSC{Complex{Float64},Int64} = SSAValue(37)
      #temp#@_9::Int64 = SSAValue(34) # line 10:
      Rc::Any = (StaticArrays._A_mul_B)($(QuoteNode(Size(3, 3))), $(QuoteNode(Size(3,))), (Core.getfield)(nm::NoTBModel, :lat)::SMatrix{3,3,Float64}, R::SVector{3,Int64})::Any # line 11:
      SSAValue(26) = ((Main.im * (Main.getindex)(Rc::Any, 1)::Any)::Any ^ (Base.getfield)(order::Tuple{Int64,Int64,Int64}, 1)::Int64)::Any
      SSAValue(25) = ((Main.im * (Main.getindex)(Rc::Any, 2)::Any)::Any ^ (Base.getfield)(order::Tuple{Int64,Int64,Int64}, 2)::Int64)::Any
      SSAValue(24) = ((Main.im * (Main.getindex)(Rc::Any, 3)::Any)::Any ^ (Base.getfield)(order::Tuple{Int64,Int64,Int64}, 3)::Int64)::Any
      SSAValue(39) = $(Expr(:invoke, MethodInstance for vecdot(::Array{Float64,1}, ::SVector{3,Int64}), :(Base.LinAlg.vecdot), :(k), :(R)))
      $(Expr(:inbounds, false))
      # meta: location operators.jl * 424
      SSAValue(20) = (Base.select_value)((Core.getfield)(Main.im, :re)::Bool, 2, (Base.flipsign_int)(0, (Base.xor_int)(0, 2)::Int64)::Int64)::Int64
      SSAValue(21) = (Base.select_value)((Core.getfield)(Main.im, :im)::Bool, 2, (Base.flipsign_int)(0, (Base.xor_int)(0, 2)::Int64)::Int64)::Int64
      SSAValue(22) = (Base.mul_float)(3.141592653589793, (Base.sitofp)(Float64, SSAValue(20))::Float64)::Float64
      SSAValue(23) = (Base.mul_float)(3.141592653589793, (Base.sitofp)(Float64, SSAValue(21))::Float64)::Float64
      SSAValue(18) = SSAValue(39)
      # meta: pop location
      $(Expr(:inbounds, :pop))
      SSAValue(40) = $(Expr(:invoke, MethodInstance for exp(::Complex{Float64}), :(Main.exp), :($(Expr(:new, Complex{Float64}, :((Base.mul_float)(SSAValue(18), SSAValue(22))::Float64), :((Base.mul_float)(SSAValue(18), SSAValue(23))::Float64))))))
      SSAValue(41) = hopping::SparseMatrixCSC{Complex{Float64},Int64}
      $(Expr(:inbounds, false))
      # meta: location operators.jl * 424
      SSAValue(28) = ((SSAValue(26) * SSAValue(25))::Any * SSAValue(24))::Any
      # meta: location operators.jl afoldl 412
      SSAValue(29) = (SSAValue(28) * SSAValue(40))::Any
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop))
      dH::Any = (dH::Any + (SSAValue(29) * SSAValue(41))::Any)::Any
      76: 
      goto 22
      78:  # line 14:
      SSAValue(30) = (Core.getfield)(nm::NoTBModel, :norbits)::Int64
      SSAValue(42) = (Base.select_value)((Base.sle_int)(1, SSAValue(30))::Bool, SSAValue(30), (Base.sub_int)(1, 1)::Int64)::Int64
      #temp#@_11::Int64 = 1
      83: 
      unless (Base.not_int)((#temp#@_11::Int64 === (Base.add_int)(SSAValue(42), 1)::Int64)::Bool)::Bool goto 94
      SSAValue(43) = #temp#@_11::Int64
      SSAValue(44) = (Base.add_int)(#temp#@_11::Int64, 1)::Int64
      iorbit::Int64 = SSAValue(43)
      #temp#@_11::Int64 = SSAValue(44) # line 15:
      SSAValue(7) = (Main.real)((Main.getindex)(dH::Any, iorbit::Int64, iorbit::Int64)::Any)::Any
      (Main.setindex!)(dH::Any, SSAValue(7), iorbit::Int64, iorbit::Int64)::Any
      92: 
      goto 83
      94:  # line 17:
      return (Main.Hermitian)(dH::Any)::Hermitian{_,_} where _ where _
  end::Hermitian{_,_} where _ where _

I don’t understand the origin of this type instability. Can anyone help me with this?


#2

The problem is the definition of NoTBModel, in particular lat. SMatrix{3,3,Float64} is not a fully parameterized type, you have to define SMatrix{3,3,Float64, 9} instead.


#3

Works like a charm, Thank you!