Skip to content

Commit df28bf7

Browse files
authored
use afoldl instead of tail recursion for tuples (#53665)
It is easy to accidentally call these functions (they are used by vcat, which is syntax) with very long lists of values, causing inference to crash and take a long time. The `afoldl` function can handle that very well however, while naive recursion did not. Fixes #53585
1 parent 2a72d65 commit df28bf7

File tree

3 files changed

+17
-5
lines changed

3 files changed

+17
-5
lines changed

base/abstractarray.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,13 +1650,15 @@ eltypeof(x::AbstractArray) = eltype(x)
16501650

16511651
promote_eltypeof() = error()
16521652
promote_eltypeof(v1) = eltypeof(v1)
1653-
promote_eltypeof(v1, vs...) = promote_type(eltypeof(v1), promote_eltypeof(vs...))
1653+
promote_eltypeof(v1, v2) = promote_type(eltypeof(v1), eltypeof(v2))
1654+
promote_eltypeof(v1, v2, vs...) = (@inline; afoldl(((::Type{T}, y) where {T}) -> promote_type(T, eltypeof(y)), promote_eltypeof(v1, v2), vs...))
16541655
promote_eltypeof(v1::T, vs::T...) where {T} = eltypeof(v1)
16551656
promote_eltypeof(v1::AbstractArray{T}, vs::AbstractArray{T}...) where {T} = T
16561657

16571658
promote_eltype() = error()
16581659
promote_eltype(v1) = eltype(v1)
1659-
promote_eltype(v1, vs...) = promote_type(eltype(v1), promote_eltype(vs...))
1660+
promote_eltype(v1, v2) = promote_type(eltype(v1), eltype(v2))
1661+
promote_eltype(v1, v2, vs...) = (@inline; afoldl(((::Type{T}, y) where {T}) -> promote_type(T, eltype(y)), promote_eltype(v1, v2), vs...))
16601662
promote_eltype(v1::T, vs::T...) where {T} = eltype(T)
16611663
promote_eltype(v1::AbstractArray{T}, vs::AbstractArray{T}...) where {T} = T
16621664

base/promotion.jl

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ Number
1919
"""
2020
typejoin() = Bottom
2121
typejoin(@nospecialize(t)) = (@_nospecializeinfer_meta; t)
22-
typejoin(@nospecialize(t), ts...) = (@_foldable_meta; @_nospecializeinfer_meta; typejoin(t, typejoin(ts...)))
22+
typejoin(@nospecialize(t), @nospecialize(s), @nospecialize(u)) = (@_foldable_meta; @_nospecializeinfer_meta; typejoin(typejoin(t, s), u))
23+
typejoin(@nospecialize(t), @nospecialize(s), @nospecialize(u), ts...) = (@_foldable_meta; @_nospecializeinfer_meta; afoldl(typejoin, typejoin(t, s, u), ts...))
2324
function typejoin(@nospecialize(a), @nospecialize(b))
2425
@_foldable_meta
2526
@_nospecializeinfer_meta
@@ -299,7 +300,8 @@ function promote_type end
299300

300301
promote_type() = Bottom
301302
promote_type(T) = T
302-
promote_type(T, S, U, V...) = (@inline; promote_type(T, promote_type(S, U, V...)))
303+
promote_type(T, S, U) = (@inline; promote_type(promote_type(T, S), U))
304+
promote_type(T, S, U, V...) = (@inline; afoldl(promote_type, promote_type(T, S, U), V...))
303305

304306
promote_type(::Type{Bottom}, ::Type{Bottom}) = Bottom
305307
promote_type(::Type{T}, ::Type{T}) where {T} = T
@@ -373,7 +375,9 @@ function _promote(x::T, y::S) where {T,S}
373375
return (convert(R, x), convert(R, y))
374376
end
375377
promote_typeof(x) = typeof(x)
376-
promote_typeof(x, xs...) = (@inline; promote_type(typeof(x), promote_typeof(xs...)))
378+
promote_typeof(x, y) = (@inline; promote_type(typeof(x), typeof(y)))
379+
promote_typeof(x, y, z) = (@inline; promote_type(typeof(x), typeof(y), typeof(z)))
380+
promote_typeof(x, y, z, a...) = (@inline; afoldl(((::Type{T}, y) where {T}) -> promote_type(T, typeof(y)), promote_typeof(x, y, z), a...))
377381
function _promote(x, y, z)
378382
@inline
379383
R = promote_typeof(x, y, z)

test/compiler/inference.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5639,3 +5639,9 @@ end
56395639
@test issue53590(true, false) == Real
56405640
@test issue53590(false, false) == Float64
56415641
@test issue53590(false, true) == Real
5642+
5643+
# issue #53585
5644+
let t = ntuple(i -> i % 8 == 1 ? Int64 : Float64, 4000)
5645+
@test only(Base.return_types(Base.promote_typeof, t)) == Type{Float64}
5646+
@test only(Base.return_types(vcat, t)) == Vector{Float64}
5647+
end

0 commit comments

Comments
 (0)