diff --git a/src/LazilyInitializedFields.jl b/src/LazilyInitializedFields.jl index 9cc0368..7b1f216 100644 --- a/src/LazilyInitializedFields.jl +++ b/src/LazilyInitializedFields.jl @@ -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 @@ -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 @@ -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) diff --git a/test/runtests.jl b/test/runtests.jl index 05a916d..046c033 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -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 @@ -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