Strange type-inference

Hey,

While trying to optimize some code, I ran into some strangely inferred types. The actual example behaves slightly different, but the following excerpt is equally strange.

abstract type Node end

mutable struct JobNode <: Node
    parent::Node
    theta::Vector{Float64}
end

mutable struct RootNode <: Node
    theta::Vector{Float64}
end

theta(node::Union{RootNode, JobNode}) = node.theta

Calling Base.return_types(theta, (Node,)) gives me Union{Array{Float64,1}, Node}
Can anyone explain this? In my actual code, it returns Any. Is there a better way to do this kind of thing? code_warntype also leads to the same result.

Thanks

Sure, it didn’t propagate the :theta constant into the field access, but it was able to figure out that any field access into an object that’s a subtype of Node, would return Union{Array{Float64,1}, Node}, because that’s the supertype of any field in any subtype of Union{RootNode, JobNode}. In general constant propagation doesn’t happen if there is more than one applicable method, though maybe it should be adjusted in this case to be more aggressive.

3 Likes