I have a case where code_warntype shows a function returning a difference concrete type from what it actually returns. Here is the code:
abstract type AbstractFoo end
mutable struct FooBase <: AbstractFoo
a::Int
# no foo_inner: terminates any recursion
end
mutable struct Foo1 <: AbstractFoo
foo_inner::FooBase
function Foo1()
return new(FooBase(1))
end
end
mutable struct Foo2 <: AbstractFoo
foo_inner::Foo1
function Foo2()
return new(Foo1())
end
end
mutable struct Foo3 <: AbstractFoo
foo_inner::Foo2
function Foo3()
return new(Foo2())
end
end
mutable struct Foo4 <: AbstractFoo
foo_inner::Foo3
function Foo4()
return new(Foo3())
end
end
# T1 <: T2 implies T1 == T2 as long as all T1 and T2 are concrete
function getInnerFoo(foo::T1, ::Type{T2}) where {T2 <: AbstractFoo, T1 <: T2}
return foo
end
function getInnerFoo(foo::T1, ::Type{T2}) where {T1 <: AbstractFoo, T2 <: AbstractFoo}
return getInnerFoo(foo.foo_inner, T2)
end
obj = Foo4()
obj2 = getInnerFoo(obj, Foo2)
println("typeof(obj2) = ", typeof(obj2))
@code_warntype getInnerFoo(obj, Foo2)
On Julia 0.6.2, the output is:
typeof(obj2) = Foo2
Variables:
#self# <optimized out>
foo::Foo4
#unused# <optimized out>
Body:
begin
return foo::Foo4
end::Foo4
Variables:
#self# <optimized out>
foo::Foo4
#unused# <optimized out>
Body:
begin
return (Main.getInnerFoo)((Core.getfield)(foo::Foo4, :foo_inner)::Foo3, $(Expr(:static_parameter, 2)))::Foo3
end::Foo3
The typeof
line shows the runtime type of obj2
is Foo2
, but the final line of the output of code_warntype
shows it returning Foo3
(if I am interpreting the output correctly). I get similar results on Julia 1.0.1
My understanding is inference can return a union or abstract type, but should not return a concrete type that is incorrect. Is this a bug?