Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix bug with max_values in union! #30315

Merged
merged 1 commit into from
Dec 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions base/abstractset.jl
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,11 @@ function union!(s::AbstractSet, sets...)
end

max_values(::Type) = typemax(Int)
max_values(T::Type{<:Union{Nothing,BitIntegerSmall}}) = 1 << (8*sizeof(T))
max_values(T::Union) = max(max_values(T.a), max_values(T.b))
max_values(T::Union{map(X -> Type{X}, BitIntegerSmall_types)...}) = 1 << (8*sizeof(T))
# saturated addition to prevent overflow with typemax(Int)
max_values(T::Union) = max(max_values(T.a), max_values(T.b), max_values(T.a) + max_values(T.b))
max_values(::Type{Bool}) = 2
max_values(::Type{Nothing}) = 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be applied to all singleton types? You can check whether a type is a singleton using isdefined(T, :instance) (there's an issingletontype helper function for this in replace.jl).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes seems like a good idea!
As CI is green and I think this is an urgent fix to have, I will merge as-is later today and implement your idea (which is not directly related to the bugfix) separately.


function union!(s::AbstractSet{T}, itr) where T
haslength(itr) && sizehint!(s, length(s) + length(itr))
Expand Down
21 changes: 21 additions & 0 deletions test/sets.jl
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,27 @@ end
end
end

@testset "optimized union! with max_values" begin
# issue #30315
T = Union{Nothing, Bool}
@test Base.max_values(T) == 3
d = Set{T}()
union!(d, (nothing, true, false))
@test length(d) == 3
@test d == Set((nothing, true, false))
@test nothing in d
@test true in d
@test false in d

for X = (Int8, Int16, Int32, Int64)
@test Base.max_values(Union{Nothing, X}) == (sizeof(X) < sizeof(Int) ?
2^(8*sizeof(X)) + 1 :
typemax(Int))
end
# this does not account for non-empty intersections of the unioned types
@test Base.max_values(Union{Int8,Int16}) == 2^8 + 2^16
end

struct OpenInterval{T}
lower::T
upper::T
Expand Down