I’ve discovered that I may have introduced some performance-sapping code into my project because of the following issue. I have two structs A and B like this:
struct A
field1::Int
end
struct B
containedA::A
end
Later I decide to rewrite A with a parameter:
struct A{T}
field1::T
end
According to my understanding of the language, I should now also parametrize B with T, else the contained field A is an abstract type and anything that uses B will involve run-time dispatch. However, in many places in my code, I forgot to do this and am just now noticing the issue.
First, is my understanding correct? Is there a performance hit for not parameterizing B?
Second, if this is indeed the case, is there a technique to discover this problem (i.e., a technique to confirm that all fields of a struct are concrete) aside from running code_warntype and poring over the output?
macro concrete(expr)
@assert expr.head == :struct
S = expr.args[2]
return quote
$(esc(expr))
for n in fieldnames($S)
if !isconcretetype(fieldtype($S, n))
error("field $n is not concrete")
end
end
end
end
julia> @concrete struct Foo
v::Array{Int}
end
ERROR: field v is not concrete
Stacktrace:
[1] error(::String) at ./error.jl:33
[2] top-level scope at REPL[1]:9
julia> struct Bar{Int} end
julia> @concrete struct Foob
v::Bar
end
ERROR: field v is not concrete
Stacktrace:
[1] error(::String) at ./error.jl:33
[2] top-level scope at REPL[1]:9
julia> @concrete struct Foobar
v::Bar{Float64}
end