Skip to content

Commit 02af65f

Browse files
committed
type stability
1 parent 87b514f commit 02af65f

File tree

2 files changed

+23
-8
lines changed

2 files changed

+23
-8
lines changed

base/abstractarray.jl

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2611,15 +2611,20 @@ end
26112611

26122612
function _vstack_plus(itr)
26132613
z = iterate(itr)
2614-
isnothing(z) && throw(ArgumentError("cannot stack an empty collection"))
2614+
z === nothing && throw(ArgumentError("cannot stack an empty collection"))
26152615
val, state = z
26162616
val isa Union{AbstractArray, Tuple} || throw(ArgumentError("cannot stack elements of type $(typeof(val))"))
26172617

26182618
axe = axes(val)
26192619
len = length(val)
26202620
n = haslength(itr) ? len*length(itr) : nothing
26212621

2622-
v = similar(val isa Tuple ? (1:0) : val, eltype(val), something(n, len))
2622+
v = if val isa Tuple
2623+
T = mapreduce(typeof, promote_type, val)
2624+
similar(1:0, T, something(n, len))
2625+
else
2626+
similar(val, something(n, len))
2627+
end
26232628
copyto!(v, 1, val, firstindex(val), len)
26242629

26252630
w = _stack_rest!(v, 0, n, axe, itr, state)
@@ -2630,12 +2635,16 @@ function _stack_rest!(v::AbstractVector, i, n, axe, itr, state)
26302635
len = prod(length, axe; init=1)
26312636
while true
26322637
z = iterate(itr, state)
2633-
isnothing(z) && return v
2638+
z === nothing && return v
26342639
val, state = z
26352640
axes(val) == axe || throw(DimensionMismatch(
26362641
"expected a consistent size, got axes $(UnitRange.(axes(val))) compared to $(UnitRange.(axe)) for the first"))
26372642
i += 1
2638-
T′ = promote_type(eltype(v), eltype(val))
2643+
T′ = if val isa Tuple
2644+
promote_type(eltype(v), mapreduce(typeof, promote_type, val))
2645+
else
2646+
promote_type(eltype(v), eltype(val))
2647+
end
26392648
if T′ <: eltype(v)
26402649
if n isa Integer
26412650
copyto!(v, i*len+1, val, firstindex(val), len)

test/abstractarray.jl

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1565,6 +1565,11 @@ end
15651565
X3 = stack(x for x in args if true)
15661566
@test X3 == Y
15671567
@test typeof(X3) === typeof(Y)
1568+
1569+
if isconcretetype(eltype(args))
1570+
@inferred stack(args)
1571+
@inferred stack(x for x in args)
1572+
end
15681573
end
15691574
# Higher dims
15701575
@test size(stack([rand(2,3) for _ in 1:4, _ in 1:5])) == (2,3,4,5)
@@ -1574,12 +1579,13 @@ end
15741579
# Tuples
15751580
@test stack([(1,2), (3,4)]) == [1 3; 2 4]
15761581
@test stack(((1,2), (3,4))) == [1 3; 2 4]
1577-
@test size(stack(Iterators.product(1:3, 1:4))) == (2,3,4)
1578-
@test stack([('a', 'b'), ('c', 'd')]) == ['a' 'c'; 'b' 'd']
1582+
@test size(@inferred stack(Iterators.product(1:3, 1:4))) == (2,3,4)
1583+
@test @inferred(stack([('a', 'b'), ('c', 'd')])) == ['a' 'c'; 'b' 'd']
1584+
@test @inferred(stack([(1,2+3im), (4, 5+6im)])) isa Matrix{Complex{Int}}
15791585

15801586
# stack(f, iter)
1581-
@test stack(x -> [x, 2x], 3:5) == [3 4 5; 6 8 10]
1582-
@test stack(x -> x*x'/2, [1:2, 3:4]) == [0.5 1.0; 1.0 2.0;;; 4.5 6.0; 6.0 8.0]
1587+
@test @inferred(stack(x -> [x, 2x], 3:5)) == [3 4 5; 6 8 10]
1588+
@test @inferred(stack(x -> x*x'/2, [1:2, 3:4])) == [0.5 1.0; 1.0 2.0;;; 4.5 6.0; 6.0 8.0]
15831589

15841590
# Mismatched sizes
15851591
@test_throws DimensionMismatch stack([1:2, 1:3])

0 commit comments

Comments
 (0)