diff --git a/README.md b/README.md index ed8743e34a678..1c616ea9d8108 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,8 @@ Currently, the `@compat` macro supports the following syntaxes: * `@compat @boundscheck checkbounds(...)` rewrites to unconditionally call `checkbounds(...)` in 0.4. The 0.4-style two-argument form of `@boundscheck` is left unchanged. +* `@compat Nullable(value, hasvalue)` to handle the switch from the `Nullable` `:isnull` field to `:hasvalue` field. [#18510](https://github.com/JuliaLang/julia/pull/18510) + ## Type Aliases * `String` has undergone multiple changes: in Julia 0.3 it was an abstract type and then got renamed to `AbstractString` in 0.4; in 0.5, `ASCIIString` and `ByteString` were deprecated, and `UTF8String` was renamed to the (now concrete) type `String`. @@ -83,6 +85,8 @@ Currently, the `@compat` macro supports the following syntaxes: * `redirect_stdout`, `redirect_stderr`, and `redirect_stdin` take an optional function as a first argument, `redirect_std*(f, stream)`, so that one may use `do` block syntax (as first available for Julia 0.6). +* `unsafe_get` returns the `:value` field of a `Nullable` object without any null-check and has a generic fallback for non-`Nullable` argument. [#18484](https://github.com/JuliaLang/julia/pull/18484) (Also, `isnull` has a generic fallback for non-`Nullable` argument.) + ## Renamed functions * `pointer_to_array` and `pointer_to_string` have been replaced with `unsafe_wrap(Array, ...)` and `unsafe_wrap(String, ...)` respectively. diff --git a/src/Compat.jl b/src/Compat.jl index 9224e03b8add8..897d4ce568cd2 100644 --- a/src/Compat.jl +++ b/src/Compat.jl @@ -613,6 +613,9 @@ function _compat(ex::Expr) elseif VERSION < v"0.5.0-dev+4340" && length(ex.args) > 3 && istopsymbol(withincurly(ex.args[1]), :Base, :show) ex = rewrite_show(ex) + elseif VERSION < v"0.6.0-dev.826" && length(ex.args) == 3 && # julia#18510 + istopsymbol(withincurly(ex.args[1]), :Base, :Nullable) + ex = Expr(:call, f, ex.args[2], Expr(:call, :(Compat._Nullable_field2), ex.args[3])) end if VERSION < v"0.5.0-dev+4305" rewrite_iocontext!(ex) @@ -1657,4 +1660,23 @@ if VERSION < v"0.5.0-dev+4677" Base.cholfact!(A::HermOrSym, T::Type) = cholfact!(A.data, Symbol(A.uplo), T) end +# julia#18510 +if VERSION < v"0.6.0-dev.826" + _Nullable_field2(x) = !x +else + _Nullable_field2(x) = x +end + +# julia#18484 +if VERSION < v"0.6.0-dev.848" + unsafe_get(x::Nullable) = x.value + unsafe_get(x) = x + export unsafe_get + if VERSION < v"0.4.0-dev+656" # so "nullable.jl" is included + isnull(x) = false + else + Base.isnull(x) = false + end +end + end # module diff --git a/test/runtests.jl b/test/runtests.jl index c38af9f6f84d9..93f475820ae0c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1455,3 +1455,55 @@ for A in (Hermitian(randn(5,5) + 10I), @test F[:U]'F[:U] ≈ A[F[:p], F[:p]] @test F[:L]*F[:L]' ≈ A[F[:p], F[:p]] end + +types = [ + Bool, + Float16, + Float32, + Float64, + Int128, + Int16, + Int32, + Int64, + Int8, + UInt16, + UInt32, + UInt64, + UInt8, +] +for T in types + # julia#18510, Nullable constructors + x = @compat Nullable(one(T), true) + @test isnull(x) === false + @test isa(x.value, T) + @test eltype(x) === T + + x = @compat Nullable{T}(one(T), true) + y = @compat Nullable{Any}(one(T), true) + @test isnull(x) === false + @test isnull(y) === false + @test isa(x.value, T) + @test eltype(x) === T + + x = @compat Nullable{T}(one(T), false) + y = @compat Nullable{Any}(one(T), false) + @test isnull(x) === true + @test isnull(y) === true + @test eltype(x) === T + + x = @compat Nullable(one(T), false) + @test isnull(x) === true + @test eltype(x) === T + + x = @compat Nullable{T}() + @test isnull(x) === true + @test eltype(x) === T + + # julia#18484, generic isnull, unsafe_get + a = one(T) + x = @compat Nullable(a, true) + @test isequal(unsafe_get(x), a) + + x = @compat Nullable{Array{T}}() + @test_throws UndefRefError unsafe_get(x) +end