Skip to content

Commit

Permalink
some stupid convert stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
KristofferC committed Oct 6, 2020
1 parent f62806b commit 6a77b22
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 3 deletions.
12 changes: 9 additions & 3 deletions src/LazilyInitializedFields.jl
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ Base.show(io::IO, b::Box) = show(io, b.x)


# This is a replication of the Nothing and Missing conversion functionality from Base.
# nonuninittype(::Type{T}) where {T} = Core.Compiler.typesubtract(T, Uninitialized)
if isdefined(Base, :typesplit)
nonuninittype(::Type{T}) where {T} = Base.typesplit(T, Uninitialized)
else
Expand All @@ -113,9 +112,16 @@ function nonuninittype_checked(T::Type)
return R
end

# These are awful
Base.convert(::Type{T}, x::T) where {T>:Uninitialized} = x
Base.convert(::Type{T}, x) where {T>:Uninitialized} = convert(nonuninittype_checked(T), x)
Base.convert(::Type{T}, x) where T>:Union{Uninitialized, Nothing} = convert(nonuninittype_checked(T), x)
Base.convert(::Type{T}, x) where T>:Union{Uninitialized, Missing} = convert(nonuninittype_checked(T), x)
Base.convert(::Type{T}, x) where T>:Union{Uninitialized, Missing, Nothing} = convert(nonuninittype_checked(T), x)
# Ambiguity resolution
Base.convert(::Type{T}, x::T) where T>:Union{LazilyInitializedFields.Uninitialized, Nothing} = x
Base.convert(::Type{T}, x::T) where T>:Union{LazilyInitializedFields.Uninitialized, Missing} = x
Base.convert(::Type{T}, x::T) where T>:Union{Nothing, Missing, LazilyInitializedFields.Uninitialized} = x


struct NonLazyFieldException <: Exception
Expand All @@ -134,8 +140,8 @@ end
Base.showerror(io::IO, err::UninitializedFieldException) =
print(io, "field `", err.s, "` in struct of type `$(err.T)` is not initialized")

@inline _setfield!(x, s::Symbol, v) = ismutable(x) ? setfield!(x, s, v) : getfield(x, s)[] = v
@inline _getfield(x, s::Symbol) = ismutable(x) ? getfield(x, s) : getfield(x, s)[]
@inline _setfield!(x, s::Symbol, v) = !isimmutable(x) ? setfield!(x, s, v) : getfield(x, s)[] = v
@inline _getfield(x, s::Symbol) = !isimmutable(x) ? getfield(x, s) : getfield(x, s)[]

"""
init!(a, s::Symbol)
Expand Down
27 changes: 27 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ end
end
box = Boxed(1, uninit)

@lazy struct Boxed
a::Int
@lazy b::Float64
end
box = Boxed(1, uninit)

@testset "Boxed" begin
@test isimmutable(box)
@test Boxed(1, 1).b === 1.0 # test conversion constructor
Expand All @@ -70,6 +76,27 @@ box = Boxed(1, uninit)
@test !(@isinit box.b)
end

@lazy struct BoxedUnion
a::Int
@lazy b::Union{Missing, Nothing, Int}
end
boxed_union = BoxedUnion(1, uninit)

@testset "Boxed" begin
@test isimmutable(box)
@test !(@isinit box.b)
if VERSION >= v"1.2"
@test BoxedUnion(1, 2.0).b === 2
else
@test_broken BoxedUnion(1, 2.0).b === 2
end
@init! box.b = 2
@test @isinit box.b
@test box.b == 2
@uninit! box.b
@test !(@isinit box.b)
end

@testset "misc" begin
@test_throws LoadError @macroexpand @lazy a::Int
@test_throws LoadError @macroexpand @lazy struct Bar end
Expand Down

0 comments on commit 6a77b22

Please sign in to comment.