What that @_4::Union{Nothing, Tuple{Int64,Int64}} is indicating? Where is there any possible Tuple in this code? Is there anything important about this warning of type evaluation? When one runs @code_warntype that line is yellow, suggesting that it deserves some attention.
julia> function s(x)
s = 0
for val in x
s = s + val
end
s
end
s (generic function with 1 method)
julia> x = ones(Int64,3);
julia> @code_warntype s(x)
Variables
#self#::Core.Compiler.Const(s, false)
x::Array{Int64,1}
s::Int64
@_4::Union{Nothing, Tuple{Int64,Int64}} #<<<<<<<<< THIS LINE
val::Int64
Body::Int64
1 ─ (s = 0)
│ %2 = x::Array{Int64,1}
│ (@_4 = Base.iterate(%2))
│ %4 = (@_4 === nothing)::Bool
│ %5 = Base.not_int(%4)::Bool
└── goto #4 if not %5
2 ┄ %7 = @_4::Tuple{Int64,Int64}::Tuple{Int64,Int64}
│ (val = Core.getfield(%7, 1))
│ %9 = Core.getfield(%7, 2)::Int64
│ (s = s + val)
│ (@_4 = Base.iterate(%2, %9))
│ %12 = (@_4 === nothing)::Bool
│ %13 = Base.not_int(%12)::Bool
└── goto #4 if not %13
3 ─ goto #2
4 ┄ return s
julia>
The union splitting for iteration is a fundamentally fast operation that would immediately raise numerous red flags if it was a problem. You really can’t remove it, but neither do you need to for high performance.
@mbauman and @abraemer thanks for the clarification. I gave it a spin and found that using while loop actually would remove the Union. I have only tested it on this function, so I do not know if it is an lucky occurence or in general.
A note for someone trying this, I did experience that some variables in a tuple could become Any by doing this inside of the while loop. The fix for that if you have a tuple, L, then instead of doing, i = L[1], j = L[2] ..., then just i,j .. = L. Just mentioning, can’t explain why.
EDIT: I did not see any major speed up using while i.e. not having the yellow union in @code_warntype. Still the programmer in me was happy soooo…
I mean, sure, you could also program entirely with gotos if you so desired such punishment. To be clear, the iteration protocol is where these Unions come from. Any time you use iteration you’ll see this. That’s every for loop, for example. This has zero impact on performance. If you can measure a meaningful performance difference, it’s a bug.
Bending over backwards to avoid using for loops is of course possible, and yes: if you don’t iterate you won’t see this union. But there’s no real reason to do so.