Repository: JuliaLang/julia
File: base/array.jl (Julia)

Code before:
        push!(a, x)
    end
    return a
end

# make a collection similar to `c` and appropriate for collecting `itr`
_similar_for(c, ::Type{T}, itr, isz, shp) where {T} = similar(c, T)

_similar_shape(itr, ::SizeUnknown) = nothing
_similar_shape(itr, ::HasLength) = length(itr)::Integer
_similar_shape(itr, ::HasShape) = axes(itr)

_similar_for(c::AbstractArray, ::Type{T}, itr, ::SizeUnknown, ::Nothing) where {T} =
    similar(c, T, 0)
_similar_for(c::AbstractArray, ::Type{T}, itr, ::HasLength, len::Integer) where {T} =
    similar(c, T, len)
_similar_for(c::AbstractArray, ::Type{T}, itr, ::HasShape, axs) where {T} =
    similar(c, T, axs)

# make a collection appropriate for collecting `itr::Generator`
_array_for2(::Type{T}, ::SizeUnknown, ::Nothing) where {T} = Vector{T}(undef, 0)
_array_for2(::Type{T}, ::HasLength, len::Integer) where {T} = Vector{T}(undef, Int(len))
_array_for2(::Type{T}, ::HasShape{N}, axs) where {T,N} = similar(Array{T,N}, axs)

# used by syntax lowering for simple typed comprehensions
_array_for(::Type{T}, itr, isz) where {T} = _array_for2(T, isz, _similar_shape(itr, isz))


"""
    collect(iterator)

Return an `Array` of all items in a collection or iterator. For dictionaries, returns
a `Vector` of `key=>value` [Pair](@ref Pair)s. If the argument is array-like or is an iterator
with the [`HasShape`](@ref IteratorSize) trait, the result will have the same shape
and number of dimensions as the argument.

Used by [comprehensions](@ref man-comprehensions) to turn a [generator expression](@ref man-generators)
into an `Array`. Thus, *on generators*, the square-brackets notation may be used instead of calling `collect`,
see second example.

The element type of the returned array is based on the types of the values collected. However, if the
iterator is empty then the element type of the returned (empty) array is determined by type inference.

# Examples

Collect items from a `UnitRange{Int64}` collection:

```jldoctest
julia> collect(1:3)
3-element Vector{Int64}:
 1

Review comment (bug):
This is the main point of contention: JET can not rule out that this method ends up calling itself recursively, which then leads to follow-up weirdness (like it looking for a `length(::HasLength)` method, and of course failing to find one).

I am open for better names than `_array_for2` (perhaps `_array_for_inner` ?).

Code after:
        push!(a, x)
    end
    return a
end

# make a collection similar to `c` and appropriate for collecting `itr`
_similar_for(c, ::Type{T}, itr, isz, shp) where {T} = similar(c, T)

_similar_shape(itr, ::SizeUnknown) = nothing
_similar_shape(itr, ::HasLength) = length(itr)::Integer
_similar_shape(itr, ::HasShape) = axes(itr)

_similar_for(c::AbstractArray, ::Type{T}, itr, ::SizeUnknown, ::Nothing) where {T} =
    similar(c, T, 0)
_similar_for(c::AbstractArray, ::Type{T}, itr, ::HasLength, len::Integer) where {T} =
    similar(c, T, len)
_similar_for(c::AbstractArray, ::Type{T}, itr, ::HasShape, axs) where {T} =
    similar(c, T, axs)

# make a collection appropriate for collecting `itr::Generator`
_array_for_inner(::Type{T}, ::SizeUnknown, ::Nothing) where {T} = Vector{T}(undef, 0)
_array_for_inner(::Type{T}, ::HasLength, len::Integer) where {T} = Vector{T}(undef, Int(len))
_array_for_inner(::Type{T}, ::HasShape{N}, axs) where {T,N} = similar(Array{T,N}, axs)

# used by syntax lowering for simple typed comprehensions
_array_for(::Type{T}, itr, isz) where {T} = _array_for_inner(T, isz, _similar_shape(itr, isz))


"""
    collect(iterator)

Return an `Array` of all items in a collection or iterator. For dictionaries, returns
a `Vector` of `key=>value` [Pair](@ref Pair)s. If the argument is array-like or is an iterator
with the [`HasShape`](@ref IteratorSize) trait, the result will have the same shape
and number of dimensions as the argument.

Used by [comprehensions](@ref man-comprehensions) to turn a [generator expression](@ref man-generators)
into an `Array`. Thus, *on generators*, the square-brackets notation may be used instead of calling `collect`,
see second example.

The element type of the returned array is based on the types of the values collected. However, if the
iterator is empty then the element type of the returned (empty) array is determined by type inference.

# Examples

Collect items from a `UnitRange{Int64}` collection:

```jldoctest
julia> collect(1:3)
3-element Vector{Int64}:
 1