I have a function that sums over expressions calling nested functions. I noticed that the function runs rather slowly. Upon further investigation, julia seems to be unable to infer the return type of this function.
The function looks somewhat like this:
struct Foo{T}
a::T
b::Array{T,1}
end
function bar(f::Foo)
ab = axes(f.b, 1)
baz(x) = sum(x * b for b in ab)
sum(b * baz(f.a) for b in ab)
end
The call to sum
in bar
returns ::Any
, according to @warn_type
:
> f = Foo(3, [1, 2, 3])
Foo{Int64}(3, [1, 2, 3])
> @code_warntype bar(f)
Variables
#self#::Core.Compiler.Const(bar, false)
f::foo{Int64}
#2::var"#2#5"{foo{Int64},var"#baz#3"{Base.OneTo{Int64}}}
ab::Base.OneTo{Int64}
baz::var"#baz#3"{Base.OneTo{Int64}}
Body::Any
1 β %1 = Base.getproperty(f, :b)::Array{Int64,1}
β (ab = Main.axes(%1, 1))
β %3 = Main.:(var"#baz#3")::Core.Compiler.Const(var"#baz#3", false)
β %4 = Core.typeof(ab)::Core.Compiler.Const(Base.OneTo{Int64}, false)
β %5 = Core.apply_type(%3, %4)::Core.Compiler.Const(var"#baz#3"{Base.OneTo{Int64}}, false)
β (baz = %new(%5, ab))
β %7 = Main.:(var"#2#5")::Core.Compiler.Const(var"#2#5", false)
β %8 = Core.typeof(f)::Core.Compiler.Const(Foo{Int64}, false)
β %9 = Core.typeof(baz)::Core.Compiler.Const(var"#baz#3"{Base.OneTo{Int64}}, false)
β %10 = Core.apply_type(%7, %8, %9)::Core.Compiler.Const(var"#2#5"{Foo{Int64},var"#baz#3"{Base.OneTo{Int64}}}, false)
β (#2 = %new(%10, f, baz))
β %12 = #2::var"#2#5"{Foo{Int64},var"#baz#3"{Base.OneTo{Int64}}}
β %13 = Base.Generator(%12, ab)::Base.Generator{Base.OneTo{Int64},var"#2#5"{Foo{Int64},var"#baz#3"{Base.OneTo{Int64}}}}
β %14 = Main.sum(%13)::Any
βββ return %14
How can I debug this further and how can I help julia inferring this type?
I know of #15276, but I donβt believe this is applicable here. As far as I can tell, the variables from bar
βs scope are not boxed.
I also tried Cthulhu.jl
βs @descend
macro, but wasnβt able to recognize the exact point, where the information is lost.
The function is inside a module, but I observe the same behavior, when I define struct and function in the REPL.