Skip to content

Commit

Permalink
Reduce number of getindex(::Type, ...) methods (#44127)
Browse files Browse the repository at this point in the history
Previously, there were special cases for `T[]`, `T[a]`, `T[a,b]` and
`T[a,b,c]`. Together with the general case for more elements, that meant
five methods to consider in cases like `T[x...]` where the length of `x`
was not known at compile time. That was beyond the inference limit and
such a call would be inferred as `Any`. So this change gets rid of all
the special cases.

The loop-based general case worked well if all arguments were of the
same type, but otherwise suffered from type-instability inside the loop.
Without the special cases for low element count this would be hit more
often, so for the non-homogeneous case, the loop is replaced with a call
to `afoldl` that basically unrolls the loop for up to 32 elements.
  • Loading branch information
martinholters committed Feb 18, 2022
1 parent 1ad2396 commit b8e5d7e
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 8 deletions.
17 changes: 10 additions & 7 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -402,17 +402,20 @@ julia> getindex(Int8, 1, 2, 3)
"""
function getindex(::Type{T}, vals...) where T
a = Vector{T}(undef, length(vals))
@inbounds for i = 1:length(vals)
a[i] = vals[i]
if vals isa NTuple
@inbounds for i in 1:length(vals)
a[i] = vals[i]
end
else
# use afoldl to avoid type instability inside loop
afoldl(1, vals...) do i, v
@inbounds a[i] = v
return i + 1
end
end
return a
end

getindex(::Type{T}) where {T} = (@inline; Vector{T}())
getindex(::Type{T}, x) where {T} = (@inline; a = Vector{T}(undef, 1); @inbounds a[1] = x; a)
getindex(::Type{T}, x, y) where {T} = (@inline; a = Vector{T}(undef, 2); @inbounds (a[1] = x; a[2] = y); a)
getindex(::Type{T}, x, y, z) where {T} = (@inline; a = Vector{T}(undef, 3); @inbounds (a[1] = x; a[2] = y; a[3] = z); a)

function getindex(::Type{Any}, @nospecialize vals...)
a = Vector{Any}(undef, length(vals))
@inbounds for i = 1:length(vals)
Expand Down
4 changes: 3 additions & 1 deletion test/arrayops.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2318,10 +2318,12 @@ let A = zeros(Int, 2, 2), B = zeros(Float64, 2, 2)
f40() = Float64[A A]
f41() = [A B]
f42() = Int[A B]
f43() = Int[A...]
f44() = Float64[A..., B...]

for f in [f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16,
f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28, f29, f30,
f31, f32, f33, f34, f35, f36, f37, f38, f39, f40, f41, f42]
f31, f32, f33, f34, f35, f36, f37, f38, f39, f40, f41, f42, f43, f44]
@test isconcretetype(Base.return_types(f, ())[1])
end
end
Expand Down

0 comments on commit b8e5d7e

Please sign in to comment.