@_4::Union{Nothing, Tuple{Int64,Int64}} in simple iterator

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> 

1 Like

A for loop lowers to calls to iterate which returns a Tuple. It’s yellow (and not red) because it likely does not require attention.

3 Likes

Writing Iterators in Julia 0.7 describes the Union used in the iteration protocol, if you’d like to learn more.

3 Likes

If I think it has an impact in my case, how would I go about removing the Union? Do I have to loop in a specific way?

Kind regards

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.

2 Likes

I suggest you open a new topic, post your code and explain what you think the problem is.

1 Like

@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…

Kind regards

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.

1 Like