@code_warntype does not warn about Array{Any}

Shouldn’t @code_warntype flag (in red) the fact that the return value of this function is an array of Any? The macro notes the Any, but does not make it red.

struct T
    x::Int32
    y::Int32
end

function test_warntype()
    x = []
    for i in 1:2
       push!(x, T(i,i))
    end
    return x
end

julia> @code_warntype test_warntype()
Variables
  #self#::Core.Compiler.Const(test_warntype, false)
  x::Array{Any,1}
  @_3::Union{Nothing, Tuple{Int64,Int64}}
  i::Int64

Body::Array{Any,1}
1 ─       (x = Base.vect())
│   %2  = (1:2)::Core.Compiler.Const(1:2, false)
│         (@_3 = Base.iterate(%2))
│   %4  = (@_3::Core.Compiler.Const((1, 1), false) === nothing)::Core.Compiler.Const(false, false)
│   %5  = Base.not_int(%4)::Core.Compiler.Const(true, false)
└──       goto #4 if not %5
2 ┄ %7  = @_3::Tuple{Int64,Int64}::Tuple{Int64,Int64}
│         (i = Core.getfield(%7, 1))
│   %9  = Core.getfield(%7, 2)::Int64
│   %10 = x::Array{Any,1} # it is Any but is green ??
│   %11 = Main.T(i, i)::T
│         Main.push!(%10, %11)
│         (@_3 = Base.iterate(%2, %9))
│   %14 = (@_3 === nothing)::Bool
│   %15 = Base.not_int(%14)::Bool
└──       goto #4 if not %15
3 ─       goto #2
4 ┄       return x


(the example reproduces a common mistake of not initializing the array as T[]).

The function is type stable and the return type is correctly inferred to Vector{Any}, so why should it warn?

5 Likes

I am not sure, that is why I am asking. In this particular case putting a red flag on that Any would allow the identification of a common mistake which is simple to address, with important performance implications.

Perhaps the question should be if any Any should be highlighted somehow? For example in the minimal, but artificial example,

julia> function f()
          x = Any[1,2,3]
       end
f (generic function with 1 method)

julia> @code_warntype f()
Variables
  #self#::Core.Compiler.Const(f, false)
  x::Array{Any,1}

Body::Array{Any,1}
1 ─ %1 = Base.getindex(Main.Any, 1, 2, 3)::Array{Any,1}
│        (x = %1)
└──      return %1


It wouldn’t harm if the Any were yellow, or purple…

2 Likes

The problem is that cases where the user is explicitly asking for Array{Any,1} (like both examples you posted) and cases where inference says “ok, this is the best I can do” have to be distinguished. It’s perfectly valid to have x = [], if you already know beforehand that you’ll push large amounts of differently typed objects into that array. If those intended uses were all marked red, it would add to the noise.

2 Likes

I agree. Maybe bold, at least :slight_smile: - I don’t know which is the color palete available. We already get harmless Union{...,nothing} in for loops in yellow (true is that causes confusion to new people).

Maybe even for experienced users, having all the non-concrete types highlighted somehow will not be bad.

1 Like

That’s the point, though-- Array{Any} is a concrete type. If there is a type instability later on, it will come when a user tries to access an element of that array, which @code_warntype will correctly warn about already:

julia> function f()
         x = []
         push!(x, 1)
         push!(x, 2)
         return x[2]
       end
f (generic function with 1 method)

julia> @code_warntype f()
Variables
  #self#::Core.Compiler.Const(f, false)
  x::Array{Any,1}

Body::Any
1 ─      (x = Base.vect())
│        Main.push!(x, 1)
│        Main.push!(x, 2)
│   %4 = Base.getindex(x, 2)::Any
└──      return %4

julia> 

x is correctly marked as Array{Any} and not highlighted because it is a concrete type and is in fact exactly what the user asked for. But return x[2] cannot be inferred, so it is marked as Any and highlighted in red.

6 Likes

Ah, I see. We didn’t do nothing with those Any elements except containing them. Probably if that is a problem later in the code the type instability would be detected somewhere else.

Thus, reformulating the question. Isn’t a good idea to somewhat highlight (even if moderately) containers of mixed or abstract types?

I think this would be a good place to use yellow (or a new color purple?) highlighting. This is a really common new user trap, so making it more visible would be good.

2 Likes

I think Unions are marked in yellow. Similar to this, explicitly wished-for unperformant types could also be marked in yellow. Don’t know if the benefits from having this warning would outweigh the visual noise but it could very well be.

1 Like

I think that the main problem is that new users may not be aware that by using [] or similar, they are explicitly asking for Any[].

If this was Julia pre-1.0, I would suggest disallowing [] (ie forcing users to use Any[]), and it is maybe something to consider for 2.0, but given the current situation highlighting could be a mitigation.

4 Likes

I tried something like that pre-1.0: JuliaLang/julia#24974, JuliaLang/julia#25032.

5 Likes

In retrospect I think these were dismissed a bit too hastily. Generally, if an argument has a default (here, types defaulting to Any), it should ideally be the most frequently used value, not the least common. But given that it was discussed I am hesitant to open an issue about it.

In any case, I think that cases of relying on these (eg []) is a good candidate for being highlighted by a linter and/or discouraged in coding style guides. My impression is that neither BlueStyle nor YASGuide mention it.

4 Likes