# Failure to optimize due to type recursion

**URL:** <https://discourse.julialang.org/t/failure-to-optimize-due-to-type-recursion/108568>\
**Category:** General Usage\
**Tags:** question, inference\
**Created:** [January 9, 2024, 3:06pm UTC](https://discourse.julialang.org/t/failure-to-optimize-due-to-type-recursion/108568 "2024-01-09T15:06:47Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [January 9, 2024, 3:06pm UTC](https://discourse.julialang.org/t/failure-to-optimize-due-to-type-recursion/108568/1 "2024-01-09T15:06:48Z")

</div>

I find that it is relatively easy to get non-inferred code where the `mapfoldl` family is involved, because their implementation has so many layers. Eg a simple example is

```julia
_length(c::Real) = 1
_length(c::Tuple) = mapfoldl(_length, +, c; init = 0)
_length(c::NamedTuple) = _length(values(c))
_length(c::AbstractArray) = sum(_length, c; init = 0)

x = (a = 1, b = [2.0, 3.0], d = (4, 5f0))
@code_warntype _length(x)

using JET
@report_opt _length(x)

```

My understanding is that [#48059](https://github.com/JuliaLang/julia/pull/48059) is meant to address this, but it is currently dormant.

Am I abusing the inference engine with simple code as above? Should I do something differently, eg use generated functions for the tuples?

Just to clarify, I am looking for general advice, the above is an MWE. I routinely write code that fails inference because of deeply nested `mapXXX` functions. I am wondering if I should give that up, or do it differently.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [January 9, 2024, 3:10pm UTC](https://discourse.julialang.org/t/failure-to-optimize-due-to-type-recursion/108568/2 "2024-01-09T15:10:12Z")

</div>

Just as an example, a heavy-handed fix is in the above case is

```julia
@generated function _length(c::T) where {T<:Tuple}
    mapfoldl(i -> :(_length(c[$i])), (a, b) -> :($a + $b), 1:fieldcount(T))
end

```

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [January 9, 2024, 4:53pm UTC](https://discourse.julialang.org/t/failure-to-optimize-due-to-type-recursion/108568/3 "2024-01-09T16:53:11Z")

</div>

Yeah recursive inference is a major issue for writing performant composable code, and comes up a lot!  
Even in very simple code:

```julia
julia> f(X) = sum(X) do x
                      sum(x) do y
                              y
                      end
              end
f (generic function with 1 method)

julia> @code_warntype f([[1]])
MethodInstance for f(::Vector{Vector{Int64}})
  from f(X) @ Main REPL[1]:1
Arguments
  #self#::Core.Const(f)
  X::Vector{Vector{Int64}}
Locals
  #6::var"#6#8"
Body::Any
1 ─ (#6 = %new(Main.:(var"#6#8")))
│ %2 = #6::Core.Const(var"#6#8"())
│ %3 = Main.sum(%2, X)::Any
└── return %3

```

is the shortest example I’m aware of.

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [January 9, 2024, 4:55pm UTC](https://discourse.julialang.org/t/failure-to-optimize-due-to-type-recursion/108568/4 "2024-01-09T16:55:12Z")

</div>

@aplavin This isn’t about recursion. This is [performance of captured variables in closures · Issue #15276 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/15276).

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [January 9, 2024, 4:56pm UTC](https://discourse.julialang.org/t/failure-to-optimize-due-to-type-recursion/108568/5 "2024-01-09T16:56:31Z")

</div>

No variables are captured in these examples though.  
To make it even more clear, try

```julia
f(X) = sum(Base.Fix1(sum, identity), X)

```

same `::Any` inference.
