From 89c95dee956e5934e400c1ff368e6a501aa4fb52 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Thu, 18 Nov 2021 16:04:51 +0100 Subject: [PATCH] Fix regression in `map` and `collect` (#43120) `promote_typejoin_tuple` returned a type which was more precise than the one which `map` and `collect` actually use via `promote_type`, triggering an assertion error in corner cases. --- base/promotion.jl | 16 ++++++++-------- test/broadcast.jl | 2 ++ test/generic_map_tests.jl | 2 ++ 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/base/promotion.jl b/base/promotion.jl index 21245f0e05c70b..845e16ca499d30 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -168,19 +168,17 @@ function promote_typejoin_union(::Type{T}) where T return Any # TODO: compute more precise bounds elseif T isa Union return promote_typejoin(promote_typejoin_union(T.a), promote_typejoin_union(T.b)) - elseif T <: Tuple - return typejoin_union_tuple(T) - else + elseif T isa DataType + T <: Tuple && return typejoin_union_tuple(T) return T + else + error("unreachable") # not a type?? end end -function typejoin_union_tuple(T::Type) +function typejoin_union_tuple(T::DataType) @_pure_meta u = Base.unwrap_unionall(T) - u isa Union && return typejoin( - 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 @@ -194,8 +192,10 @@ function typejoin_union_tuple(T::Type) ci = Union{} elseif U isa Union ci = typejoin(U.a, U.b) + elseif U isa UnionAll + return Any # TODO: compute more precise bounds else - ci = U + ci = promote_typejoin_union(U) end if i == lr && Core.Compiler.isvarargtype(pi) c[i] = isdefined(pi, :N) ? Vararg{ci, pi.N} : Vararg{ci} diff --git a/test/broadcast.jl b/test/broadcast.jl index 1cad14de44c5f1..b3899ddb063df7 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -1011,6 +1011,8 @@ end @test typeof.([iszero, iszero]) == [typeof(iszero), typeof(iszero)] @test isequal(identity.(Vector{<:Union{Int, Missing}}[[1, 2],[missing, 1]]), [[1, 2],[missing, 1]]) + @test broadcast(i -> ((x=i, y=(i==1 ? 1 : "a")), 3), 1:4) isa + Vector{Tuple{NamedTuple{(:x, :y)}, Int}} end @testset "Issue #28382: eltype inconsistent with getindex" begin diff --git a/test/generic_map_tests.jl b/test/generic_map_tests.jl index abd9a31946a9ad..b155370dd64650 100644 --- a/test/generic_map_tests.jl +++ b/test/generic_map_tests.jl @@ -75,6 +75,8 @@ function generic_map_tests(mapf, inplace_mapf=nothing) @test isequal(map(identity, Vector{<:Union{Int, Missing}}[[1, 2],[missing, 1]]), [[1, 2],[missing, 1]]) @test map(x -> x < 0 ? false : x, Int[]) isa Vector{Integer} + @test map(i -> ((x=i, y=(i==1 ? 1 : "a")), 3), 1:4) isa + Vector{Tuple{NamedTuple{(:x, :y)}, Int}} end function testmap_equivalence(mapf, f, c...)