From d487b1d3f41c5530b030d96db226ef91d9d6d312 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Fri, 21 Dec 2018 22:12:22 +0100 Subject: [PATCH 01/12] Make return type of broadcast inferrable with heterogeneous arrays Inference is not able to detect the element type automatically, but we can do it manually since we know promote_typejoin is used for widening. --- base/broadcast.jl | 33 +++++++++++++++++++++++++++++++-- test/broadcast.jl | 22 +++++++++++++++++++++- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index fb9c5948af4e6..4c098eaa69686 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -691,8 +691,31 @@ eltypes(t::Tuple{Any}) = Tuple{_broadcast_getindex_eltype(t[1])} eltypes(t::Tuple{Any,Any}) = Tuple{_broadcast_getindex_eltype(t[1]), _broadcast_getindex_eltype(t[2])} eltypes(t::Tuple) = Tuple{_broadcast_getindex_eltype(t[1]), eltypes(tail(t)).types...} +Base.@pure function promote_typejoin_union(::Type{T}) where T + if T isa Union + promote_typejoin(promote_typejoin_union(T.a), promote_typejoin_union(T.b)) + elseif T <: Tuple + p = T.parameters + lr = length(p)::Int + if lr == 0 + return Tuple{} + end + lf, fixed = Core.Compiler.full_va_len(p) + c = Vector{Any}(undef, lf) + for i = 1:lf + pi = p[i] + ci = promote_typejoin_union(Core.Compiler.unwrapva(pi)) + c[i] = i == lf && Core.Compiler.isvarargtype(pi) ? Vararg{ci} : ci + end + return Tuple{c...} + else + T + end +end + # Inferred eltype of result of broadcast(f, args...) -combine_eltypes(f, args::Tuple) = Base._return_type(f, eltypes(args)) +combine_eltypes(f, args::Tuple) = + promote_typejoin_union(Base._return_type(f, eltypes(args))) ## Broadcasting core @@ -877,7 +900,13 @@ const NonleafHandlingStyles = Union{DefaultArrayStyle,ArrayConflict} dest = similar(bc′, typeof(val)) @inbounds dest[I] = val # Now handle the remaining values - return copyto_nonleaf!(dest, bc′, iter, state, 1) + if dest isa AbstractArray + # Give inference a helping hand on the element type and dimensionality + # (work-around for #28382) + return copyto_nonleaf!(dest, bc′, iter, state, 1)::AbstractArray{<:ElType, ndims(dest)} + else + return copyto_nonleaf!(dest, bc′, iter, state, 1) + end end ## general `copyto!` methods diff --git a/test/broadcast.jl b/test/broadcast.jl index 628003d4b47c5..507e3f5c5f5ff 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -365,7 +365,7 @@ end let f17314 = x -> x < 0 ? false : x @test eltype(broadcast(f17314, 1:3)) === Int @test eltype(broadcast(f17314, -1:1)) === Integer - @test eltype(broadcast(f17314, Int[])) == Union{Bool,Int} + @test eltype(broadcast(f17314, Int[])) === Integer end let io = IOBuffer() broadcast(x->print(io,x), 1:5) # broadcast with side effects @@ -934,3 +934,23 @@ ret = @macroexpand @.([Int, Number] <: Real) ret = @macroexpand @.([Int, Number] >: Real) @test ret == :([Int, Number] .>: Real) + +@testset "Issue #28382: inferrability of broadcast with Union eltype" begin + @test isequal([1, 2] .+ [3.0, missing], [4.0, missing]) + @test Core.Compiler.return_type(broadcast, Tuple{typeof(+), Vector{Int}, + Vector{Union{Float64, Missing}}}) == + Vector{<:Union{Float64, Missing}} + @test isequal([1, 2] + [3.0, missing], [4.0, missing]) + @test Core.Compiler.return_type(+, Tuple{Vector{Int}, + Vector{Union{Float64, Missing}}}) == + Vector{<:Union{Float64, Missing}} + # Check that corner cases do not throw an error + @test isequal(broadcast(x -> x === 1 ? nothing : x, [1, 2, missing]), + [nothing, 2, missing]) + @test isequal(broadcast(x -> x === 1 ? nothing : x, Any[1, 2, 3.0, missing]), + [nothing, 2, 3, missing]) + @test broadcast((x,y)->(x==1 ? 1.0 : x, y), [1 2 3], ["a", "b", "c"]) == + [(1.0, "a") (2, "a") (3, "a") + (1.0, "b") (2, "b") (3, "b") + (1.0, "c") (2, "c") (3, "c")] +end \ No newline at end of file From 3f1a1f1951a47e2611ef34f89a05705a0f86fda3 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Wed, 2 Jan 2019 19:56:06 +0100 Subject: [PATCH 02/12] Add var and std --- base/broadcast.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index 4c098eaa69686..4db2210e52836 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -692,7 +692,9 @@ eltypes(t::Tuple{Any,Any}) = Tuple{_broadcast_getindex_eltype(t[1]), _broadcast_ eltypes(t::Tuple) = Tuple{_broadcast_getindex_eltype(t[1]), eltypes(tail(t)).types...} Base.@pure function promote_typejoin_union(::Type{T}) where T - if T isa Union + if T === Union{} + return Union{} + elseif T isa Union promote_typejoin(promote_typejoin_union(T.a), promote_typejoin_union(T.b)) elseif T <: Tuple p = T.parameters From 8a1e65f11b4ffda70358ef8e4cac8fc95f3c6895 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Tue, 5 Feb 2019 09:56:20 +0100 Subject: [PATCH 03/12] Don't use @pure --- base/broadcast.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index 4db2210e52836..2cfe1d71aecb1 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -691,7 +691,7 @@ eltypes(t::Tuple{Any}) = Tuple{_broadcast_getindex_eltype(t[1])} eltypes(t::Tuple{Any,Any}) = Tuple{_broadcast_getindex_eltype(t[1]), _broadcast_getindex_eltype(t[2])} eltypes(t::Tuple) = Tuple{_broadcast_getindex_eltype(t[1]), eltypes(tail(t)).types...} -Base.@pure function promote_typejoin_union(::Type{T}) where T +function promote_typejoin_union(::Type{T}) where T if T === Union{} return Union{} elseif T isa Union From 999f17fe0fe3f9f5be1d6b0bb96bbc7e654a33b5 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Tue, 5 Feb 2019 11:49:39 +0100 Subject: [PATCH 04/12] Stop using @pure with promote_typejoin --- base/broadcast.jl | 41 ++++++++++++++++++++++++++--------------- test/broadcast.jl | 4 ++++ 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index 2cfe1d71aecb1..45f513a02e2df 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -8,7 +8,7 @@ Module containing the broadcasting implementation. module Broadcast using .Base.Cartesian -using .Base: Indices, OneTo, tail, to_shape, isoperator, promote_typejoin, +using .Base: Indices, OneTo, tail, to_shape, isoperator, promote_typejoin, @pure, _msk_end, unsafe_bitgetindex, bitcache_chunks, bitcache_size, dumpbitcache, unalias import .Base: copy, copyto!, axes export broadcast, broadcast!, BroadcastStyle, broadcast_axes, broadcastable, dotview, @__dot__, broadcast_preserving_zero_d @@ -137,7 +137,7 @@ BroadcastStyle(a::AbstractArrayStyle, ::Style{Tuple}) = a BroadcastStyle(::A, ::A) where A<:ArrayStyle = A() BroadcastStyle(::ArrayStyle, ::ArrayStyle) = Unknown() BroadcastStyle(::A, ::A) where A<:AbstractArrayStyle = A() -Base.@pure function BroadcastStyle(a::A, b::B) where {A<:AbstractArrayStyle{M},B<:AbstractArrayStyle{N}} where {M,N} +@pure function BroadcastStyle(a::A, b::B) where {A<:AbstractArrayStyle{M},B<:AbstractArrayStyle{N}} where {M,N} if Base.typename(A) === Base.typename(B) return A(Val(max(M, N))) end @@ -697,24 +697,35 @@ function promote_typejoin_union(::Type{T}) where T elseif T isa Union promote_typejoin(promote_typejoin_union(T.a), promote_typejoin_union(T.b)) elseif T <: Tuple - p = T.parameters - lr = length(p)::Int - if lr == 0 - return Tuple{} - end - lf, fixed = Core.Compiler.full_va_len(p) - c = Vector{Any}(undef, lf) - for i = 1:lf - pi = p[i] - ci = promote_typejoin_union(Core.Compiler.unwrapva(pi)) - c[i] = i == lf && Core.Compiler.isvarargtype(pi) ? Vararg{ci} : ci - end - return Tuple{c...} + typejoin_union_tuple(T) else T end end +@pure function typejoin_union_tuple(::Type{T}) where {T} + p = T.parameters + lr = length(p)::Int + if lr == 0 + return Tuple{} + end + lf, fixed = Core.Compiler.full_va_len(p) + c = Vector{Any}(undef, lf) + for i = 1:lf + pi = p[i] + U = Core.Compiler.unwrapva(pi) + if U === Union{} + ci = Union{} + elseif U isa Union + ci = typejoin(U.a, U.b) + else + ci = U + end + c[i] = i == lf && Core.Compiler.isvarargtype(pi) ? Vararg{ci} : ci + end + return Tuple{c...} +end + # Inferred eltype of result of broadcast(f, args...) combine_eltypes(f, args::Tuple) = promote_typejoin_union(Base._return_type(f, eltypes(args))) diff --git a/test/broadcast.jl b/test/broadcast.jl index 507e3f5c5f5ff..bd0eba20d5e21 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -944,6 +944,10 @@ ret = @macroexpand @.([Int, Number] >: Real) @test Core.Compiler.return_type(+, Tuple{Vector{Int}, Vector{Union{Float64, Missing}}}) == Vector{<:Union{Float64, Missing}} + @test isequal(tuple.([1, 2], [3.0, missing]), [(1, 3.0), (2, missing)]) + @test Core.Compiler.return_type(broadcast, Tuple{typeof(tuple), Vector{Int}, + Vector{Union{Float64, Missing}}}) == + Vector{<:Tuple{Int, Any}} # Check that corner cases do not throw an error @test isequal(broadcast(x -> x === 1 ? nothing : x, [1, 2, missing]), [nothing, 2, missing]) From 707e0fda92b5dc86b5c911370223ba77e3959de0 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Thu, 13 Aug 2020 11:57:23 +0200 Subject: [PATCH 05/12] Review fixes --- base/broadcast.jl | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index 45f513a02e2df..abbf5dcd2d97d 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -137,7 +137,7 @@ BroadcastStyle(a::AbstractArrayStyle, ::Style{Tuple}) = a BroadcastStyle(::A, ::A) where A<:ArrayStyle = A() BroadcastStyle(::ArrayStyle, ::ArrayStyle) = Unknown() BroadcastStyle(::A, ::A) where A<:AbstractArrayStyle = A() -@pure function BroadcastStyle(a::A, b::B) where {A<:AbstractArrayStyle{M},B<:AbstractArrayStyle{N}} where {M,N} +Base.@pure function BroadcastStyle(a::A, b::B) where {A<:AbstractArrayStyle{M},B<:AbstractArrayStyle{N}} where {M,N} if Base.typename(A) === Base.typename(B) return A(Val(max(M, N))) end @@ -695,23 +695,22 @@ function promote_typejoin_union(::Type{T}) where T if T === Union{} return Union{} elseif T isa Union - promote_typejoin(promote_typejoin_union(T.a), promote_typejoin_union(T.b)) + return promote_typejoin(promote_typejoin_union(T.a), promote_typejoin_union(T.b)) elseif T <: Tuple - typejoin_union_tuple(T) + return typejoin_union_tuple(T) else - T + return T end end @pure function typejoin_union_tuple(::Type{T}) where {T} - p = T.parameters + p = (Core.Compiler.unwrap_unionall(T)::DataType).parameters lr = length(p)::Int if lr == 0 return Tuple{} end - lf, fixed = Core.Compiler.full_va_len(p) - c = Vector{Any}(undef, lf) - for i = 1:lf + c = Vector{Any}(undef, lr) + for i = 1:lr pi = p[i] U = Core.Compiler.unwrapva(pi) if U === Union{} @@ -721,7 +720,12 @@ end else ci = U end - c[i] = i == lf && Core.Compiler.isvarargtype(pi) ? Vararg{ci} : ci + if i == lr && Core.Compiler.isvarargtype(pi) + N = (Core.Compiler.unwrap_unionall(pi)::DataType).parameters[2] + c[i] = Vararg{ci, N} + else + c[i] = ci + end end return Tuple{c...} end @@ -913,13 +917,9 @@ const NonleafHandlingStyles = Union{DefaultArrayStyle,ArrayConflict} dest = similar(bc′, typeof(val)) @inbounds dest[I] = val # Now handle the remaining values - if dest isa AbstractArray - # Give inference a helping hand on the element type and dimensionality - # (work-around for #28382) - return copyto_nonleaf!(dest, bc′, iter, state, 1)::AbstractArray{<:ElType, ndims(dest)} - else - return copyto_nonleaf!(dest, bc′, iter, state, 1) - end + # The typeassert gives inference a helping hand on the element type and dimensionality + # (work-around for #28382) + return copyto_nonleaf!(dest, bc′, iter, state, 1)::(dest isa AbstractArray ? AbstractArray{<:ElType, ndims(dest)} : Any) end ## general `copyto!` methods From 1da52df1618b9e451d597d7f537548dcdeecf1f6 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Tue, 29 Sep 2020 15:57:02 +0200 Subject: [PATCH 06/12] Fixes --- base/broadcast.jl | 10 ++++++---- test/broadcast.jl | 18 ++++++++++++++++-- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index c06e254284bd6..379ff76e7fa4b 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -703,8 +703,8 @@ function promote_typejoin_union(::Type{T}) where T end end -@pure function typejoin_union_tuple(::Type{T}) where {T} - p = (Core.Compiler.unwrap_unionall(T)::DataType).parameters +@pure function typejoin_union_tuple(T::Type) + p = (Base.unwrap_unionall(T)::DataType).parameters lr = length(p)::Int if lr == 0 return Tuple{} @@ -721,7 +721,7 @@ end ci = U end if i == lr && Core.Compiler.isvarargtype(pi) - N = (Core.Compiler.unwrap_unionall(pi)::DataType).parameters[2] + N = (Base.unwrap_unionall(pi)::DataType).parameters[2] c[i] = Vararg{ci, N} else c[i] = ci @@ -919,7 +919,9 @@ const NonleafHandlingStyles = Union{DefaultArrayStyle,ArrayConflict} # Now handle the remaining values # The typeassert gives inference a helping hand on the element type and dimensionality # (work-around for #28382) - return copyto_nonleaf!(dest, bc′, iter, state, 1)::(dest isa AbstractArray ? AbstractArray{<:ElType, ndims(dest)} : Any) + ElType′ = ElType <: Type ? DataType : ElType + RT = dest isa AbstractArray ? AbstractArray{<:ElType′, ndims(dest)} : Any + return copyto_nonleaf!(dest, bc′, iter, state, 1)::RT end ## general `copyto!` methods diff --git a/test/broadcast.jl b/test/broadcast.jl index fe919b5d80b57..8cb30a8f358ff 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -947,17 +947,29 @@ p0 = copy(p) @testset "Issue #28382: inferrability of broadcast with Union eltype" begin @test isequal([1, 2] .+ [3.0, missing], [4.0, missing]) + @test_broken Core.Compiler.return_type(broadcast, Tuple{typeof(+), Vector{Int}, + Vector{Union{Float64, Missing}}}) == + Vector{<:Union{Float64, Missing}} @test Core.Compiler.return_type(broadcast, Tuple{typeof(+), Vector{Int}, Vector{Union{Float64, Missing}}}) == - Vector{<:Union{Float64, Missing}} + AbstractVector{<:Union{Float64, Missing}} @test isequal([1, 2] + [3.0, missing], [4.0, missing]) + @test_broken Core.Compiler.return_type(+, Tuple{Vector{Int}, + Vector{Union{Float64, Missing}}}) == + Vector{<:Union{Float64, Missing}} @test Core.Compiler.return_type(+, Tuple{Vector{Int}, Vector{Union{Float64, Missing}}}) == + AbstractVector{<:Union{Float64, Missing}} + @test_broken Core.Compiler.return_type(+, Tuple{Vector{Int}, + Vector{Union{Float64, Missing}}}) == Vector{<:Union{Float64, Missing}} @test isequal(tuple.([1, 2], [3.0, missing]), [(1, 3.0), (2, missing)]) + @test_broken Core.Compiler.return_type(broadcast, Tuple{typeof(tuple), Vector{Int}, + Vector{Union{Float64, Missing}}}) == + Vector{<:Tuple{Int, Any}} @test Core.Compiler.return_type(broadcast, Tuple{typeof(tuple), Vector{Int}, Vector{Union{Float64, Missing}}}) == - Vector{<:Tuple{Int, Any}} + AbstractVector{<:Tuple{Int, Any}} # Check that corner cases do not throw an error @test isequal(broadcast(x -> x === 1 ? nothing : x, [1, 2, missing]), [nothing, 2, missing]) @@ -967,4 +979,6 @@ p0 = copy(p) [(1.0, "a") (2, "a") (3, "a") (1.0, "b") (2, "b") (3, "b") (1.0, "c") (2, "c") (3, "c")] + @test typeof.([iszero, isdigit]) == [typeof(iszero), typeof(isdigit)] + @test typeof.([iszero, iszero]) == [typeof(iszero), typeof(iszero)] end From d5767ab98678644eb944a2cdb75a5cf60b9b85eb Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Tue, 29 Sep 2020 17:16:39 +0200 Subject: [PATCH 07/12] Fix assertion --- base/broadcast.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index 379ff76e7fa4b..b072c85793f5b 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -704,7 +704,7 @@ function promote_typejoin_union(::Type{T}) where T end @pure function typejoin_union_tuple(T::Type) - p = (Base.unwrap_unionall(T)::DataType).parameters + p = (Base.unwrap_unionall(T)::Union{DataType, Union}).parameters lr = length(p)::Int if lr == 0 return Tuple{} From a59f36469d2f5577a99d7842459980053c8ccf7f Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Tue, 29 Sep 2020 18:05:25 +0200 Subject: [PATCH 08/12] Apply suggestions from code review Co-authored-by: Jameson Nash --- base/broadcast.jl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index b072c85793f5b..f676aeee0c5c3 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -704,7 +704,11 @@ function promote_typejoin_union(::Type{T}) where T end @pure function typejoin_union_tuple(T::Type) - p = (Base.unwrap_unionall(T)::Union{DataType, Union}).parameters + u = Base.unwrap_unionall(T) + u isa Union && return typejoin( + typejoin_union_tuple(rewrap_unionall(u.a, T)), + typejoin_union_tuple(rewrap_unionall(u.b, T))) + p = (u::DataType).parameters lr = length(p)::Int if lr == 0 return Tuple{} @@ -716,7 +720,7 @@ end if U === Union{} ci = Union{} elseif U isa Union - ci = typejoin(U.a, U.b) + ci = typejoin(rewrap_unionall(U.a, T), rewrap_unionall(U.b, T)) else ci = U end @@ -727,7 +731,7 @@ end c[i] = ci end end - return Tuple{c...} + return rewrap_unionall(Tuple{c...}, T) end # Inferred eltype of result of broadcast(f, args...) From d7721a0e9b20c2a67bd8ac86a1fd3af8f3356971 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Tue, 29 Sep 2020 18:55:24 +0200 Subject: [PATCH 09/12] Fix whitespace --- base/broadcast.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index f676aeee0c5c3..315d047012977 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -708,7 +708,7 @@ end u isa Union && return typejoin( typejoin_union_tuple(rewrap_unionall(u.a, T)), typejoin_union_tuple(rewrap_unionall(u.b, T))) - p = (u::DataType).parameters + p = (u::DataType).parameters lr = length(p)::Int if lr == 0 return Tuple{} From 42d1020e52837f8bdd0c897e0089bcb0fab4a2fe Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Tue, 29 Sep 2020 21:36:56 +0200 Subject: [PATCH 10/12] Fix missing module prefix --- base/broadcast.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index 315d047012977..b838bcae8197f 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -706,8 +706,8 @@ end @pure function typejoin_union_tuple(T::Type) u = Base.unwrap_unionall(T) u isa Union && return typejoin( - typejoin_union_tuple(rewrap_unionall(u.a, T)), - typejoin_union_tuple(rewrap_unionall(u.b, T))) + typejoin_union_tuple(Base.rewrap_unionall(u.a, T)), + typejoin_union_tuple(Base.rewrap_unionall(u.b, T))) p = (u::DataType).parameters lr = length(p)::Int if lr == 0 @@ -720,7 +720,7 @@ end if U === Union{} ci = Union{} elseif U isa Union - ci = typejoin(rewrap_unionall(U.a, T), rewrap_unionall(U.b, T)) + ci = typejoin(Base.rewrap_unionall(U.a, T), Base.rewrap_unionall(U.b, T)) else ci = U end @@ -731,7 +731,7 @@ end c[i] = ci end end - return rewrap_unionall(Tuple{c...}, T) + return Base.rewrap_unionall(Tuple{c...}, T) end # Inferred eltype of result of broadcast(f, args...) From 56d37ff7c35b4afd6a3f8d1a448e88e0b9674802 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Mon, 5 Oct 2020 22:10:24 +0200 Subject: [PATCH 11/12] Apply suggestions from code review Co-authored-by: Jameson Nash --- base/broadcast.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index b838bcae8197f..f71d95371811f 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -726,7 +726,7 @@ end end if i == lr && Core.Compiler.isvarargtype(pi) N = (Base.unwrap_unionall(pi)::DataType).parameters[2] - c[i] = Vararg{ci, N} + c[i] = Base.rewrap_unionall(Vararg{ci, N}, pi) else c[i] = ci end @@ -923,7 +923,7 @@ const NonleafHandlingStyles = Union{DefaultArrayStyle,ArrayConflict} # Now handle the remaining values # The typeassert gives inference a helping hand on the element type and dimensionality # (work-around for #28382) - ElType′ = ElType <: Type ? DataType : ElType + ElType′ = ElType <: Type ? Type : ElType RT = dest isa AbstractArray ? AbstractArray{<:ElType′, ndims(dest)} : Any return copyto_nonleaf!(dest, bc′, iter, state, 1)::RT end From 0c78029cdf199d6d9ddc24b6543bb0bafdf562ec Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Sat, 24 Oct 2020 22:45:25 +0200 Subject: [PATCH 12/12] Use typejoin --- base/broadcast.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index 1255e8127f587..34c2241864fd6 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -720,7 +720,7 @@ end if U === Union{} ci = Union{} elseif U isa Union - ci = typejoin(Base.rewrap_unionall(U.a, T), Base.rewrap_unionall(U.b, T)) + ci = typejoin(U.a, U.b) else ci = U end