Skip to content

Commit 5ccafa9

Browse files
rfourquetKristofferC
authored andcommitted
fix bug with max_values in union! (#30315)
(cherry picked from commit f49cb42)
1 parent adadb31 commit 5ccafa9

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
@@ -69,9 +69,11 @@ function union!(s::AbstractSet, sets...)
6969
end
7070

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

7678
function union!(s::AbstractSet{T}, itr) where T
7779
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
@@ -628,6 +628,27 @@ end
628628
end
629629
end
630630

631+
@testset "optimized union! with max_values" begin
632+
# issue #30315
633+
T = Union{Nothing, Bool}
634+
@test Base.max_values(T) == 3
635+
d = Set{T}()
636+
union!(d, (nothing, true, false))
637+
@test length(d) == 3
638+
@test d == Set((nothing, true, false))
639+
@test nothing in d
640+
@test true in d
641+
@test false in d
642+
643+
for X = (Int8, Int16, Int32, Int64)
644+
@test Base.max_values(Union{Nothing, X}) == (sizeof(X) < sizeof(Int) ?
645+
2^(8*sizeof(X)) + 1 :
646+
typemax(Int))
647+
end
648+
# this does not account for non-empty intersections of the unioned types
649+
@test Base.max_values(Union{Int8,Int16}) == 2^8 + 2^16
650+
end
651+
631652
struct OpenInterval{T}
632653
lower::T
633654
upper::T

0 commit comments

Comments
 (0)