Skip to content

Commit

Permalink
use afoldl instead of tail recursion for tuples
Browse files Browse the repository at this point in the history
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
  • Loading branch information
vtjnash committed Mar 8, 2024
1 parent e618369 commit a85fc89
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 5 deletions.
4 changes: 2 additions & 2 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1649,13 +1649,13 @@ eltypeof(x::AbstractArray) = eltype(x)

promote_eltypeof() = error()
promote_eltypeof(v1) = eltypeof(v1)
promote_eltypeof(v1, vs...) = promote_type(eltypeof(v1), promote_eltypeof(vs...))
promote_eltypeof(v1, vs...) = (@inline; afoldl(((::Type{T}, y) where {T}) -> promote_type(T, eltypeof(y)), eltypeof(v1), vs...))
promote_eltypeof(v1::T, vs::T...) where {T} = eltypeof(v1)
promote_eltypeof(v1::AbstractArray{T}, vs::AbstractArray{T}...) where {T} = T

promote_eltype() = error()
promote_eltype(v1) = eltype(v1)
promote_eltype(v1, vs...) = promote_type(eltype(v1), promote_eltype(vs...))
promote_eltype(v1, vs...) = (@inline; afoldl(((::Type{T}, y) where {T}) -> promote_type(T, eltype(y)), eltype(v1), vs...))
promote_eltype(v1::T, vs::T...) where {T} = eltype(T)
promote_eltype(v1::AbstractArray{T}, vs::AbstractArray{T}...) where {T} = T

Expand Down
6 changes: 3 additions & 3 deletions base/promotion.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Number
"""
typejoin() = Bottom
typejoin(@nospecialize(t)) = (@_nospecializeinfer_meta; t)
typejoin(@nospecialize(t), ts...) = (@_foldable_meta; @_nospecializeinfer_meta; typejoin(t, typejoin(ts...)))
typejoin(@nospecialize(t), ts...) = (@_foldable_meta; @_nospecializeinfer_meta; afoldl(typejoin, t, ts...))
function typejoin(@nospecialize(a), @nospecialize(b))
@_foldable_meta
@_nospecializeinfer_meta
Expand Down Expand Up @@ -299,7 +299,7 @@ function promote_type end

promote_type() = Bottom
promote_type(T) = T
promote_type(T, S, U, V...) = (@inline; promote_type(T, promote_type(S, U, V...)))
promote_type(T, S, U, V...) = (@inline; promote_type(T, promote_type(S, afoldl(promote_type, U, V...))))

promote_type(::Type{Bottom}, ::Type{Bottom}) = Bottom
promote_type(::Type{T}, ::Type{T}) where {T} = T
Expand Down Expand Up @@ -373,7 +373,7 @@ function _promote(x::T, y::S) where {T,S}
return (convert(R, x), convert(R, y))
end
promote_typeof(x) = typeof(x)
promote_typeof(x, xs...) = (@inline; promote_type(typeof(x), promote_typeof(xs...)))
promote_typeof(x, xs...) = (@inline; afoldl(((::Type{T}, y) where {T}) -> promote_type(T, typeof(y)), typeof(x), xs...))
function _promote(x, y, z)
@inline
R = promote_typeof(x, y, z)
Expand Down
6 changes: 6 additions & 0 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5639,3 +5639,9 @@ end
@test issue53590(true, false) == Real
@test issue53590(false, false) == Float64
@test issue53590(false, true) == Real

# issue #53585
let t = ntuple(i -> i % 8 == 1 ? Int64 : Float64, 4000)
@test only(Base.return_types(Base.promote_typeof, t)) == Type{Float64}
@test only(Base.return_types(vcat, t)) == Vector{Float64}
end

0 comments on commit a85fc89

Please sign in to comment.