From 2e49e39070fe6d9add47af7f1da946829a3f6854 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Mon, 29 Jan 2018 22:39:30 +0100 Subject: [PATCH 1/2] Use promote_typejoin() to choose type parameters in Dict constructor This is consistent with Array, NamedTuple and Tuple (via its eltype method), and in particular the Dict(::AbstractArray{<:Pair}) constructor. --- base/dict.jl | 6 ++---- test/dict.jl | 11 +++++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/base/dict.jl b/base/dict.jl index 9d264a6091c1e..050e0484ff89f 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -130,10 +130,8 @@ copy(d::Dict) = Dict(d) const AnyDict = Dict{Any,Any} -Dict(ps::Pair{K,V}...) where {K,V} = Dict{K,V}(ps) -Dict(ps::Pair{K}...) where {K} = Dict{K,Any}(ps) -Dict(ps::(Pair{K,V} where K)...) where {V} = Dict{Any,V}(ps) -Dict(ps::Pair...) = Dict{Any,Any}(ps) +Dict(ps::Pair{K,V}...) where {K,V} = Dict{K,V}(ps) +Dict(ps::Pair...) = Dict(ps) function Dict(kv) try diff --git a/test/dict.jl b/test/dict.jl index f4d9a4b1f4399..a5e0b5fbc79f9 100644 --- a/test/dict.jl +++ b/test/dict.jl @@ -160,6 +160,17 @@ end @test d == Dict{Real,Real}(2.0=>3.0, 1=>2) end +@testset "type of Dict constructed from varargs of Pairs" begin + @test Dict(1=>1, 2=>2.0) isa Dict{Int,Real} + @test Dict(1=>1, 2.0=>2) isa Dict{Real,Int} + @test Dict(1=>1.0, 2.0=>2) isa Dict{Real,Real} + + @test Dict(1=>1, 2=>missing) isa Dict{Int,Union{Int,Missing}} + @test Dict(1=>1, 2=>nothing) isa Dict{Int,Union{Int,Nothing}} + @test Dict(1=>1, missing=>2) isa Dict{Union{Int,Missing},Int} + @test Dict(1=>1, nothing=>2) isa Dict{Union{Int,Nothing},Int} +end + @test_throws KeyError Dict("a"=>2)[Base.secret_table_token] @testset "issue #1821" begin From ea96757cde444ab11527901e450d02f462550915 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Sat, 10 Feb 2018 17:47:58 +0100 Subject: [PATCH 2/2] Fix promote_type(Union{}, Missing/Nothing) and add tests Without this Dict(1=>missing, 2=>2) returns a Dict{Int,Any}. --- base/promotion.jl | 8 ++++---- test/core.jl | 2 ++ test/dict.jl | 10 ++++++---- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/base/promotion.jl b/base/promotion.jl index 3b82a64d955f1..4b851fca93760 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -117,13 +117,13 @@ Falls back to [`typejoin`](@ref). promote_typejoin(@nospecialize(a), @nospecialize(b)) = (@_pure_meta; join_types(a, b, promote_typejoin)) promote_typejoin(::Type{Nothing}, ::Type{T}) where {T} = - isconcretetype(T) ? Union{T, Nothing} : Any + isconcretetype(T) || T === Union{} ? Union{T, Nothing} : Any promote_typejoin(::Type{T}, ::Type{Nothing}) where {T} = - isconcretetype(T) ? Union{T, Nothing} : Any + isconcretetype(T) || T === Union{} ? Union{T, Nothing} : Any promote_typejoin(::Type{Missing}, ::Type{T}) where {T} = - isconcretetype(T) ? Union{T, Missing} : Any + isconcretetype(T) || T === Union{} ? Union{T, Missing} : Any promote_typejoin(::Type{T}, ::Type{Missing}) where {T} = - isconcretetype(T) ? Union{T, Missing} : Any + isconcretetype(T) || T === Union{} ? Union{T, Missing} : Any promote_typejoin(::Type{Nothing}, ::Type{Missing}) = Union{Nothing, Missing} promote_typejoin(::Type{Missing}, ::Type{Nothing}) = Union{Nothing, Missing} promote_typejoin(::Type{Nothing}, ::Type{Nothing}) = Nothing diff --git a/test/core.jl b/test/core.jl index 91a61a6ecac2e..969db095e3a6e 100644 --- a/test/core.jl +++ b/test/core.jl @@ -139,6 +139,8 @@ for T in (Nothing, Missing) @test Base.promote_typejoin(Int, String) === Any @test Base.promote_typejoin(Int, Union{Float64, T}) === Any @test Base.promote_typejoin(Int, Union{String, T}) === Any + @test Base.promote_typejoin(T, Union{}) === T + @test Base.promote_typejoin(Union{}, T) === T end @test promote_type(Bool,Bottom) === Bool diff --git a/test/dict.jl b/test/dict.jl index a5e0b5fbc79f9..fc0b0b1a6dc09 100644 --- a/test/dict.jl +++ b/test/dict.jl @@ -165,10 +165,12 @@ end @test Dict(1=>1, 2.0=>2) isa Dict{Real,Int} @test Dict(1=>1.0, 2.0=>2) isa Dict{Real,Real} - @test Dict(1=>1, 2=>missing) isa Dict{Int,Union{Int,Missing}} - @test Dict(1=>1, 2=>nothing) isa Dict{Int,Union{Int,Nothing}} - @test Dict(1=>1, missing=>2) isa Dict{Union{Int,Missing},Int} - @test Dict(1=>1, nothing=>2) isa Dict{Union{Int,Nothing},Int} + for T in (Nothing, Missing) + @test Dict(1=>1, 2=>T()) isa Dict{Int,Union{Int,T}} + @test Dict(1=>T(), 2=>2) isa Dict{Int,Union{Int,T}} + @test Dict(1=>1, T()=>2) isa Dict{Union{Int,T},Int} + @test Dict(T()=>1, 2=>2) isa Dict{Union{Int,T},Int} + end end @test_throws KeyError Dict("a"=>2)[Base.secret_table_token]