We usually speak of type stability for functions and we also have the tools to determine that (like @code_warntype).
But say I would like to check whether a struct is type-stable, in the sense that it is well defined and no field is of an abstract type.
For the small structs it is trivial, but for long composite nested structs it is quite hard to inspect it manually.
Is there a tool to handle this automatically ?
Not sure what exactly mean with fields being “well defined” (they always are), but this should do what you’re looking for:
julia> allconcrete(x::T) where T = all(isconcretetype, fieldtypes(T))
allconcrete (generic function with 1 method)
julia> allconcrete(a1)
false
julia> allconcrete(a2)
true
Note that this works through reflection via fieldtypes.
“type stable” as a term only makes sense in the context of a function using an object, since type stability only refers to some function whose return type depends on the value of its arguments instead of its types. It’s true that abstractly typed fields can lead to type instabilities in functions using that type, but I’m not sure we should refer to structs with non-concretely typed fields as “type unstable”. There are valid reasons for having a field typed as e.g. Any - for example when the field can take on a diverse number of types and specializing on it would not help (or even hinder) performance.
I understand that there can be the case that a parameter type might not be linked to a specific field, and thus there will be no negative impact in performance for abstract types.
e.g.:
In these cases, the parameter is mostly used for specialization.
Maybe it’s useful to translate the problem in the function domain.
E.g. I could write something like this, in order to recursively evaluate all fields from the struct:
@inline function teststab(a::R) where R
if isprimitivetype(R)
return a
else
for x in getfield.([a], fieldnames(R))
testalpha(x)
end
end
end
The problem is that the compiler inside the for loop doesn’t specialize on the type of each field x although it should be statically retrievable.
Any ideas how to proceed ?