Skip to content

Commit 44b9fce

Browse files
rfourquetKristofferC
authored andcommitted
fix bug with max_values in union! (#30315)
(cherry picked from commit f49cb42)
1 parent 57243bb commit 44b9fce

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

base/abstractset.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,11 @@ function union!(s::AbstractSet, sets...)
6767
end
6868

6969
max_values(::Type) = typemax(Int)
70-
max_values(T::Type{<:Union{Nothing,BitIntegerSmall}}) = 1 << (8*sizeof(T))
71-
max_values(T::Union) = max(max_values(T.a), max_values(T.b))
70+
max_values(T::Union{map(X -> Type{X}, BitIntegerSmall_types)...}) = 1 << (8*sizeof(T))
71+
# saturated addition to prevent overflow with typemax(Int)
72+
max_values(T::Union) = max(max_values(T.a), max_values(T.b), max_values(T.a) + max_values(T.b))
7273
max_values(::Type{Bool}) = 2
74+
max_values(::Type{Nothing}) = 1
7375

7476
function union!(s::AbstractSet{T}, itr) where T
7577
haslength(itr) && sizehint!(s, length(s) + length(itr))

test/sets.jl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,27 @@ end
613613
end
614614
end
615615

616+
@testset "optimized union! with max_values" begin
617+
# issue #30315
618+
T = Union{Nothing, Bool}
619+
@test Base.max_values(T) == 3
620+
d = Set{T}()
621+
union!(d, (nothing, true, false))
622+
@test length(d) == 3
623+
@test d == Set((nothing, true, false))
624+
@test nothing in d
625+
@test true in d
626+
@test false in d
627+
628+
for X = (Int8, Int16, Int32, Int64)
629+
@test Base.max_values(Union{Nothing, X}) == (sizeof(X) < sizeof(Int) ?
630+
2^(8*sizeof(X)) + 1 :
631+
typemax(Int))
632+
end
633+
# this does not account for non-empty intersections of the unioned types
634+
@test Base.max_values(Union{Int8,Int16}) == 2^8 + 2^16
635+
end
636+
616637
struct OpenInterval{T}
617638
lower::T
618639
upper::T

0 commit comments

Comments
 (0)