Hello!
The real code is a bit of a mess, so just giving an example and looking for a hint. I have defined a struct as:
@with_kw struct CLL{I,T,D}
Points::Vector{SVector{D,T}}
MaxValidIndex::Base.RefValue{Int} = Ref(0)
CutOff::T
CutOffSquared::T = CutOff^2
Padding::I = 2
HalfPad::I = convert(typeof(Padding),Padding//2)
ZeroOffset::I = 1 #Since we start from 0 when generating cells
ListOfInteractions::Vector{Tuple{I,I,T}} = Vector{Tuple{Int,Int,getsvecT(eltype(Points))}}(undef,length(Points)^2)
Stencil::Vector{NTuple{D, I}} = neighbors(Val(getsvecD(eltype(Points))) )
Cells::Vector{NTuple{D, I}} = ExtractCells(Points,CutOff,Val(getsvecD(eltype(Points))))
UniqueCells::Vector{NTuple{D, I}} = unique(Cells)
Nmax::I = maximum(reinterpret(Int,@view(Cells[:]))) + ZeroOffset
Layout::Array{Vector{I}, D} = GenerateM(Nmax,ZeroOffset,HalfPad,Padding,Cells,Val(getsvecD(eltype(Points))))
end
In which I
is an Integer
type, T
is a float type and D
is dimensions, 2d or 3d.
I have noticed that when I use @code_warntype
on this struct I get:
MethodInstance for Core.kwcall(::@NamedTuple{Points::Vector{SVector{2, Float64}}, CutOff::Float64}, ::Type{CLL})
from kwcall(::NamedTuple, ::Type{CLL}) @ Main c:\git\SPHExample\example\TempRepoCLL.jl:7
Arguments
_::Core.Const(Core.kwcall)
@_2::@NamedTuple{Points::Vector{SVector{2, Float64}}, CutOff::Float64}
@_3::Type{CLL}
Locals
@_4::Any
Points::Vector{SVector{2, Float64}}
MaxValidIndex::Base.RefValue{Int64}
CutOff::Float64
CutOffSquared::Float64
Padding::Int64
HalfPad::Int64
ZeroOffset::Int64
ListOfInteractions::Vector{Tuple{Int64, Int64, Float64}}
Stencil::Vector{Tuple{Int64, Int64}}
Cells::Vector{Tuple{Int64, Int64}}
UniqueCells::Vector{Tuple{Int64, Int64}}
Nmax::Int64
Layout::Matrix{Vector{Int64}}
@_18::SubArray{Tuple{Int64, Int64}, 1, Vector{Tuple{Int64, Int64}}, Tuple{Base.Slice{Base.OneTo{Int64}}}, true}
Body::CLL{Int64, Float64, 2}
1 ββ Core.NewvarNode(:(@_4))
β %2 = Core.isdefined(@_2, :Points)::Core.Const(true)
ββββ goto #3 if not %2
2 ββ (@_4 = Core.getfield(@_2, :Points))
ββββ goto #4
3 ββ Core.Const(:(Core.UndefKeywordError(:Points)))
ββββ Core.Const(:(@_4 = Core.throw(%6)))
4 ββ %8 = @_4::Vector{SVector{2, Float64}}
β (Points = %8)
β %10 = Core.isdefined(@_2, :MaxValidIndex)::Core.Const(false)
ββββ goto #6 if not %10
5 ββ Core.Const(:(@_4 = Core.getfield(@_2, :MaxValidIndex)))
ββββ Core.Const(:(goto %15))
6 ββ (@_4 = Main.Ref(0))
β %15 = @_4::Base.RefValue{Int64}
β (MaxValidIndex = %15)
β %17 = Core.isdefined(@_2, :CutOff)::Core.Const(true)
ββββ goto #8 if not %17
7 ββ (@_4 = Core.getfield(@_2, :CutOff))
ββββ goto #9
8 ββ Core.Const(:(Core.UndefKeywordError(:CutOff)))
ββββ Core.Const(:(@_4 = Core.throw(%21)))
9 ββ %23 = @_4::Float64
β (CutOff = %23)
β %25 = Core.isdefined(@_2, :CutOffSquared)::Core.Const(false)
ββββ goto #11 if not %25
10 β Core.Const(:(@_4 = Core.getfield(@_2, :CutOffSquared)))
ββββ Core.Const(:(goto %34))
11 β %29 = Main.:^::Core.Const(^)
β %30 = CutOff::Float64
β %31 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2})
β %32 = (%31)()::Core.Const(Val{2}())
β (@_4 = Base.literal_pow(%29, %30, %32))
β %34 = @_4::Float64
β (CutOffSquared = %34)
β %36 = Core.isdefined(@_2, :Padding)::Core.Const(false)
ββββ goto #13 if not %36
12 β Core.Const(:(@_4 = Core.getfield(@_2, :Padding)))
ββββ Core.Const(:(goto %41))
13 β (@_4 = 2)
β %41 = @_4::Core.Const(2)
β (Padding = %41)
β %43 = Core.isdefined(@_2, :HalfPad)::Core.Const(false)
ββββ goto #15 if not %43
14 β Core.Const(:(@_4 = Core.getfield(@_2, :HalfPad)))
ββββ Core.Const(:(goto %50))
15 β %47 = Main.typeof(Padding::Core.Const(2))::Core.Const(Int64)
β %48 = (Padding::Core.Const(2) // 2)::Core.Const(1//1)
β (@_4 = Main.convert(%47, %48))
β %50 = @_4::Core.Const(1)
β (HalfPad = %50)
β %52 = Core.isdefined(@_2, :ZeroOffset)::Core.Const(false)
ββββ goto #17 if not %52
16 β Core.Const(:(@_4 = Core.getfield(@_2, :ZeroOffset)))
ββββ Core.Const(:(goto %57))
17 β (@_4 = 1)
...
It does make sense to me why it is Any
, from the code snippet above I see that _@4
is overwritten a lot of times.
I noticed that if I limit my struct to the first four fields, i.e. before hitting I
field type, then it does not come up as Any
in @code_warntype
but up as a yellow Union..
which is great. It seems like the βfourthβ type breaks type stability?
How would I go about removing this kind of type instability, can anyone point to an example?
Kind regards