Skip to content

Commit

Permalink
Make reinterpretting Unions of nothings/missing and a bitstype work
Browse files Browse the repository at this point in the history
remove mistakenly included files

remove mistakenly included files
  • Loading branch information
oxinabox committed Jun 7, 2020
1 parent c1c6a17 commit da23ed5
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 25 deletions.
27 changes: 27 additions & 0 deletions base/missing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 3 additions & 7 deletions base/regex.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down
42 changes: 42 additions & 0 deletions test/missing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
18 changes: 0 additions & 18 deletions test/regex.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit da23ed5

Please sign in to comment.