diff --git a/NEWS.md b/NEWS.md index 8c06002f2e758..a9d2533299cf2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -82,6 +82,14 @@ Language changes For example, `f() = (global sin = "gluttony"; nothing)` will now resolve which module contains `sin` eagerly, rather than delaying that decision until `f` is run. ([#22984]). + * Uninitialized `BitArray` constructors of the form `BitArray[{N}](shape...)` have been + deprecated in favor of equivalents accepting `uninitialized` (an alias for + `Uninitialized()`) as their first argument, as in + `BitArray[{N}](uninitialized, shape...)`. For example, `BitVector(3)` is now + `BitVector(uninitialized, 3)`, `BitMatrix((2, 4))` is now + `BitMatrix(uninitialized, (2, 4))`, and `BitArray{3}(11, 13, 17)` is now + `BitArray{3}(uninitialized, 11, 14, 17)` ([#24785]). + * Dispatch rules have been simplified: method matching is now determined exclusively by subtyping; the rule that method type parameters must also be captured has been removed. diff --git a/base/bitarray.jl b/base/bitarray.jl index 3d2267bc49f00..6dafc69a772cf 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -13,7 +13,7 @@ mutable struct BitArray{N} <: DenseArray{Bool, N} chunks::Vector{UInt64} len::Int dims::NTuple{N,Int} - function BitArray{N}(dims::Vararg{Int,N}) where N + function BitArray{N}(::Uninitialized, dims::Vararg{Int,N}) where N n = 1 i = 1 for d in dims @@ -34,33 +34,35 @@ end # the first one is recognized by the help system; it would be nice # to fix this. """ - BitArray(dims::Integer...) - BitArray{N}(dims::NTuple{N,Int}) + BitArray(uninitialized, dims::Integer...) + BitArray{N}(uninitialized, dims::NTuple{N,Int}) Construct an uninitialized [`BitArray`](@ref) with the given dimensions. -Behaves identically to the [`Array`](@ref) constructor. +Behaves identically to the [`Array`](@ref) constructor. See [`uninitialized`](@ref). # Examples ```julia-repl -julia> BitArray(2, 2) +julia> BitArray(uninitialized, 2, 2) 2×2 BitArray{2}: false false false true -julia> BitArray((3, 1)) +julia> BitArray(uninitialized, (3, 1)) 3×1 BitArray{2}: false true false ``` """ -BitArray(dims::Integer...) = BitArray(map(Int,dims)) -BitArray(dims::NTuple{N,Int}) where {N} = BitArray{N}(dims...) +BitArray(::Uninitialized, dims::Integer...) = BitArray(uninitialized, map(Int,dims)) +BitArray{N}(::Uninitialized, dims::Integer...) where {N} = BitArray{N}(uninitialized, map(Int,dims)) +BitArray(::Uninitialized, dims::NTuple{N,Int}) where {N} = BitArray{N}(uninitialized, dims...) +BitArray{N}(::Uninitialized, dims::NTuple{N,Int}) where {N} = BitArray{N}(uninitialized, dims...) const BitVector = BitArray{1} const BitMatrix = BitArray{2} -BitVector() = BitArray{1}(0) +BitVector() = BitArray{1}(uninitialized, 0) ## utility functions ## @@ -341,15 +343,17 @@ done(B::BitArray, i::Int) = i >= length(B) ## similar, fill!, copy! etc ## -similar(B::BitArray) = BitArray(size(B)) -similar(B::BitArray, dims::Int...) = BitArray(dims) -similar(B::BitArray, dims::Dims) = BitArray(dims...) +similar(B::BitArray) = BitArray(uninitialized, size(B)) +similar(B::BitArray, dims::Int...) = BitArray(uninitialized, dims) +similar(B::BitArray, dims::Dims) = BitArray(uninitialized, dims...) -similar(B::BitArray, T::Type{Bool}, dims::Dims) = BitArray(dims) +similar(B::BitArray, T::Type{Bool}, dims::Dims) = BitArray(uninitialized, dims) # changing type to a non-Bool returns an Array # (this triggers conversions like float(bitvector) etc.) similar(B::BitArray, T::Type, dims::Dims) = Array{T}(uninitialized, dims) +similar(::Type{T}, shape::Tuple) where {T<:BitArray} = T(uninitialized, to_shape(shape)) + function fill!(B::BitArray, x) y = convert(Bool, x) isempty(B) && return B @@ -376,7 +380,7 @@ julia> falses(2,3) false false false ``` """ -falses(dims::Dims) = fill!(BitArray(dims), false) +falses(dims::Dims) = fill!(BitArray(uninitialized, dims), false) falses(dims::Integer...) = falses(map(Int,dims)) """ falses(A) @@ -411,7 +415,7 @@ julia> trues(2,3) true true true ``` """ -trues(dims::Dims) = fill!(BitArray(dims), true) +trues(dims::Dims) = fill!(BitArray(uninitialized, dims), true) trues(dims::Integer...) = trues(map(Int,dims)) """ trues(A) @@ -490,7 +494,7 @@ reshape(B::BitArray, dims::Tuple{Vararg{Int}}) = _bitreshape(B, dims) function _bitreshape(B::BitArray, dims::NTuple{N,Int}) where N prod(dims) == length(B) || throw(DimensionMismatch("new dimensions $(dims) must be consistent with array size $(length(B))")) - Br = BitArray{N}(ntuple(i->0,Val(N))...) + Br = BitArray{N}(uninitialized, ntuple(i->0,Val(N))...) Br.chunks = B.chunks Br.len = prod(dims) N != 1 && (Br.dims = dims) @@ -512,7 +516,7 @@ end convert(::Type{BitArray}, A::AbstractArray{T,N}) where {T,N} = convert(BitArray{N}, A) function convert(::Type{BitArray{N}}, A::AbstractArray{T,N}) where N where T - B = BitArray(size(A)) + B = BitArray(uninitialized, size(A)) Bc = B.chunks l = length(B) l == 0 && return B @@ -537,7 +541,7 @@ function convert(::Type{BitArray{N}}, A::AbstractArray{T,N}) where N where T end function convert(::Type{BitArray{N}}, A::Array{Bool,N}) where N - B = BitArray(size(A)) + B = BitArray(uninitialized, size(A)) Bc = B.chunks l = length(B) l == 0 && return B @@ -595,7 +599,7 @@ gen_bitarray(isz::IteratorSize, itr) = gen_bitarray_from_itr(itr, start(itr)) # generic iterable with known shape function gen_bitarray(::HasShape, itr) - B = BitArray(size(itr)) + B = BitArray(uninitialized, size(itr)) for (I,x) in zip(CartesianRange(indices(itr)), itr) B[I] = x end @@ -604,13 +608,12 @@ end # generator with known shape or length function gen_bitarray(::HasShape, itr::Generator) - B = BitArray(size(itr)) + B = BitArray(uninitialized, size(itr)) return fill_bitarray_from_itr!(B, itr, start(itr)) end function gen_bitarray(::HasLength, itr) - n = length(itr) - B = BitArray(n) - return fill_bitarray_from_itr!(B, itr, start(itr)) + b = BitVector(uninitialized, length(itr)) + return fill_bitarray_from_itr!(b, itr, start(itr)) end gen_bitarray(::IsInfinite, itr) = throw(ArgumentError("infinite-size iterable used in BitArray constructor")) @@ -619,7 +622,7 @@ gen_bitarray(::IsInfinite, itr) = throw(ArgumentError("infinite-size iterable u # use a Vector{Bool} cache for performance reasons function gen_bitarray_from_itr(itr, st) - B = empty!(BitArray(bitcache_size)) + B = empty!(BitVector(uninitialized, bitcache_size)) C = Vector{Bool}(uninitialized, bitcache_size) Bc = B.chunks ind = 1 @@ -1050,7 +1053,7 @@ function splice!(B::BitVector, i::Integer) return v end -const _default_bit_splice = BitVector(0) +const _default_bit_splice = BitVector() function splice!(B::BitVector, r::Union{UnitRange{Int}, Integer}, ins::AbstractArray = _default_bit_splice) n = length(B) @@ -1064,7 +1067,7 @@ function splice!(B::BitVector, r::Union{UnitRange{Int}, Integer}, ins::AbstractA if (i_f > n) append!(B, Bins) - return BitVector(0) + return BitVector() end v = B[r] # TODO: change to a copy if/when subscripting becomes an ArrayView @@ -1094,7 +1097,7 @@ function splice!(B::BitVector, r::Union{UnitRange{Int}, Integer}, ins::AbstractA end function splice!(B::BitVector, r::Union{UnitRange{Int}, Integer}, ins) - Bins = BitArray(length(ins)) + Bins = BitVector(uninitialized, length(ins)) i = 1 for x in ins Bins[i] = Bool(x) @@ -1221,7 +1224,7 @@ broadcast(::typeof(xor), x::Bool, B::BitArray) = broadcast(xor, B, x) for f in (:&, :|, :xor) @eval begin function broadcast(::typeof($f), A::BitArray, B::BitArray) - F = BitArray(promote_shape(size(A),size(B))...) + F = BitArray(uninitialized, promote_shape(size(A),size(B))...) Fc = F.chunks Ac = A.chunks Bc = B.chunks @@ -1803,7 +1806,7 @@ function hcat(B::BitVector...) length(B[j]) == height || throw(DimensionMismatch("dimensions must match")) end - M = BitArray(height, length(B)) + M = BitMatrix(uninitialized, height, length(B)) for j = 1:length(B) copy_chunks!(M.chunks, (height*(j-1))+1, B[j].chunks, 1, height) end @@ -1815,7 +1818,7 @@ function vcat(V::BitVector...) for Vk in V n += length(Vk) end - B = BitArray(n) + B = BitVector(uninitialized, n) j = 1 for Vk in V copy_chunks!(B.chunks, j, Vk.chunks, 1, length(Vk)) @@ -1837,7 +1840,7 @@ function hcat(A::Union{BitMatrix,BitVector}...) throw(DimensionMismatch("row lengths must match")) end - B = BitArray(nrows, ncols) + B = BitMatrix(uninitialized, nrows, ncols) pos = 1 for k = 1:nargs @@ -1857,7 +1860,7 @@ function vcat(A::BitMatrix...) size(A[j], 2) == ncols || throw(DimensionMismatch("column lengths must match")) end - B = BitArray(nrows, ncols) + B = BitMatrix(uninitialized, nrows, ncols) Bc = B.chunks nrowsA = [size(a, 1) for a in A] Ac = [a.chunks for a in A] diff --git a/base/deprecated.jl b/base/deprecated.jl index 30d76b3f8763f..48456d017f31b 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1877,6 +1877,11 @@ end @deprecate diagm(v::AbstractVector, k::Integer) diagm(k => v) @deprecate diagm(x::Number) fill(x, 1, 1) +# deprecate BitArray{...}(shape...) constructors to BitArray{...}(uninitialized, shape...) equivalents +@deprecate BitArray{N}(dims::Vararg{Int,N}) where {N} BitArray{N}(uninitialized, dims) +@deprecate BitArray(dims::NTuple{N,Int}) where {N} BitArray(uninitialized, dims...) +@deprecate BitArray(dims::Integer...) BitArray(uninitialized, dims) + ## deprecate full export full # full no-op fallback diff --git a/base/pkg/cache.jl b/base/pkg/cache.jl index db9d2426c4704..61127cf281bdf 100644 --- a/base/pkg/cache.jl +++ b/base/pkg/cache.jl @@ -58,11 +58,11 @@ function prefetch(pkg::AbstractString, url::AbstractString, sha1s::Vector) end try LibGit2.set_remote_url(repo, "origin", normalized_url) - in_cache = BitArray(map(sha1->LibGit2.iscommit(sha1, repo), sha1s)) + in_cache = BitVector(map(sha1->LibGit2.iscommit(sha1, repo), sha1s)) if !all(in_cache) info("Updating cache of $pkg...") LibGit2.fetch(repo) - in_cache = BitArray(map(sha1->LibGit2.iscommit(sha1, repo), sha1s)) + in_cache = BitVector(map(sha1->LibGit2.iscommit(sha1, repo), sha1s)) end sha1s[.!in_cache] finally diff --git a/base/random/misc.jl b/base/random/misc.jl index 55b9e09079159..ded18d5c07c03 100644 --- a/base/random/misc.jl +++ b/base/random/misc.jl @@ -33,11 +33,11 @@ julia> bitrand(rng, 10) true ``` """ -bitrand(r::AbstractRNG, dims::Dims) = rand!(r, BitArray(dims)) -bitrand(r::AbstractRNG, dims::Integer...) = rand!(r, BitArray(convert(Dims, dims))) +bitrand(r::AbstractRNG, dims::Dims) = rand!(r, BitArray(uninitialized, dims)) +bitrand(r::AbstractRNG, dims::Integer...) = rand!(r, BitArray(uninitialized, convert(Dims, dims))) -bitrand(dims::Dims) = rand!(BitArray(dims)) -bitrand(dims::Integer...) = rand!(BitArray(convert(Dims, dims))) +bitrand(dims::Dims) = rand!(BitArray(uninitialized, dims)) +bitrand(dims::Integer...) = rand!(BitArray(uninitialized, convert(Dims, dims))) ## randstring (often useful for temporary filenames/dirnames) diff --git a/doc/src/stdlib/arrays.md b/doc/src/stdlib/arrays.md index 6d97c072088a9..9ec8c580cc1fa 100644 --- a/doc/src/stdlib/arrays.md +++ b/doc/src/stdlib/arrays.md @@ -20,7 +20,7 @@ Base.getindex(::Type, ::Any...) Base.zeros Base.ones Base.BitArray -Base.BitArray(::Integer...) +Base.BitArray(::Uninitialized, ::Integer...) Base.BitArray(::Any) Base.trues Base.falses diff --git a/stdlib/Mmap/src/Mmap.jl b/stdlib/Mmap/src/Mmap.jl index e5d0fccd90456..8e91cb940dd72 100644 --- a/stdlib/Mmap/src/Mmap.jl +++ b/stdlib/Mmap/src/Mmap.jl @@ -259,7 +259,7 @@ function mmap(io::IOStream, ::Type{<:BitArray}, dims::NTuple{N,Integer}, throw(ArgumentError("the given file does not contain a valid BitArray of size $(join(dims, 'x')) (open with \"r+\" mode to override)")) end end - B = BitArray{N}(ntuple(i->0,Val(N))...) + B = BitArray{N}(uninitialized, ntuple(i->0,Val(N))...) B.chunks = chunks B.len = n if N != 1 diff --git a/test/TestHelpers.jl b/test/TestHelpers.jl index 78736bf4878fa..65f30e8f934da 100644 --- a/test/TestHelpers.jl +++ b/test/TestHelpers.jl @@ -181,7 +181,10 @@ function Base.similar(A::AbstractArray, T::Type, inds::Tuple{UnitRange,Vararg{Un OffsetArray(B, map(indsoffset, inds)) end -Base.similar(f::Union{Function,Type}, shape::Tuple{UnitRange,Vararg{UnitRange}}) = OffsetArray(f(map(length, shape)), map(indsoffset, shape)) +Base.similar(f::Union{Function,Type}, shape::Tuple{UnitRange,Vararg{UnitRange}}) = + OffsetArray(f(map(length, shape)), map(indsoffset, shape)) +Base.similar(::Type{T}, shape::Tuple{UnitRange,Vararg{UnitRange}}) where {T<:BitArray} = + OffsetArray(T(uninitialized, map(length, shape)), map(indsoffset, shape)) Base.reshape(A::AbstractArray, inds::Tuple{UnitRange,Vararg{UnitRange}}) = OffsetArray(reshape(A, map(length, inds)), map(indsoffset, inds)) diff --git a/test/bitarray.jl b/test/bitarray.jl index 9e2ab38ccf8e4..1ea8872869d56 100644 --- a/test/bitarray.jl +++ b/test/bitarray.jl @@ -40,7 +40,7 @@ let t0 = time() end @testset "empty bitvector" begin - @test BitVector() == BitVector(0) + @test BitVector() == BitVector(uninitialized, 0) end # vectors size @@ -156,8 +156,8 @@ timesofar("conversions") end @testset "sizeof (issue #7515)" begin - @test sizeof(BitArray(64)) == 8 - @test sizeof(BitArray(65)) == 16 + @test sizeof(BitVector(uninitialized, 64)) == 8 + @test sizeof(BitVector(uninitialized, 65)) == 16 end end @@ -165,8 +165,8 @@ timesofar("utils") @testset "Constructors" begin @testset "non-Int dims constructors" begin - b1 = BitArray(Int32(v1)) - b2 = BitArray(Int64(v1)) + b1 = BitVector(uninitialized, Int32(v1)) + b2 = BitVector(uninitialized, Int64(v1)) @test size(b1) == size(b2) for c in [trues, falses] @@ -187,14 +187,14 @@ timesofar("utils") end @testset "one" begin - @test Array(one(BitMatrix(2,2))) == Matrix(I, 2, 2) - @test_throws DimensionMismatch one(BitMatrix(2,3)) + @test Array(one(BitMatrix(uninitialized, 2,2))) == Matrix(I, 2, 2) + @test_throws DimensionMismatch one(BitMatrix(uninitialized, 2,3)) end # constructors should copy a = trues(3) @test BitArray(a) !== a - @test BitArray{1}(a) !== a + @test BitVector(a) !== a # issue #24062 @test_throws InexactError BitArray([0, 1, 2, 3]) @@ -511,7 +511,7 @@ end timesofar("indexing") @testset "Deque Functionality" begin - b1 = BitArray(0) + b1 = BitVector() i1 = Bool[] for m = 1:v1 x = rand(Bool) @@ -553,7 +553,7 @@ timesofar("indexing") @test length(b1) == 0 - b1 = BitArray(0) + b1 = BitVector() i1 = Bool[] for m = 1:v1 x = rand(Bool) @@ -574,7 +574,7 @@ timesofar("indexing") end @test length(b1) == 0 - b1 = BitArray(0) + b1 = BitVector() @test_throws BoundsError insert!(b1, 2, false) @test_throws BoundsError insert!(b1, 0, false) i1 = Array(b1) @@ -1182,7 +1182,7 @@ timesofar("nnz&find") @test findlast(b1) == Base.findlastnot(b2) == 777 @test findfirst(b1) == Base.findfirstnot(b2) == 77 - b0 = BitVector(0) + b0 = BitVector() @test findprev(x->true, b0, -1) == 0 @test_throws BoundsError findprev(x->true, b0, 1) @test_throws BoundsError findnext(x->true, b0, -1) @@ -1267,7 +1267,7 @@ timesofar("reductions") @test map(!=, b1, b2) == map((x,y)->x!=y, b1, b2) == (b1 .!= b2) @testset "map! for length $l" begin - b = BitArray(l) + b = BitVector(uninitialized, l) @test map!(~, b, b1) == map!(x->~x, b, b1) == broadcast(~, b1) == b @test map!(!, b, b1) == map!(x->!x, b, b1) == broadcast(~, b1) == b @test map!(identity, b, b1) == map!(x->x, b, b1) == b1 == b @@ -1468,11 +1468,11 @@ end @test_throws DimensionMismatch read!(fname, b2) @test bitcheck(b2) - b1 = BitArray(0) + b1 = BitVector() open(fname, "w") do f write(f, b1) end - b2 = BitArray(0) + b2 = BitVector() read!(fname, b2) @test b1 == b2 @test bitcheck(b2) diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index a68781ec01285..40fcf47cf142e 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -628,9 +628,9 @@ end testmap_equivalence(identity, (1,2,3,4)) testmap_equivalence(x->x>0 ? 1.0 : 0.0, sparse(1.0I, 5, 5)) testmap_equivalence((x,y,z)->x+y+z, 1,2,3) -testmap_equivalence(x->x ? false : true, BitArray(10,10)) -testmap_equivalence(x->"foobar", BitArray(10,10)) -testmap_equivalence((x,y,z)->string(x,y,z), BitArray(10), ones(10), "1234567890") +testmap_equivalence(x->x ? false : true, BitMatrix(uninitialized, 10,10)) +testmap_equivalence(x->"foobar", BitMatrix(uninitialized, 10,10)) +testmap_equivalence((x,y,z)->string(x,y,z), BitVector(uninitialized, 10), ones(10), "1234567890") @test asyncmap(uppercase, "Hello World!") == map(uppercase, "Hello World!") @test pmap(uppercase, "Hello World!") == map(uppercase, "Hello World!") diff --git a/test/random.jl b/test/random.jl index e3601904a98db..14c7c040cb8d3 100644 --- a/test/random.jl +++ b/test/random.jl @@ -409,8 +409,8 @@ for rng in ([], [MersenneTwister(0)], [RandomDevice()]) bitrand(rng..., 5) ::BitArray{1} bitrand(rng..., 2, 3) ::BitArray{2} bitrand(rng..., b2, u3) ::BitArray{2} - rand!(rng..., BitArray(5)) ::BitArray{1} - rand!(rng..., BitArray(2, 3)) ::BitArray{2} + rand!(rng..., BitVector(uninitialized, 5)) ::BitArray{1} + rand!(rng..., BitMatrix(uninitialized, 2, 3)) ::BitArray{2} # Test that you cannot call randn or randexp with non-Float types. for r in [randn, randexp, randn!, randexp!] diff --git a/test/show.jl b/test/show.jl index 4685672ba2ac7..6114fdb730d62 100644 --- a/test/show.jl +++ b/test/show.jl @@ -118,7 +118,7 @@ end # line meta dims::NTuple{N,Int} # line meta - function BitArray(dims::Int...) + function BitArray(uninitialized, dims::Int...) # line meta if length(dims) != N # line meta