From 64a4fe7132934b15ad1272a63863aa1a3d005398 Mon Sep 17 00:00:00 2001 From: Martin Holters <martin.holters@hsu-hh.de> Date: Mon, 20 Mar 2017 10:05:07 +0100 Subject: [PATCH 1/3] Use `typejoin` of the field types for `eltype` of heterogeneous `Tuple`s --- base/tuple.jl | 9 +++++++++ test/tuple.jl | 7 ++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/base/tuple.jl b/base/tuple.jl index b3799e57d6fba..e96e3ab06db97 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -63,6 +63,15 @@ first(t::Tuple) = t[1] eltype(::Type{Tuple{}}) = Bottom eltype(::Type{<:Tuple{Vararg{E}}}) where {E} = E +function eltype(t::Type{<:Tuple}) + @_pure_meta + t´ = unwrap_unionall(t) + r = Union{} + for ti in t´.parameters + r = typejoin(r, unwrapva(ti)) + end + return rewrap_unionall(r, t) +end # version of tail that doesn't throw on empty tuples (used in array indexing) safe_tail(t::Tuple) = tail(t) diff --git a/test/tuple.jl b/test/tuple.jl index 20ccbe348587c..8a2e3de09275b 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -65,8 +65,13 @@ end @test eltype((1,2,3)) === Int @test eltype((1.0,2.0,3.0)) <: AbstractFloat @test eltype((true, false)) === Bool -@test eltype((1,2.0, false)) === Any +@test eltype((1, 2.0, false)) === typejoin(Int, Float64, Bool) @test eltype(()) === Union{} +@test eltype(Tuple{Int, Float64, Vararg{Bool}}) === typejoin(Int, Float64, Bool) +@test eltype(Tuple{Int, T, Vararg{Bool}} where T <: AbstractFloat) === + typejoin(Int, AbstractFloat, Bool) +@test eltype(Tuple{Int, Bool, Vararg{T}} where T <: AbstractFloat) === + typejoin(Int, AbstractFloat, Bool) begin local foo From da53d717ebdcacef2f712b6cb9c8ba6bbf97b64e Mon Sep 17 00:00:00 2001 From: Martin Holters <martin.holters@hsu-hh.de> Date: Mon, 20 Mar 2017 17:24:24 +0100 Subject: [PATCH 2/3] Move `rewrap_unionall` in `eltype(::Type{<:Tuple})` --- base/tuple.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/tuple.jl b/base/tuple.jl index e96e3ab06db97..ec4bcbf2434a4 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -68,9 +68,9 @@ function eltype(t::Type{<:Tuple}) t´ = unwrap_unionall(t) r = Union{} for ti in t´.parameters - r = typejoin(r, unwrapva(ti)) + r = typejoin(r, rewrap_unionall(unwrapva(ti), t)) end - return rewrap_unionall(r, t) + return r end # version of tail that doesn't throw on empty tuples (used in array indexing) From 4752d246105ec7c9114efa51fd15ce7cb4e950e9 Mon Sep 17 00:00:00 2001 From: Martin Holters <martin.holters@hsu-hh.de> Date: Tue, 21 Mar 2017 08:51:57 +0100 Subject: [PATCH 3/3] Handle `Union` of `Tuple`s in `eltype(::Type{<:Tuple})` --- base/tuple.jl | 1 + test/tuple.jl | 1 + 2 files changed, 2 insertions(+) diff --git a/base/tuple.jl b/base/tuple.jl index ec4bcbf2434a4..3b45f812fc0b6 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -65,6 +65,7 @@ eltype(::Type{Tuple{}}) = Bottom eltype(::Type{<:Tuple{Vararg{E}}}) where {E} = E function eltype(t::Type{<:Tuple}) @_pure_meta + t isa Union && return typejoin(eltype(t.a), eltype(t.b)) t´ = unwrap_unionall(t) r = Union{} for ti in t´.parameters diff --git a/test/tuple.jl b/test/tuple.jl index 8a2e3de09275b..70f08a30f667a 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -72,6 +72,7 @@ end typejoin(Int, AbstractFloat, Bool) @test eltype(Tuple{Int, Bool, Vararg{T}} where T <: AbstractFloat) === typejoin(Int, AbstractFloat, Bool) +@test eltype(Union{Tuple{Int, Float64}, Tuple{Vararg{Bool}}}) === typejoin(Int, Float64, Bool) begin local foo