Iβm encountering a strange type instability that I could distill to the following minimal code:
function unstable(rv,x0)
    x1=copy(x0)
    for t in 1:10
        p::Int = prod(x0[j] for j in rv; init=1)
        x1[1] = p == 1 ? 0 : 1
        x0,x1 = x1,x0
    end
    return x0
end
@code_warntype gives the following. The instability disappears if:
- If I set p=1instead of thep=prod(... )
- If I typeassert x0andx1in the assignment, i.e.x0::Vector{Int},x1::Vector{Int} = x1,x0instead ofx0,x1 = x1,x0.
Any idea or explanation?
julia> @code_warntype unstable(fill(1,10),fill(1,10))
MethodInstance for unstable(::Vector{Int64}, ::Vector{Int64})
  from unstable(rv, x0) @ Main REPL[103]:1
Arguments
  #self#::Core.Const(unstable)
  rv::Vector{Int64}
  x0@_3::Vector{Int64}
Locals
  @_4::Union{Nothing, Tuple{Int64, Int64}}
  x1::Any
  #109::var"#109#110"
  t::Int64
  p::Int64
  x0@_9::Union{}
  x0@_10::Union{}
  x0@_11::Union{}
  x0@_12::Union{Core.Box, Vector{Int64}}
  @_13::Int64
Body::Any
1 ββ       (x0@_12 = x0@_3)
β          (x0@_12 = Core.Box(x0@_12::Vector{Int64}))
β          Core.NewvarNode(:(@_4))
β          Core.NewvarNode(:(x1))
β    %5  = Core.isdefined(x0@_12::Core.Box, :contents)::Bool
ββββ       goto #3 if not %5
2 ββ       goto #4
3 ββ       Core.NewvarNode(:(x0@_9))
ββββ       x0@_9
4 ββ %10 = Core.getfield(x0@_12::Core.Box, :contents)::Any
β          (x1 = Main.copy(%10))
β    %12 = (1:10)::Core.Const(1:10)
β          (@_4 = Base.iterate(%12))
β    %14 = (@_4::Core.Const((1, 1)) === nothing)::Core.Const(false)
β    %15 = Base.not_int(%14)::Core.Const(true)
ββββ       goto #13 if not %15
5 ββ %17 = @_4::Tuple{Int64, Int64}
β          (t = Core.getfield(%17, 1))
β    %19 = Core.getfield(%17, 2)::Int64
β          (#109 = %new(Main.:(var"#109#110"), x0@_12::Core.Box))
β    %21 = #109::var"#109#110"
β    %22 = Base.Generator(%21, rv)::Base.Generator{Vector{Int64}, var"#109#110"}
β    %23 = (:init,)::Core.Const((:init,))
β    %24 = Core.apply_type(Core.NamedTuple, %23)::Core.Const(NamedTuple{(:init,)})
β    %25 = Core.tuple(1)::Core.Const((1,))
β    %26 = (%24)(%25)::Core.Const((init = 1,))
β    %27 = Core.kwcall(%26, Main.prod, %22)::Any
β    %28 = Base.convert(Main.Int, %27)::Any
β          (p = Core.typeassert(%28, Main.Int))
β    %30 = (p == 1)::Bool
ββββ       goto #7 if not %30
6 ββ       (@_13 = 0)
ββββ       goto #8
7 ββ       (@_13 = 1)
8 ββ %35 = @_13::Int64
β          Base.setindex!(x1, %35, 1)
β    %37 = x1::Any
β    %38 = Core.isdefined(x0@_12::Core.Box, :contents)::Bool
ββββ       goto #10 if not %38
9 ββ       goto #11
10 β       Core.NewvarNode(:(x0@_10))
ββββ       x0@_10
11 β %43 = Core.getfield(x0@_12::Core.Box, :contents)::Any
β          Core.setfield!(x0@_12::Core.Box, :contents, %37)
β          (x1 = %43)
β          (@_4 = Base.iterate(%12, %19))
β    %47 = (@_4 === nothing)::Bool
β    %48 = Base.not_int(%47)::Bool
ββββ       goto #13 if not %48
12 β       goto #5
13 β %51 = Core.isdefined(x0@_12::Core.Box, :contents)::Bool
ββββ       goto #15 if not %51
14 β       goto #16
15 β       Core.NewvarNode(:(x0@_11))
ββββ       x0@_11
16 β %56 = Core.getfield(x0@_12::Core.Box, :contents)::Any
ββββ       return %56