diff --git a/base/missing.jl b/base/missing.jl index 403a1092a63fe..c270b8af80e3e 100644 --- a/base/missing.jl +++ b/base/missing.jl @@ -69,6 +69,33 @@ convert(::Type{T}, x::T) where {T>:Union{Missing, Nothing}} = x convert(::Type{T}, x) where {T>:Missing} = convert(nonmissingtype_checked(T), x) convert(::Type{T}, x) where {T>:Union{Missing, Nothing}} = convert(nonmissingtype_checked(nonnothingtype_checked(T)), x) +for Cs in ((:Missing,), (:Nothing,), (:Missing, :Nothing)) + @eval function Base.reinterpret( + ::Type{<:T}, # Note this is effectively same as Type{T} since will error if T is abstract + xs::Array{Union{T, $(Cs...)},N} + ) where {T,N} + isbitstype(T) || throw(ArgumentError("cannot reinterpret `$(eltype(xs))`, type `$(T)` is not a bits type")) + return unsafe_wrap(Array{T,N}, Ptr{T}(pointer(xs)), length(xs)) + end + + #== + @eval function Base.convert( + ::Type{Array{Q,N}}, + xs::Array{Union{T, $(Cs...)},N} + ) where {N} where {T<:Q} where Q + + all(x->x isa T, xs) || throw(ArgumentError("cannot convert $(eltype(xs)) to $T")) + if isbitstype(T) && + reinterpret(T, xs) + else + T[x for x in xs] + end + end + ==# +end +# Resolve ambiguity +#Base.convert(::Type{Array{Any,1}}, xs::Array{Any,1}) = xs + # Comparison operators ==(::Missing, ::Missing) = missing diff --git a/base/regex.jl b/base/regex.jl index e7eb535a70c2e..1c94e245e3189 100644 --- a/base/regex.jl +++ b/base/regex.jl @@ -145,13 +145,13 @@ function show(io::IO, m::RegexMatch) idx_to_capture_name = PCRE.capture_names(m.regex.regex) if !isempty(m.captures) print(io, ", ") - for (i, capture) in enumerate(m) + for i = 1:length(m.captures) # If the capture group is named, show the name. # Otherwise show its index. capture_name = get(idx_to_capture_name, i, i) print(io, capture_name, "=") - show(io, capture) - if i < length(m) + show(io, m.captures[i]) + if i < length(m.captures) print(io, ", ") end end @@ -168,10 +168,6 @@ function getindex(m::RegexMatch, name::Symbol) end getindex(m::RegexMatch, name::AbstractString) = m[Symbol(name)] -iterate(m::RegexMatch, args...) = iterate(m.captures, args...) -length(m::RegexMatch) = length(m.captures) -eltype(m::RegexMatch) = eltype(m.captures) - function occursin(r::Regex, s::AbstractString; offset::Integer=0) compile(r) return PCRE.exec_r(r.regex, String(s), offset, r.match_options) diff --git a/test/missing.jl b/test/missing.jl index 850482585b2cd..7cac897625f9b 100644 --- a/test/missing.jl +++ b/test/missing.jl @@ -23,6 +23,48 @@ end @test_throws MethodError convert(Union{Int, Missing}, "a") end +mutable struct NotABitsType a end +==(n1::NotABitsType,n2::NotABitsType) = n1.a == n2.a + +@testset "convert/reinterpret Arrays of Unions" begin + unions(T) = (Union{T, Missing}, Union{T, Nothing}, Union{T, Missing, Nothing}) + corrupters(::Type{T}) where T = (x for x in (missing, nothing) if x isa T) + + @testset "bits type ($U)" for U in unions(Int) + xo = U[1, 2, 3] + xr = reinterpret(Int, xo) + #xc = convert(Vector{Int}, xo) + #@test xc isa Vector{Int} + @test xr isa Vector{Int} + @test xr == xo + #@test xc == xo + # should not have allocated new memory + #@test pointer(xc) == pointer(xo) + @test pointer(xr) == pointer(xo) + + @test_throws ArgumentError reinterpret(Integer, xo) + + @testset "With non-target type values" begin + yo = U[1, 2, 3, corrupters(U)...] + #@test_throws ArgumentError convert(Vector{Int}, yo) + yr = reinterpret(Int, yo) + @test yr isa Vector{Int} + # No comment on what happens for the nonInt values, unspecified behavour + @test yr[1:3] == yo[1:3] + @test length(yo) == length(yr) + end + end + @testset "non-bits type ($U)" for U in unions(NotABitsType) + xo = U[NotABitsType(1), NotABitsType(2), NotABitsType(3)] + @test_throws ArgumentError reinterpret(Int, xo) + #xc = convert(Vector{NotABitsType}, x) + #@test xc isa Vector{Int} + #@test xc == xo + # should have allocated new memory + #@test pointer(xc) != pointer(xo) + end +end + @testset "promote rules" begin @test promote_type(Missing, Missing) == Missing @test promote_type(Missing, Int) == Union{Missing, Int} diff --git a/test/regex.jl b/test/regex.jl index 7fb5113a98cf2..0d76285060f53 100644 --- a/test/regex.jl +++ b/test/regex.jl @@ -136,24 +136,6 @@ @test r"this|that"^2 == r"(?:this|that){2}" end - @testset "iterate" begin - m = match(r"(.) test (.+)", "a test 123") - @test first(m) == "a" - @test collect(m) == ["a", "123"] - @test for (i, capture) in enumerate(m) - i == 1 && @test capture == "a" - i == 2 && @test capture == "123" - end - end - - @testset "Destructuring dispatch" begin - handle(::Nothing) = "not found" - handle((capture,)::RegexMatch) = "found $capture" - - @test handle(match(r"a (\d)", "xyz")) == "not found" - @test handle(match(r"a (\d)", "a 1")) == "found 1" - end - # Test that PCRE throws the correct kind of error # TODO: Uncomment this once the corresponding change has propagated to CI #@test_throws ErrorException Base.PCRE.info(C_NULL, Base.PCRE.INFO_NAMECOUNT, UInt32)