From a7c4fd383852e5465988037f95ab438aae277857 Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Thu, 28 May 2020 15:55:03 +0200 Subject: [PATCH 01/29] fix #36031: Printf bug for BigInt (#36033) * fix #36031 * Apply suggestions from code review Co-authored-by: Simon Byrne (cherry picked from commit 150311f89d9e4bdb683d4bba397c822fabab272a) --- stdlib/Printf/src/Printf.jl | 23 ++++++++++++++--------- stdlib/Printf/test/runtests.jl | 5 ++--- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/stdlib/Printf/src/Printf.jl b/stdlib/Printf/src/Printf.jl index ee40edd32c8b8..ac4d3d4e7dff3 100644 --- a/stdlib/Printf/src/Printf.jl +++ b/stdlib/Printf/src/Printf.jl @@ -942,10 +942,12 @@ function decode_0ct(x::BigInt, digits) pt = Base.ndigits0z(x, 8) + 1 length(digits) < pt+1 && resize!(digits, pt+1) neg && (x.size = -x.size) - p = convert(Ptr{UInt8}, digits) + 1 - GMP.MPZ.get_str!(p, 8, x) + GC.@preserve digits begin + p = pointer(digits,2) + GMP.MPZ.get_str!(p, 8, x) + end neg && (x.size = -x.size) - return neg, Int32(pt), Int32(pt) + return Int32(pt), Int32(pt), neg end ### decoding functions directly used by printf generated code ### @@ -1059,13 +1061,16 @@ function ini_dec(x::BigInt, n::Int, digits) end d = Base.ndigits0z(x) if d <= n - info = decode_dec(x) - d == n && return info - p = convert(Ptr{Cvoid}, digits) + info[2] - ccall(:memset, Ptr{Cvoid}, (Ptr{Cvoid}, Cint, Csize_t), p, '0', n - info[2]) - return info + len,pt,neg = decode_dec(x, digits) + d == n && return (len,pt,neg) + + GC.@preserve digits begin + ccall(:memset, Ptr{Cvoid}, (Ptr{Cvoid}, Cint, Csize_t), pointer(digits, pt+1), '0', n - pt) + end + return (len,pt,neg) end - return (n, d, decode_dec(round(BigInt,x/big(10)^(d-n)))[3]) + _, _, neg = decode_dec(round(BigInt,x/big(10)^(d-n)), digits) + return (n, d, neg) end diff --git a/stdlib/Printf/test/runtests.jl b/stdlib/Printf/test/runtests.jl index e2b1e9ff4962d..562d478ef4676 100644 --- a/stdlib/Printf/test/runtests.jl +++ b/stdlib/Printf/test/runtests.jl @@ -39,11 +39,10 @@ for (fmt, val) in (("%i", "42"), ("%20a"," 0x2.ap+4"), ("%-20a","0x2.ap+4 "), ("%f", "42.000000"), - ("%g", "42")), + ("%g", "42"), + ("%e", "4.200000e+01")), num in (UInt16(42), UInt32(42), UInt64(42), UInt128(42), Int16(42), Int32(42), Int64(42), Int128(42), big"42") - #big"42" causes stack overflow on %a ; gh #14409 - num isa BigInt && fmt in ["%a", "%#o", "%g"] && continue @test @eval(@sprintf($fmt, $num) == $val) end From 91216bfdc96c51c343e9d9522f434407a32aec48 Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Thu, 28 May 2020 11:45:22 -0700 Subject: [PATCH 02/29] Update armv7l `-d16` -> `+d32` feature change for LLVM 9+ (cherry picked from commit 7e60e1bf13cc94c21a7088eb528ba46463c5d033) --- src/features_aarch32.h | 4 ++-- src/processor_arm.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/features_aarch32.h b/src/features_aarch32.h index 803d576c61548..d160ea7464c42 100644 --- a/src/features_aarch32.h +++ b/src/features_aarch32.h @@ -4,11 +4,11 @@ // hwcap JL_FEATURE_DEF(neon, 12, 0) JL_FEATURE_DEF(vfp3, 13, 0) -// JL_FEATURE_DEF(vfpv3d16, 14, 0) // d16 +// JL_FEATURE_DEF(vfpv3d16, 14, 0) // -d32 JL_FEATURE_DEF(vfp4, 16, 0) JL_FEATURE_DEF_NAME(hwdiv_arm, 17, 0, "hwdiv-arm") JL_FEATURE_DEF(hwdiv, 18, 0) -JL_FEATURE_DEF(d32, 19, 0) // -d16 +JL_FEATURE_DEF(d32, 19, 0) // hwcap2 JL_FEATURE_DEF(crypto, 32 + 0, 0) diff --git a/src/processor_arm.cpp b/src/processor_arm.cpp index 7b5fe0003bb56..5570d69455e2e 100644 --- a/src/processor_arm.cpp +++ b/src/processor_arm.cpp @@ -1220,7 +1220,7 @@ get_llvm_target_noext(const TargetData &data) const char *fename_str = fename.name; bool enable = test_nbit(features, fename.bit); bool disable = test_nbit(data.dis.features, fename.bit); -#ifdef _CPU_ARM_ +#if defined(_CPU_ARM_) && JL_LLVM_VERSION < 90000 if (fename.bit == Feature::d32) { if (enable) { feature_strs.push_back("-d16"); From 53f039332e2acc29b3f1d80066a2ffb9f1a608cb Mon Sep 17 00:00:00 2001 From: Jonas Witschel Date: Fri, 29 May 2020 03:05:15 +0000 Subject: [PATCH 03/29] LibGit2: add resolve_url to RemoteCallbacksStruct for LibGit2 0.99.0 (#35232) * LibGit2: amend GitError enum Since upstream commit https://github.com/libgit2/libgit2/commit/e9cef7c4b16b2cb572ac19fcd39217f7934cfa99 ("http: introduce GIT_ERROR_HTTP") an invalid content type yields a GIT_ERROR_HTTP instead of a GIT_ERROR_NET error. Update the enum to include this new error so that the unit test for LibGit2 doesn't fail with "invalid value for Enum Class: 34". * LibGit2: add resolve_url to RemoteCallbacksStruct for LibGit2 0.99.0 Upstream commit https://github.com/libgit2/libgit2/commit/59647e1ad095f80112918971b7bbe05adfaf8c3c ("remote: add callback to resolve URLs before connecting") introduced a new callback "resolve_url" in LibGit2 0.99.0. Even though it is not currently used in Julia, it needs to be accounted for to get the correct size for FetchOptionsStruct. An incorrectly aligned FetchOptionsStruct leads to error messages like "invalid version 0 on git_proxy_options" when trying to use the latest LibGit2 version. * LibGit2: update error message checking for LibGit2 0.99.0 Upstream commit https://github.com/libgit2/libgit2/commit/b9c5b15a7958ab4ecb83504a6d858efd18610297 ("http: use the new httpclient") changed the error message to include additional quotes. Relax the unit test to allow these if present. Co-authored-by: Milan Bouchet-Valat (cherry picked from commit 59a315cac72f048847b85e285ae19ef2dc9514c3) --- stdlib/LibGit2/src/error.jl | 7 ++++++- stdlib/LibGit2/src/types.jl | 3 +++ stdlib/LibGit2/test/libgit2.jl | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/stdlib/LibGit2/src/error.jl b/stdlib/LibGit2/src/error.jl index 4d1e915cef314..61eff41855ae4 100644 --- a/stdlib/LibGit2/src/error.jl +++ b/stdlib/LibGit2/src/error.jl @@ -58,7 +58,12 @@ export GitError Callback, CherryPick, Describe, - Rebase) + Rebase, + Filesystem, + Patch, + WorkTree, + SHA1, + HTTP) struct ErrorStruct message::Ptr{UInt8} diff --git a/stdlib/LibGit2/src/types.jl b/stdlib/LibGit2/src/types.jl index 6ffbe67ea2775..e00a0f161e79b 100644 --- a/stdlib/LibGit2/src/types.jl +++ b/stdlib/LibGit2/src/types.jl @@ -223,6 +223,9 @@ end push_negotiation::Ptr{Cvoid} = C_NULL transport::Ptr{Cvoid} = C_NULL payload::Ptr{Cvoid} = C_NULL + @static if LibGit2.VERSION >= v"0.99.0" + resolve_url::Ptr{Cvoid} = C_NULL + end end """ diff --git a/stdlib/LibGit2/test/libgit2.jl b/stdlib/LibGit2/test/libgit2.jl index 8f890ab0478ca..65b8f6b9e26c2 100644 --- a/stdlib/LibGit2/test/libgit2.jl +++ b/stdlib/LibGit2/test/libgit2.jl @@ -3048,7 +3048,7 @@ mktempdir() do dir deserialize(f) end @test err.code == LibGit2.Error.ERROR - @test lowercase(err.msg) == lowercase("invalid Content-Type: text/plain") + @test occursin(r"invalid content-type: '?text/plain'?"i, err.msg) end # OpenSSL s_server should still be running From 5e85387d8ead42ab2418b5cfff8fd6ddff2052f0 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Thu, 4 Jun 2020 14:54:56 +0200 Subject: [PATCH 04/29] update NEWS entry for popat! --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 6bbf77b67b9d7..58cdc37b4edee 100644 --- a/NEWS.md +++ b/NEWS.md @@ -116,6 +116,7 @@ New library functions * New function `contains(haystack, needle)` and its one argument partially applied form have been added, it acts like `occursin(needle, haystack)` ([#35132]). * New function `Base.exit_on_sigint` is added to control if `InterruptException` is thrown by Ctrl-C ([#29411]). +* New function `popat!(vector, index, [default])` for removing an element at an arbitrary index from a `Vector` ([#35513], [#36070]). New library features -------------------- @@ -128,7 +129,6 @@ New library features * `x::Signed % Unsigned` and `x::Unsigned % Signed` are supported for integer bitstypes. * `signed(unsigned_type)` is supported for integer bitstypes, `unsigned(signed_type)` has been supported. * `accumulate`, `cumsum`, and `cumprod` now support `Tuple` ([#34654]) and arbitrary iterators ([#34656]). -* `pop!(collection, key, [default])` now has a method for `Vector` to remove an element at an arbitrary index ([#35513]). * In `splice!` with no replacement, values to be removed can now be specified with an arbitrary iterable (instead of a `UnitRange`) ([#34524]). * The `@view` and `@views` macros now support the `a[begin]` syntax that was introduced in Julia 1.4 ([#35289]). From d01886d2d58abf52cefbb27dfb17b8dd6936bb52 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Mon, 1 Jun 2020 08:06:34 -0700 Subject: [PATCH 05/29] Fix a bug with break/continue/return in at-testset begin end (#36046) (cherry picked from commit 932a1ecbe92ebccf026d3bd4b5bc904390e28f9a) --- stdlib/Test/src/Test.jl | 6 ++++-- stdlib/Test/test/runtests.jl | 11 +++++++++++ stdlib/Test/test/test_pop_testset_exec.jl | 6 ++++++ 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 stdlib/Test/test/test_pop_testset_exec.jl diff --git a/stdlib/Test/src/Test.jl b/stdlib/Test/src/Test.jl index 3fb64bdff5bd3..2081425563780 100644 --- a/stdlib/Test/src/Test.jl +++ b/stdlib/Test/src/Test.jl @@ -1100,6 +1100,7 @@ function testset_beginend(args, tests, source) # action (such as reporting the results) ex = quote _check_testset($testsettype, $(QuoteNode(testsettype.args[1]))) + local ret local ts = $(testsettype)($desc; $options...) push_testset(ts) # we reproduce the logic of guardseed, but this function @@ -1120,9 +1121,10 @@ function testset_beginend(args, tests, source) record(ts, Error(:nontest_error, Expr(:tuple), err, Base.catch_stack(), $(QuoteNode(source)))) finally copy!(RNG, oldrng) + pop_testset() + ret = finish(ts) end - pop_testset() - finish(ts) + ret end # preserve outer location if possible if tests isa Expr && tests.head === :block && !isempty(tests.args) && tests.args[1] isa LineNumberNode diff --git a/stdlib/Test/test/runtests.jl b/stdlib/Test/test/runtests.jl index f3c0d4969ddfe..3307fd48e0d3c 100644 --- a/stdlib/Test/test/runtests.jl +++ b/stdlib/Test/test/runtests.jl @@ -919,3 +919,14 @@ end # Issue 20620 @test @inferred(.![true, false]) == [false, true] @test @inferred([3, 4] .- [1, 2] .+ [-2, -2]) == [0, 0] + +@testset "push/pop_testset invariance (Issue 32937)" begin + io = IOBuffer() + path = joinpath(@__DIR__(), "test_pop_testset_exec.jl") + cmd = `$(Base.julia_cmd()) $path` + ok = !success(pipeline(cmd; stdout = io, stderr = io)) + if !ok + @error "push/pop_testset invariance test failed" cmd Text(String(take!(io))) + end + @test ok +end diff --git a/stdlib/Test/test/test_pop_testset_exec.jl b/stdlib/Test/test/test_pop_testset_exec.jl new file mode 100644 index 0000000000000..3c5fde63f4ad4 --- /dev/null +++ b/stdlib/Test/test/test_pop_testset_exec.jl @@ -0,0 +1,6 @@ +using Test + +@testset begin + @test false + return +end From c7476afb9c816e8bdb76f506e7b5cafc9eea0c52 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 1 Jun 2020 14:58:40 -0400 Subject: [PATCH 06/29] clarify `show` doc strings (#36076) fixes #36072 (cherry picked from commit 147d5b101cea8c845b81c80943a8089bd59f5e1a) --- base/multimedia.jl | 18 ++++++++++-------- base/show.jl | 23 +++++++++++++++-------- doc/src/base/io-network.md | 4 ++-- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/base/multimedia.jl b/base/multimedia.jl index a50ea4690c994..4729849cfbc8d 100644 --- a/base/multimedia.jl +++ b/base/multimedia.jl @@ -77,7 +77,7 @@ showable(::MIME{mime}, @nospecialize x) where {mime} = hasmethod(show, Tuple{IO, showable(m::AbstractString, @nospecialize x) = showable(MIME(m), x) """ - show(io, mime, x) + show(io::IO, mime, x) The [`display`](@ref) functions ultimately call `show` in order to write an object `x` as a given `mime` type to a given I/O stream `io` (usually a memory buffer), if possible. In order @@ -94,18 +94,20 @@ your images to be displayed on any PNG-capable `AbstractDisplay` (such as IJulia to `import Base.show` in order to add new methods to the built-in Julia function `show`. -The default MIME type is `MIME"text/plain"`. There is a fallback definition for `text/plain` -output that calls `show` with 2 arguments. Therefore, this case should be handled by -defining a 2-argument `show(io::IO, x::MyType)` method. - Technically, the `MIME"mime"` macro defines a singleton type for the given `mime` string, which allows us to exploit Julia's dispatch mechanisms in determining how to display objects of any given type. -The first argument to `show` can be an [`IOContext`](@ref) specifying output format properties. -See [`IOContext`](@ref) for details. +The default MIME type is `MIME"text/plain"`. There is a fallback definition for `text/plain` +output that calls `show` with 2 arguments, so it is not always necessary to add a method +for that case. If a type benefits from custom human-readable output though, +`show(::IO, ::MIME"text/plain", ::T)` should be defined. For example, the `Day` type uses +`1 day` as the output for the `text/plain` MIME type, and `Day(1)` as the output of 2-argument `show`. + +Container types generally implement 3-argument `show` by calling `show(io, MIME"text/plain"(), x)` +for elements `x`, with `:compact => true` set in an [`IOContext`](@ref) passed as the first argument. """ -show(stream, mime, x) +show(stream::IO, mime, x) show(io::IO, m::AbstractString, x) = show(io, MIME(m), x) """ diff --git a/base/show.jl b/base/show.jl index 77adf0454894f..e0c52825ba61d 100644 --- a/base/show.jl +++ b/base/show.jl @@ -263,9 +263,9 @@ the properties of that stream (note that `io` can itself be an `IOContext`). The following properties are in common use: - - `:compact`: Boolean specifying that small values should be printed more compactly, e.g. + - `:compact`: Boolean specifying that values should be printed more compactly, e.g. that numbers should be printed with fewer digits. This is set when printing array - elements. + elements. `:compact` output should not contain line breaks. - `:limit`: Boolean specifying that containers should be truncated, e.g. showing `…` in place of most elements. - `:displaysize`: A `Tuple{Int,Int}` giving the size in rows and columns to use for text @@ -356,14 +356,21 @@ function show_circular(io::IOContext, @nospecialize(x)) end """ - show(x) + show([io::IO = stdout], x) -Write an informative text representation of a value to the current output stream. New types -should overload `show(io::IO, x)` where the first argument is a stream. The representation used -by `show` generally includes Julia-specific formatting and type information. +Write a text representation of a value `x` to the output stream `io`. New types `T` +should overload `show(io::IO, x::T)`. The representation used by `show` generally +includes Julia-specific formatting and type information, and should be parseable +Julia code when possible. [`repr`](@ref) returns the output of `show` as a string. +To customize human-readable text output for objects of type `T`, define +`show(io::IO, ::MIME"text/plain", ::T)` instead. Checking the `:compact` +[`IOContext`](@ref) property of `io` in such methods is recommended, +since some containers show their elements by calling this method with +`:compact => true`. + See also [`print`](@ref), which writes un-decorated representations. # Examples @@ -374,10 +381,10 @@ julia> print("Hello World!") Hello World! ``` """ -show(x) = show(stdout::IO, x) - show(io::IO, @nospecialize(x)) = show_default(io, x) +show(x) = show(stdout::IO, x) + # avoid inferring show_default on the type of `x` show_default(io::IO, @nospecialize(x)) = _show_default(io, inferencebarrier(x)) diff --git a/doc/src/base/io-network.md b/doc/src/base/io-network.md index adaa8e8b53856..101cdc890f9a9 100644 --- a/doc/src/base/io-network.md +++ b/doc/src/base/io-network.md @@ -55,7 +55,7 @@ Base.IOContext(::IO, ::IOContext) ## Text I/O ```@docs -Base.show(::Any) +Base.show(::IO, ::Any) Base.summary Base.print Base.println @@ -93,7 +93,7 @@ Base.AbstractDisplay Base.Multimedia.display Base.Multimedia.redisplay Base.Multimedia.displayable -Base.show(::Any, ::Any, ::Any) +Base.show(::IO, ::Any, ::Any) Base.Multimedia.showable Base.repr(::MIME, ::Any) Base.MIME From 99adb513b0391b1504c603de6415ab1091439c5b Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Tue, 2 Jun 2020 16:26:33 +0200 Subject: [PATCH 07/29] Revert "Use norm instead of abs in generic lu factorization (#34575)" (#36096) This reverts commit ecc0c434fae2438c05093b0fb1443b21c5463825. (cherry picked from commit be2c6430bd5ce1b80f8324fd23f3b4c6644ea7b3) --- stdlib/LinearAlgebra/src/lu.jl | 4 ++-- stdlib/LinearAlgebra/test/generic.jl | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/stdlib/LinearAlgebra/src/lu.jl b/stdlib/LinearAlgebra/src/lu.jl index 18ba0bbe11e6a..c770f478d4f4a 100644 --- a/stdlib/LinearAlgebra/src/lu.jl +++ b/stdlib/LinearAlgebra/src/lu.jl @@ -140,9 +140,9 @@ function generic_lufact!(A::StridedMatrix{T}, ::Val{Pivot} = Val(true); # find index max kp = k if Pivot - amax = norm(zero(T)) + amax = abs(zero(T)) for i = k:m - absi = norm(A[i,k]) + absi = abs(A[i,k]) if absi > amax kp = i amax = absi diff --git a/stdlib/LinearAlgebra/test/generic.jl b/stdlib/LinearAlgebra/test/generic.jl index de7eade6030b3..9ca508d9a9908 100644 --- a/stdlib/LinearAlgebra/test/generic.jl +++ b/stdlib/LinearAlgebra/test/generic.jl @@ -365,8 +365,6 @@ LinearAlgebra.Transpose(a::ModInt{n}) where {n} = transpose(a) # Needed for pivoting: Base.abs(a::ModInt{n}) where {n} = a - LinearAlgebra.norm(a::ModInt{n}) where {n} = a - Base.:<(a::ModInt{n}, b::ModInt{n}) where {n} = a.k < b.k @test A*(lu(A, Val(true))\b) == b From 3ccc9166f9107e424a1e46290b7087e73b39d9a6 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Tue, 2 Jun 2020 16:28:07 +0200 Subject: [PATCH 08/29] rename pop!(vector, idx, [default]) to popat! (#36070) * rename pop!(vector, idx, [default]) to popat! * popat! : explain what `default` is (cherry picked from commit 016410192516c56392be3653b44f7c82960ef769) --- base/array.jl | 35 +++++++++++++++++++++++++++++++++-- base/dict.jl | 3 --- base/exports.jl | 1 + doc/src/base/collections.md | 1 + test/arrayops.jl | 14 +++++++------- 5 files changed, 42 insertions(+), 12 deletions(-) diff --git a/base/array.jl b/base/array.jl index d52997bf7af53..8954f3e5b9d23 100644 --- a/base/array.jl +++ b/base/array.jl @@ -1153,13 +1153,44 @@ function pop!(a::Vector) return item end -function pop!(a::Vector, i::Integer) +""" + popat!(a::Vector, i::Integer, [default]) + +Remove the item at the given `i` and return it. Subsequent items +are shifted to fill the resulting gap. +When `i` is not a valid index for `a`, return `default`, or throw an error if +`default` is not specified. +See also [`deleteat!`](@ref) and [`splice!`](@ref). + +!!! compat "Julia 1.5" + This function is available as of Julia 1.5. + +# Examples +```jldoctest +julia> a = [4, 3, 2, 1]; popat!(a, 2) +3 + +julia> a +3-element Array{Int64,1}: + 4 + 2 + 1 + +julia> popat!(a, 4, missing) +missing + +julia> popat!(a, 4) +ERROR: BoundsError: attempt to access 3-element Array{Int64,1} at index [4] +[...] +``` +""" +function popat!(a::Vector, i::Integer) x = a[i] _deleteat!(a, i, 1) x end -function pop!(a::Vector, i::Integer, default) +function popat!(a::Vector, i::Integer, default) if 1 <= i <= length(a) x = @inbounds a[i] _deleteat!(a, i, 1) diff --git a/base/dict.jl b/base/dict.jl index 109538e70cf4f..cf6e380f4ca76 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -576,9 +576,6 @@ end Delete and return the mapping for `key` if it exists in `collection`, otherwise return `default`, or throw an error if `default` is not specified. -!!! compat "Julia 1.5" - For `collection::Vector`, this method requires at least Julia 1.5. - # Examples ```jldoctest julia> d = Dict("a"=>1, "b"=>2, "c"=>3); diff --git a/base/exports.jl b/base/exports.jl index 316025db9ce6c..fbd704eac95e4 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -472,6 +472,7 @@ export append!, insert!, pop!, + popat!, prepend!, push!, resize!, diff --git a/doc/src/base/collections.md b/doc/src/base/collections.md index fae621b302871..383dbcda4f93e 100644 --- a/doc/src/base/collections.md +++ b/doc/src/base/collections.md @@ -269,6 +269,7 @@ Partially implemented by: ```@docs Base.push! Base.pop! +Base.popat! Base.pushfirst! Base.popfirst! Base.insert! diff --git a/test/arrayops.jl b/test/arrayops.jl index 6e915f8c83e9c..9ecd9f4a0bab2 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -467,17 +467,17 @@ end @test_throws BoundsError insert!(v, 5, 5) end -@testset "pop!(::Vector, i, [default])" begin +@testset "popat!(::Vector, i, [default])" begin a = [1, 2, 3, 4] - @test_throws BoundsError pop!(a, 0) - @test pop!(a, 0, "default") == "default" + @test_throws BoundsError popat!(a, 0) + @test popat!(a, 0, "default") == "default" @test a == 1:4 - @test_throws BoundsError pop!(a, 5) - @test pop!(a, 1) == 1 + @test_throws BoundsError popat!(a, 5) + @test popat!(a, 1) == 1 @test a == [2, 3, 4] - @test pop!(a, 2) == 3 + @test popat!(a, 2) == 3 @test a == [2, 4] - badpop() = @inbounds pop!([1], 2) + badpop() = @inbounds popat!([1], 2) @test_throws BoundsError badpop() end From 88b689b10bd0d30cf9b2a78a61f5cfefd87bf91b Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Wed, 3 Jun 2020 08:08:09 -0500 Subject: [PATCH 09/29] fix #36116, diff(::AbstractRange) returns an Array (#36117) * fix #36116, diff(::AbstractRange) returns an Array (cherry picked from commit b49a0d5910635ff1297f9df5adf299804a908a4e) --- base/multidimensional.jl | 4 ++++ test/ranges.jl | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index c2417cdf095d5..e26ae13664f2b 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -848,6 +848,10 @@ function diff(a::AbstractArray{T,N}; dims::Integer) where {T,N} return view(a, r1...) .- view(a, r0...) end +function diff(r::AbstractRange{T}; dims::Integer=1) where {T} + dims == 1 || throw(ArgumentError("dimension $dims out of range (1:1)")) + return T[@inbounds r[i+1] - r[i] for i in firstindex(r):lastindex(r)-1] +end ### from abstractarray.jl diff --git a/test/ranges.jl b/test/ranges.jl index 77f925b5af337..0777323b9ed66 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -1607,6 +1607,16 @@ end @test collect(r) == ['a','c','e','g'] end +@testset "diff of ranges, #36116" begin + for r in (0:2, 0:1:2, 0.0:1.0:2.0, LinRange(0,2,3)) + @test diff(r) == diff(collect(r)) == fill(1, 2) + @test_throws ArgumentError diff(r, dims=2) + end + for r in (0:2:5, 0.1:0.1:2.0, LinRange(0,2,33)) + @test diff(r) == diff(collect(r)) == [r[i+1] - r[i] for i in 1:length(r)-1] + end +end + @testset "Return type of indexing with ranges" begin for T = (Base.OneTo{Int}, UnitRange{Int}, StepRange{Int,Int}, StepRangeLen{Int}, LinRange{Int}) @test eltype(T(1:5)) === eltype(T(1:5)[1:2]) From 539eab5e162b8052870b405a80065f075a8194cb Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 3 Jun 2020 12:00:03 -0400 Subject: [PATCH 10/29] fix #36108, printing invalid numeric juxtapositions (#36122) (cherry picked from commit 890f34cfdb9103cd5b64a3f009e9a0a2370c0e38) --- base/show.jl | 3 ++- test/show.jl | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/base/show.jl b/base/show.jl index e0c52825ba61d..a8bad7be8742e 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1338,7 +1338,8 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int, quote_level::In # scalar multiplication (i.e. "100x") elseif (func === :* && - length(func_args)==2 && isa(func_args[1], Real) && isa(func_args[2], Symbol)) + length(func_args) == 2 && isa(func_args[1], Union{Int, Int64, Float32, Float64}) && + isa(func_args[2], Symbol) && !in(string(func_args[2])[1], ('e', 'E', 'f'))) if func_prec <= prec show_enclosed_list(io, '(', func_args, "", ')', indent, func_prec, quote_level) else diff --git a/test/show.jl b/test/show.jl index ade7cb361f8d6..cd48ac5dd1888 100644 --- a/test/show.jl +++ b/test/show.jl @@ -138,6 +138,10 @@ end # basic expressions @test_repr "x + y" @test_repr "2e" +@test_repr "2*e1" +@test_repr "2*E1" +@test_repr "2*f1" +@test_repr "0x00*a" @test_repr "!x" @test_repr "f(1, 2, 3)" @test_repr "x = ~y" From 633046e65b764a6f922bdd667bff6097a1eafdb3 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Wed, 3 Jun 2020 15:53:47 -0700 Subject: [PATCH 11/29] Fix mkpath error handling (#36126) The error thrown by `mkdir` when the directory already exists was changed in #33422. (cherry picked from commit 912a8ed365f707e6104ce52c35a3dffa496a0868) --- base/file.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/file.jl b/base/file.jl index 9e91f433f2942..bb5a203a0e554 100644 --- a/base/file.jl +++ b/base/file.jl @@ -228,7 +228,7 @@ function mkpath(path::AbstractString; mode::Integer = 0o777) catch err # If there is a problem with making the directory, but the directory # does in fact exist, then ignore the error. Else re-throw it. - if !isa(err, SystemError) || !isdir(path) + if !isa(err, IOError) || !isdir(path) rethrow() end end From 360f5cc553835d4564d188decd3a17b8cd477040 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 4 Jun 2020 16:27:28 -0400 Subject: [PATCH 12/29] fix #36104, assign global name during type definitions (#36121) also fixes #21816 (cherry picked from commit 095e92d4e9ad2b90d525fec99f5474cd8d017b80) --- base/compiler/tfuncs.jl | 2 +- src/builtins.c | 57 ++++++++++++++++++++++++----------------- src/jltypes.c | 3 +++ src/julia-syntax.scm | 33 +++++++++++++++++++----- test/core.jl | 17 ++++++++++++ 5 files changed, 81 insertions(+), 31 deletions(-) diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index 5f5cc8cdb714b..ac72cf2559440 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -568,7 +568,7 @@ is_dt_const_field(fld::Int) = ( function const_datatype_getfield_tfunc(@nospecialize(sv), fld::Int) if fld == DATATYPE_INSTANCE_FIELDINDEX return isdefined(sv, fld) ? Const(getfield(sv, fld)) : Union{} - elseif is_dt_const_field(fld) + elseif is_dt_const_field(fld) && isdefined(sv, fld) return Const(getfield(sv, fld)) end return nothing diff --git a/src/builtins.c b/src/builtins.c index c89745c48ea93..5bb5fd098f855 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -1262,6 +1262,27 @@ JL_CALLABLE(jl_f__setsuper) void jl_reinstantiate_inner_types(jl_datatype_t *t); +static int equiv_field_types(jl_value_t *old, jl_value_t *ft) +{ + size_t nf = jl_svec_len(ft); + if (jl_svec_len(old) != nf) + return 0; + size_t i; + for (i = 0; i < nf; i++) { + jl_value_t *ta = jl_svecref(old, i); + jl_value_t *tb = jl_svecref(ft, i); + if (jl_has_free_typevars(ta)) { + if (!jl_has_free_typevars(tb) || !jl_egal(ta, tb)) + return 0; + } + else if (jl_has_free_typevars(tb) || jl_typeof(ta) != jl_typeof(tb) || + !jl_types_equal(ta, tb)) { + return 0; + } + } + return 1; +} + JL_CALLABLE(jl_f__typebody) { JL_NARGS(_typebody!, 1, 2); @@ -1270,16 +1291,23 @@ JL_CALLABLE(jl_f__typebody) if (nargs == 2) { jl_value_t *ft = args[1]; JL_TYPECHK(_typebody!, simplevector, ft); - dt->types = (jl_svec_t*)ft; - jl_gc_wb(dt, ft); - for (size_t i = 0; i < jl_svec_len(dt->types); i++) { - jl_value_t *elt = jl_svecref(dt->types, i); + size_t nf = jl_svec_len(ft); + for (size_t i = 0; i < nf; i++) { + jl_value_t *elt = jl_svecref(ft, i); if ((!jl_is_type(elt) && !jl_is_typevar(elt)) || jl_is_vararg_type(elt)) { jl_type_error_rt(jl_symbol_name(dt->name->name), "type definition", (jl_value_t*)jl_type_type, elt); } } + if (dt->types != NULL) { + if (!equiv_field_types((jl_value_t*)dt->types, ft)) + jl_errorf("invalid redefinition of type %s", jl_symbol_name(dt->name->name)); + } + else { + dt->types = (jl_svec_t*)ft; + jl_gc_wb(dt, ft); + } } JL_TRY { @@ -1306,15 +1334,13 @@ static int equiv_type(jl_value_t *ta, jl_value_t *tb) dta->name->name == dtb->name->name && dta->abstract == dtb->abstract && dta->mutabl == dtb->mutabl && - dta->size == dtb->size && + (jl_svec_len(jl_field_names(dta)) != 0 || dta->size == dtb->size) && dta->ninitialized == dtb->ninitialized && jl_egal((jl_value_t*)jl_field_names(dta), (jl_value_t*)jl_field_names(dtb)) && - jl_nparams(dta) == jl_nparams(dtb) && - jl_svec_len(dta->types) == jl_svec_len(dtb->types))) + jl_nparams(dta) == jl_nparams(dtb))) return 0; jl_value_t *a=NULL, *b=NULL; int ok = 1; - size_t i, nf = jl_svec_len(dta->types); JL_GC_PUSH2(&a, &b); a = jl_rewrap_unionall((jl_value_t*)dta->super, dta->name->wrapper); b = jl_rewrap_unionall((jl_value_t*)dtb->super, dtb->name->wrapper); @@ -1340,21 +1366,6 @@ static int equiv_type(jl_value_t *ta, jl_value_t *tb) a = jl_instantiate_unionall(ua, (jl_value_t*)ub->var); b = ub->body; } - assert(jl_is_datatype(a) && jl_is_datatype(b)); - a = (jl_value_t*)jl_get_fieldtypes((jl_datatype_t*)a); - b = (jl_value_t*)jl_get_fieldtypes((jl_datatype_t*)b); - for (i = 0; i < nf; i++) { - jl_value_t *ta = jl_svecref(a, i); - jl_value_t *tb = jl_svecref(b, i); - if (jl_has_free_typevars(ta)) { - if (!jl_has_free_typevars(tb) || !jl_egal(ta, tb)) - goto no; - } - else if (jl_has_free_typevars(tb) || jl_typeof(ta) != jl_typeof(tb) || - !jl_types_equal(ta, tb)) { - goto no; - } - } JL_GC_POP(); return 1; no: diff --git a/src/jltypes.c b/src/jltypes.c index ac2a60df9145c..4019aa814ef40 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -1631,6 +1631,9 @@ JL_DLLEXPORT jl_svec_t *jl_compute_fieldtypes(jl_datatype_t *st JL_PROPAGATES_RO assert(n > 0 && "expected empty case to be handled during construction"); //if (n == 0) // return ((st->types = jl_emptysvec)); + if (wt->types == NULL) + jl_errorf("cannot determine field types of incomplete type %s", + jl_symbol_name(st->name->name)); jl_typeenv_t *env = (jl_typeenv_t*)alloca(n * sizeof(jl_typeenv_t)); for (i = 0; i < n; i++) { env[i].var = (jl_tvar_t*)jl_svecref(wt->parameters, i); diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index ec1c5af9eca3d..1aad6281c4df0 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -878,7 +878,8 @@ (defs2 (if (null? defs) (default-inner-ctors name field-names field-types params bounds locs) defs)) - (min-initialized (min (ctors-min-initialized defs) (length fields)))) + (min-initialized (min (ctors-min-initialized defs) (length fields))) + (prev (make-ssavalue))) (let ((dups (has-dups field-names))) (if dups (error (string "duplicate field name: \"" (car dups) "\" is not unique")))) (for-each (lambda (v) @@ -892,16 +893,29 @@ (local-def ,name) ,@(map (lambda (v) `(local ,v)) params) ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v #t))) params bounds) - (toplevel-only struct) + (toplevel-only struct (outerref ,name)) (= ,name (call (core _structtype) (thismodule) (inert ,name) (call (core svec) ,@params) (call (core svec) ,@(map quotify field-names)) ,mut ,min-initialized)) (call (core _setsuper!) ,name ,super) - (call (core _typebody!) ,name (call (core svec) ,@field-types)) - (if (&& (isdefined (outerref ,name)) - (call (core _equiv_typedef) (outerref ,name) ,name)) - (null) + (if (isdefined (outerref ,name)) + (block + (= ,prev (outerref ,name)) + (if (call (core _equiv_typedef) ,prev ,name) + ;; if this is compatible with an old definition, use the existing type object + ;; and its parameters + (block (= ,name ,prev) + ,@(if (pair? params) + `((= (tuple ,@params) (|.| + ,(foldl (lambda (_ x) `(|.| ,x (quote body))) + prev + params) + (quote parameters)))) + '())) + ;; otherwise do an assignment to trigger an error + (= (outerref ,name) ,name))) (= (outerref ,name) ,name)) + (call (core _typebody!) ,name (call (core svec) ,@field-types)) (null))) ;; "inner" constructors (scope-block @@ -3345,7 +3359,12 @@ f(x) = yt(x) ((atom? e) e) (else (case (car e) - ((quote top core globalref outerref thismodule toplevel-only line break inert module toplevel null true false meta) e) + ((quote top core globalref outerref thismodule line break inert module toplevel null true false meta) e) + ((toplevel-only) + ;; hack to avoid generating a (method x) expr for struct types + (if (eq? (cadr e) 'struct) + (put! defined (caddr e) #t)) + e) ((=) (let ((var (cadr e)) (rhs (cl-convert (caddr e) fname lam namemap defined toplevel interp))) diff --git a/test/core.jl b/test/core.jl index 98344bfb44506..a44582beda567 100644 --- a/test/core.jl +++ b/test/core.jl @@ -7216,3 +7216,20 @@ struct AVL35416{K,V} avl:: Union{Nothing,Node35416{AVL35416{K,V},<:K,<:V}} end @test AVL35416(Node35416{AVL35416{Integer,AbstractString},Int,String}()) isa AVL35416{Integer,AbstractString} + +# issue #36104 +module M36104 +struct T36104 + v::Vector{M36104.T36104} +end +struct T36104 # check that redefining it works, issue #21816 + v::Vector{T36104} +end +end +@test fieldtypes(M36104.T36104) == (Vector{M36104.T36104},) +@test_throws ErrorException("expected") @eval(struct X36104; x::error("expected"); end) +@test @isdefined(X36104) +struct X36104; x::Int; end +@test fieldtypes(X36104) == (Int,) +primitive type P36104 8 end +@test_throws ErrorException("invalid redefinition of constant P36104") @eval(primitive type P36104 16 end) From fdd45476b4e9a037f183880ea54fc837d4727bd1 Mon Sep 17 00:00:00 2001 From: Sebastian Stock <42280794+sostock@users.noreply.github.com> Date: Thu, 4 Jun 2020 22:42:48 +0200 Subject: [PATCH 13/29] Fix zero(::Type{<:TwicePrecision}) for dimensionful quantities (#36113) (cherry picked from commit 38238c8de3858c000aff3d3b5bf404afbeccad6c) --- base/twiceprecision.jl | 5 ++++- test/ranges.jl | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/base/twiceprecision.jl b/base/twiceprecision.jl index 97cece5b99d72..4fac09068c97a 100644 --- a/base/twiceprecision.jl +++ b/base/twiceprecision.jl @@ -257,7 +257,10 @@ big(x::TwicePrecision) = big(x.hi) + big(x.lo) -(x::TwicePrecision) = TwicePrecision(-x.hi, -x.lo) -zero(::Type{TwicePrecision{T}}) where {T} = TwicePrecision{T}(0, 0) +function zero(::Type{TwicePrecision{T}}) where {T} + z = zero(T) + TwicePrecision{T}(z, z) +end # Arithmetic diff --git a/test/ranges.jl b/test/ranges.jl index 0777323b9ed66..66e1891e7fcab 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -193,6 +193,7 @@ end @test_throws ErrorException("Int is incommensurate with PhysQuantity") x*2 # not a MethodError for convert @test x.hi/2 === PhysQuantity{1}(2.0) @test_throws ErrorException("Int is incommensurate with PhysQuantity") x/2 + @test zero(typeof(x)) === Base.TwicePrecision(PhysQuantity{1}(0.0)) end @testset "ranges" begin @test size(10:1:0) == (0,) From 5c236b4f06523662769328d9d371b05be364251f Mon Sep 17 00:00:00 2001 From: Sebastian Stock <42280794+sostock@users.noreply.github.com> Date: Fri, 29 May 2020 16:43:43 +0200 Subject: [PATCH 14/29] Fix equality for one-element ranges (cherry picked from commit 73858763671d84d87c8007b6228ef67c0ff61d15) --- base/range.jl | 27 +++++++++++++++++++++------ test/ranges.jl | 4 +++- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/base/range.jl b/base/range.jl index f4af1cb055f72..24d9725df3493 100644 --- a/base/range.jl +++ b/base/range.jl @@ -742,14 +742,29 @@ show(io::IO, r::AbstractRange) = print(io, repr(first(r)), ':', repr(step(r)), ' show(io::IO, r::UnitRange) = print(io, repr(first(r)), ':', repr(last(r))) show(io::IO, r::OneTo) = print(io, "Base.OneTo(", r.stop, ")") -==(r::T, s::T) where {T<:AbstractRange} = - (isempty(r) & isempty(s)) | ((first(r) == first(s)) & (step(r) == step(s)) & (last(r) == last(s))) -==(r::OrdinalRange, s::OrdinalRange) = - (isempty(r) & isempty(s)) | ((first(r) == first(s)) & (step(r) == step(s)) & (last(r) == last(s))) +function ==(r::T, s::T) where {T<:AbstractRange} + isempty(r) && return isempty(s) + _has_length_one(r) && return _has_length_one(s) & (first(r) == first(s)) + (first(r) == first(s)) & (step(r) == step(s)) & (last(r) == last(s)) +end + +function ==(r::OrdinalRange, s::OrdinalRange) + isempty(r) && return isempty(s) + _has_length_one(r) && return _has_length_one(s) & (first(r) == first(s)) + (first(r) == first(s)) & (step(r) == step(s)) & (last(r) == last(s)) +end + ==(r::T, s::T) where {T<:Union{StepRangeLen,LinRange}} = (isempty(r) & isempty(s)) | ((first(r) == first(s)) & (length(r) == length(s)) & (last(r) == last(s))) -==(r::Union{StepRange{T},StepRangeLen{T,T}}, s::Union{StepRange{T},StepRangeLen{T,T}}) where {T} = - (isempty(r) & isempty(s)) | ((first(r) == first(s)) & (step(r) == step(s)) & (last(r) == last(s))) + +function ==(r::Union{StepRange{T},StepRangeLen{T,T}}, s::Union{StepRange{T},StepRangeLen{T,T}}) where {T} + isempty(r) && return isempty(s) + _has_length_one(r) && return _has_length_one(s) & (first(r) == first(s)) + (first(r) == first(s)) & (step(r) == step(s)) & (last(r) == last(s)) +end + +_has_length_one(r::OrdinalRange) = first(r) == last(r) +_has_length_one(r::AbstractRange) = isone(length(r)) function ==(r::AbstractRange, s::AbstractRange) lr = length(r) diff --git a/test/ranges.jl b/test/ranges.jl index 66e1891e7fcab..35f5cc5b6d8d9 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -820,7 +820,9 @@ end 0.0:0.1:1.0, map(Float32,0.0:0.1:1.0),map(Float32,LinRange(0.0, 1.0, 11)), 1.0:eps():1.0 .+ 10eps(), 9007199254740990.:1.0:9007199254740994, range(0, stop=1, length=20), map(Float32, range(0, stop=1, length=20)), - 3:2, 5:-2:7, range(0.0, step=2.0, length=0), 3//2:3//2:0//1, LinRange(2,3,0)] + 3:2, 5:-2:7, range(0.0, step=2.0, length=0), 3//2:3//2:0//1, LinRange(2,3,0), + Base.OneTo(1), 1:1, 1:-3:1, 1//1:1//3:1//1, range(1.0, step=2.5, length=1), + LinRange(1,1,1), LinRange(1,1,2)] for r in Rs local r ar = Vector(r) From 60bab00ea1440e6fafa9922b306b7d956ea0aede Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Thu, 4 Jun 2020 22:49:43 +0200 Subject: [PATCH 15/29] fix ImmutableDict(pairs...) constructor (#36143) It could only handle a couple of pairs, e.g. ImmutableDict(1=>1, 2=>2, 3=>3) would throw. The fix is implemented by adding the `ImmutableDict(t::ImmutableDict, pairs...)` constructor, which generalizes `ImmutableDict(t::ImmutableDict, pair)` (with some similarity to how `push!` accepts multiple items to be pushed). (cherry picked from commit 162cde194c2c303a69d3689f5992ff7df6358363) --- base/dict.jl | 2 ++ test/dict.jl | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/base/dict.jl b/base/dict.jl index cf6e380f4ca76..6a0f4ae6a4718 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -739,6 +739,8 @@ Create a new entry in the `ImmutableDict` for a `key => value` pair ImmutableDict ImmutableDict(KV::Pair{K,V}) where {K,V} = ImmutableDict{K,V}(KV[1], KV[2]) ImmutableDict(t::ImmutableDict{K,V}, KV::Pair) where {K,V} = ImmutableDict{K,V}(t, KV[1], KV[2]) +ImmutableDict(t::ImmutableDict{K,V}, KV::Pair, rest::Pair...) where {K,V} = + ImmutableDict(ImmutableDict(t, KV), rest...) ImmutableDict(KV::Pair, rest::Pair...) = ImmutableDict(ImmutableDict(KV), rest...) function in(key_value::Pair, dict::ImmutableDict, valcmp=(==)) diff --git a/test/dict.jl b/test/dict.jl index 5f2fc6aa0aef4..25a3bca3ee753 100644 --- a/test/dict.jl +++ b/test/dict.jl @@ -723,7 +723,9 @@ import Base.ImmutableDict d5 = ImmutableDict(v...) @test d5 == d2 @test reverse(collect(d5)) == v - @test ImmutableDict(:a => 1, :a => 2)[:a] == 2 + d6 = ImmutableDict(:a => 1, :b => 3, :a => 2) + @test d6[:a] == 2 + @test d6[:b] == 3 @test !haskey(ImmutableDict(-0.0=>1), 0.0) end From 2f8eb20812848bfa78c0d4d109a32ba170e1781c Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 2 Jun 2020 22:40:19 -0400 Subject: [PATCH 16/29] inference: ignore badly behaving generated functions (#36115) fix #36088 (cherry picked from commit 5d6a910260c6114565c1102cbc4a4ca34362189c) --- base/compiler/abstractinterpretation.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 2ec3d76f6cbfe..c9bdbe7dbc7d2 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -259,6 +259,7 @@ function abstract_call_method_with_const_args(@nospecialize(rettype), @nospecial if inf_result === nothing inf_result = InferenceResult(mi, argtypes) frame = InferenceState(inf_result, #=cache=#false, sv.params) + frame === nothing && return Any # this is probably a bad generated function (unsound), but just ignore it frame.limited = true frame.parent = sv push!(sv.params.cache, inf_result) From 62ea26d235a65dea3c31b9ef547119d8afb9b6ec Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Thu, 28 May 2020 14:33:14 +0200 Subject: [PATCH 17/29] Error when compiling invalid AddrSpacePtrs. (cherry picked from commit 968ccfc2409eeb7cdf1debf6e8061bfd2bb470f4) --- src/cgutils.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index d23bf9c20e7e6..57f4b623863ab 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -591,16 +591,14 @@ static Type *bitstype_to_llvm(jl_value_t *bt, bool llvmcall = false) if (bt == (jl_value_t*)jl_float64_type) return T_float64; if (jl_is_addrspace_ptr_type(bt)) { - int as = 0; - - jl_datatype_t *typ = (jl_datatype_t*)bt; - jl_value_t *as_param = jl_svecref(typ->parameters, 1); - + jl_value_t *as_param = jl_tparam1(bt); + int as; if (jl_is_int32(as_param)) as = jl_unbox_int32(as_param); else if (jl_is_int64(as_param)) as = jl_unbox_int64(as_param); - + else + jl_error("invalid pointer address space"); return PointerType::get(T_int8, as); } int nb = jl_datatype_size(bt); From cf26388cf561929386be261f1bb29cd4d5c906dc Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Thu, 28 May 2020 18:35:45 +0200 Subject: [PATCH 18/29] Rename AddrSpacePtr to LLVMPtr. (cherry picked from commit a6354d9898ea213dfec0085408eac7538c0708f3) --- base/refpointer.jl | 12 ++++++++---- src/builtins.c | 2 +- src/ccall.cpp | 2 +- src/cgutils.cpp | 2 +- src/jltypes.c | 12 ++++++------ src/julia.h | 9 +++++---- src/staticdata.c | 4 ++-- test/llvmpasses/llvmcall.jl | 2 +- 8 files changed, 25 insertions(+), 20 deletions(-) diff --git a/base/refpointer.jl b/base/refpointer.jl index 88e59ae6a3cc5..0a67a8bb240cf 100644 --- a/base/refpointer.jl +++ b/base/refpointer.jl @@ -144,9 +144,13 @@ setindex!(b::RefArray, x) = (b.x[b.i] = x; b) ### """ - AddrSpacePtr{T, AS} + LLVMPtr{T, AS} -When passed as a `ccall` argument with the `llvmcall` calling convention, an `AddrSpacePtr` will be converted to an LLVM pointer type with the correct address space. -This type is mainly used to ensure Julia's codegen uses the correct address space when calling LLVM intrinsics. +A pointer type that more closely resembles LLVM semantics: It includes the pointer address +space, and will be passed as an actual pointer instead of an integer. + +This type is mainly used to interface with code that has strict requirements about pointers, +e.g., intrinsics that are selected based on the address space, or back-ends that require +pointers to be identifiable by their types. """ -Core.AddrSpacePtr +Core.LLVMPtr diff --git a/src/builtins.c b/src/builtins.c index 5bb5fd098f855..f0bdb41ddb2ad 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -1581,7 +1581,7 @@ void jl_init_primitives(void) JL_GC_DISABLED add_builtin("CodeInfo", (jl_value_t*)jl_code_info_type); add_builtin("Ref", (jl_value_t*)jl_ref_type); add_builtin("Ptr", (jl_value_t*)jl_pointer_type); - add_builtin("AddrSpacePtr", (jl_value_t*)jl_addrspace_pointer_type); + add_builtin("LLVMPtr", (jl_value_t*)jl_llvmpointer_type); add_builtin("Task", (jl_value_t*)jl_task_type); add_builtin("AbstractArray", (jl_value_t*)jl_abstractarray_type); diff --git a/src/ccall.cpp b/src/ccall.cpp index d41876f3f0fa2..31cfedb9bd03c 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -1185,7 +1185,7 @@ std::string generate_func_sig(const char *fname) t = T_pint8; isboxed = false; } - else if (llvmcall && jl_is_addrspace_ptr_type(tti)) { + else if (llvmcall && jl_is_llvmpointer_type(tti)) { t = bitstype_to_llvm(tti, true); tti = (jl_value_t*)jl_voidpointer_type; isboxed = false; diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 57f4b623863ab..8cdaf9c5bd2f4 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -590,7 +590,7 @@ static Type *bitstype_to_llvm(jl_value_t *bt, bool llvmcall = false) return T_float32; if (bt == (jl_value_t*)jl_float64_type) return T_float64; - if (jl_is_addrspace_ptr_type(bt)) { + if (jl_is_llvmpointer_type(bt)) { jl_value_t *as_param = jl_tparam1(bt); int as; if (jl_is_int32(as_param)) diff --git a/src/jltypes.c b/src/jltypes.c index 4019aa814ef40..b0c536337c069 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -119,8 +119,8 @@ jl_datatype_t *jl_lineinfonode_type; jl_unionall_t *jl_ref_type; jl_unionall_t *jl_pointer_type; jl_typename_t *jl_pointer_typename; -jl_unionall_t *jl_addrspace_pointer_type; -jl_typename_t *jl_addrspace_pointer_typename; +jl_unionall_t *jl_llvmpointer_type; +jl_typename_t *jl_llvmpointer_typename; jl_datatype_t *jl_void_type; // deprecated jl_datatype_t *jl_nothing_type; jl_datatype_t *jl_voidpointer_type; @@ -2240,14 +2240,14 @@ void jl_init_types(void) JL_GC_DISABLED sizeof(void*)*8)->name->wrapper; jl_pointer_typename = ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_pointer_type))->name; - // AddrSpacePtr{T, AS} where {T, AS} + // LLVMPtr{T, AS} where {T, AS} tv = jl_svec2(tvar("T"), tvar("AS")); jl_svec_t *tv_base = jl_svec1(tvar("T")); - jl_addrspace_pointer_type = (jl_unionall_t*) - jl_new_primitivetype((jl_value_t*)jl_symbol("AddrSpacePtr"), core, + jl_llvmpointer_type = (jl_unionall_t*) + jl_new_primitivetype((jl_value_t*)jl_symbol("LLVMPtr"), core, (jl_datatype_t*)jl_apply_type((jl_value_t*)jl_ref_type, jl_svec_data(tv_base), 1), tv, sizeof(void*)*8)->name->wrapper; - jl_addrspace_pointer_typename = ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_addrspace_pointer_type))->name; + jl_llvmpointer_typename = ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_llvmpointer_type))->name; // Type{T} where T<:Tuple tttvar = jl_new_typevar(jl_symbol("T"), diff --git a/src/julia.h b/src/julia.h index a90aa6dc8b265..a7f3052e59fb3 100644 --- a/src/julia.h +++ b/src/julia.h @@ -635,10 +635,10 @@ extern JL_DLLEXPORT jl_datatype_t *jl_nothing_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_datatype_t *jl_signed_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_datatype_t *jl_voidpointer_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_unionall_t *jl_pointer_type JL_GLOBALLY_ROOTED; -extern JL_DLLEXPORT jl_unionall_t *jl_addrspace_pointer_type JL_GLOBALLY_ROOTED; +extern JL_DLLEXPORT jl_unionall_t *jl_llvmpointer_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_unionall_t *jl_ref_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_typename_t *jl_pointer_typename JL_GLOBALLY_ROOTED; -extern JL_DLLEXPORT jl_typename_t *jl_addrspace_pointer_typename JL_GLOBALLY_ROOTED; +extern JL_DLLEXPORT jl_typename_t *jl_llvmpointer_typename JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_typename_t *jl_namedtuple_typename JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_unionall_t *jl_namedtuple_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_datatype_t *jl_task_type JL_GLOBALLY_ROOTED; @@ -1088,6 +1088,7 @@ static inline int jl_is_layout_opaque(const jl_datatype_layout_t *l) JL_NOTSAFEP #define jl_is_string(v) jl_typeis(v,jl_string_type) #define jl_is_cpointer(v) jl_is_cpointer_type(jl_typeof(v)) #define jl_is_pointer(v) jl_is_cpointer_type(jl_typeof(v)) +#define jl_is_llvmpointer(v) jl_typeis(v,jl_llvmpointer_type) #define jl_is_intrinsic(v) jl_typeis(v,jl_intrinsic_type) #define jl_array_isbitsunion(a) (!(((jl_array_t*)(a))->flags.ptrarray) && jl_is_uniontype(jl_tparam0(jl_typeof(a)))) @@ -1152,10 +1153,10 @@ STATIC_INLINE int jl_is_cpointer_type(jl_value_t *t) JL_NOTSAFEPOINT ((jl_datatype_t*)(t))->name == ((jl_datatype_t*)jl_pointer_type->body)->name); } -STATIC_INLINE int jl_is_addrspace_ptr_type(jl_value_t *t) JL_NOTSAFEPOINT +STATIC_INLINE int jl_is_llvmpointer_type(jl_value_t *t) JL_NOTSAFEPOINT { return (jl_is_datatype(t) && - ((jl_datatype_t*)(t))->name == jl_addrspace_pointer_typename); + ((jl_datatype_t*)(t))->name == jl_llvmpointer_typename); } STATIC_INLINE int jl_is_abstract_ref_type(jl_value_t *t) JL_NOTSAFEPOINT diff --git a/src/staticdata.c b/src/staticdata.c index 6e09a26a47f04..440926d0876a7 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -41,7 +41,7 @@ static void *const _tags[] = { &jl_linenumbernode_type, &jl_lineinfonode_type, &jl_gotonode_type, &jl_quotenode_type, &jl_pinode_type, &jl_phinode_type, &jl_phicnode_type, &jl_upsilonnode_type, - &jl_type_type, &jl_bottom_type, &jl_ref_type, &jl_pointer_type, &jl_addrspace_pointer_type, + &jl_type_type, &jl_bottom_type, &jl_ref_type, &jl_pointer_type, &jl_llvmpointer_type, &jl_vararg_type, &jl_abstractarray_type, &jl_densearray_type, &jl_nothing_type, &jl_function_type, &jl_typeofbottom_type, &jl_unionall_type, &jl_typename_type, &jl_builtin_type, &jl_code_info_type, @@ -57,7 +57,7 @@ static void *const _tags[] = { &jl_float16_type, &jl_float32_type, &jl_float64_type, &jl_floatingpoint_type, &jl_number_type, &jl_signed_type, // special typenames - &jl_tuple_typename, &jl_pointer_typename, &jl_addrspace_pointer_typename, &jl_array_typename, &jl_type_typename, + &jl_tuple_typename, &jl_pointer_typename, &jl_llvmpointer_typename, &jl_array_typename, &jl_type_typename, &jl_vararg_typename, &jl_namedtuple_typename, &jl_vecelement_typename, // special exceptions diff --git a/test/llvmpasses/llvmcall.jl b/test/llvmpasses/llvmcall.jl index c00cbeb66b66a..c9cdf4db1fc38 100644 --- a/test/llvmpasses/llvmcall.jl +++ b/test/llvmpasses/llvmcall.jl @@ -23,7 +23,7 @@ emit(foo, NTuple{2, Float16}) emit(foo, NTuple{2, VecElement{Float16}}) # CHECK: call i8 addrspace(3)* @foo(i8 addrspace(3)* %{{[0-9]+}}) -emit(foo, Core.AddrSpacePtr{Float32, 3}) +emit(foo, Core.LLVMPtr{Float32, 3}) # CHECK: call { i32, i32 } @foo({ i32, i32 } %{{[0-9]+}}) emit(foo, Foo) From bf34e0a1241e3f36b283539cef734614af09498a Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Fri, 5 Jun 2020 01:04:34 +0200 Subject: [PATCH 19/29] Mark Tuples with Bottom among their parameters as cacheable (#36152) Fixes #36100. (cherry picked from commit 287215fc1816594d66624c0d79214eb986dd8cff) --- src/jltypes.c | 2 +- test/subtype.jl | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/jltypes.c b/src/jltypes.c index b0c536337c069..dbd21f873bb5d 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -1379,7 +1379,7 @@ static jl_tupletype_t *jl_apply_tuple_type_v_(jl_value_t **p, size_t np, jl_svec int cacheable = 1; for (size_t i = 0; i < np; i++) { assert(p[i]); - if (!jl_is_concrete_type(p[i])) + if (!jl_is_concrete_type(p[i]) && p[i] != jl_bottom_type) cacheable = 0; } return (jl_datatype_t*)inst_datatype_inner(jl_anytuple_type, params, p, np, cacheable, NULL, NULL); diff --git a/test/subtype.jl b/test/subtype.jl index 39bc4da86b08d..d528a2230fca9 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -1753,3 +1753,7 @@ s26065 = Ref{Tuple{T,Ref{Union{Ref{Tuple{Ref{Union{Ref{Ref{Tuple{Ref{Tuple{Union @test !issub(Tuple{Type{T}, T} where T<:Tuple{String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}}, Tuple{Type{Tuple{Vararg{V, N} where N}}, Tuple{Vararg{V, N} where N}} where V) + +# issue 36100 +@test NamedTuple{(:a, :b), Tuple{Missing, Union{}}} == NamedTuple{(:a, :b), Tuple{Missing, Union{}}} +@test Val{Tuple{Missing, Union{}}} === Val{Tuple{Missing, Union{}}} From e4b83af8cfc9583d33e76d385e9073832d462c22 Mon Sep 17 00:00:00 2001 From: KristofferC Date: Fri, 5 Jun 2020 15:31:21 +0200 Subject: [PATCH 20/29] bump Pkg version --- .../Pkg-e364c897b349d48372df4425cbb6f982a00b214d.tar.gz/md5 | 1 + .../Pkg-e364c897b349d48372df4425cbb6f982a00b214d.tar.gz/sha512 | 1 + .../Pkg-fff698d3d7d90a55431ad2f4fa0af9719d899954.tar.gz/md5 | 1 - .../Pkg-fff698d3d7d90a55431ad2f4fa0af9719d899954.tar.gz/sha512 | 1 - stdlib/Pkg.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 deps/checksums/Pkg-e364c897b349d48372df4425cbb6f982a00b214d.tar.gz/md5 create mode 100644 deps/checksums/Pkg-e364c897b349d48372df4425cbb6f982a00b214d.tar.gz/sha512 delete mode 100644 deps/checksums/Pkg-fff698d3d7d90a55431ad2f4fa0af9719d899954.tar.gz/md5 delete mode 100644 deps/checksums/Pkg-fff698d3d7d90a55431ad2f4fa0af9719d899954.tar.gz/sha512 diff --git a/deps/checksums/Pkg-e364c897b349d48372df4425cbb6f982a00b214d.tar.gz/md5 b/deps/checksums/Pkg-e364c897b349d48372df4425cbb6f982a00b214d.tar.gz/md5 new file mode 100644 index 0000000000000..2e73b619d19d5 --- /dev/null +++ b/deps/checksums/Pkg-e364c897b349d48372df4425cbb6f982a00b214d.tar.gz/md5 @@ -0,0 +1 @@ +afa660cd84edd7ed6ef7ebf71846320f diff --git a/deps/checksums/Pkg-e364c897b349d48372df4425cbb6f982a00b214d.tar.gz/sha512 b/deps/checksums/Pkg-e364c897b349d48372df4425cbb6f982a00b214d.tar.gz/sha512 new file mode 100644 index 0000000000000..08461f451f5a9 --- /dev/null +++ b/deps/checksums/Pkg-e364c897b349d48372df4425cbb6f982a00b214d.tar.gz/sha512 @@ -0,0 +1 @@ +6685c021761fd5bd656d88f404d34d95dab931d47bf3600debf09a19dc331a31beb6e39494aac7252aae37247c15c7666e10eb15564ac0ef2ab73bef8e80cee5 diff --git a/deps/checksums/Pkg-fff698d3d7d90a55431ad2f4fa0af9719d899954.tar.gz/md5 b/deps/checksums/Pkg-fff698d3d7d90a55431ad2f4fa0af9719d899954.tar.gz/md5 deleted file mode 100644 index a47a137bb59b5..0000000000000 --- a/deps/checksums/Pkg-fff698d3d7d90a55431ad2f4fa0af9719d899954.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -3ef6ca69b7cdef18228ccab2ce20d84f diff --git a/deps/checksums/Pkg-fff698d3d7d90a55431ad2f4fa0af9719d899954.tar.gz/sha512 b/deps/checksums/Pkg-fff698d3d7d90a55431ad2f4fa0af9719d899954.tar.gz/sha512 deleted file mode 100644 index d91c754e91496..0000000000000 --- a/deps/checksums/Pkg-fff698d3d7d90a55431ad2f4fa0af9719d899954.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -eb69f2f5abb8b9a3ec7abd52beff2286d7c2b3861b57459d63dc6783c28c64cb034c539d2b1b05f3bd696ae8adae32cc330b540ad111a06005879f00066a05b9 diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index cab9544700174..77217c8bd7f08 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,2 +1,2 @@ PKG_BRANCH = master -PKG_SHA1 = fff698d3d7d90a55431ad2f4fa0af9719d899954 +PKG_SHA1 = e364c897b349d48372df4425cbb6f982a00b214d From 3854131c82192ce45db13187e61f3314b75ddf23 Mon Sep 17 00:00:00 2001 From: KristofferC Date: Fri, 5 Jun 2020 15:32:09 +0200 Subject: [PATCH 21/29] bump Statistics version --- .../md5 | 1 - .../sha512 | 1 - .../md5 | 1 + .../sha512 | 1 + stdlib/Statistics.version | 3 ++- 5 files changed, 4 insertions(+), 3 deletions(-) delete mode 100644 deps/checksums/Statistics-42f46093985058665b085f24001882f3f33a400c.tar.gz/md5 delete mode 100644 deps/checksums/Statistics-42f46093985058665b085f24001882f3f33a400c.tar.gz/sha512 create mode 100644 deps/checksums/Statistics-cde87c8062032883165cd242f4a5c6b7943cb0b1.tar.gz/md5 create mode 100644 deps/checksums/Statistics-cde87c8062032883165cd242f4a5c6b7943cb0b1.tar.gz/sha512 diff --git a/deps/checksums/Statistics-42f46093985058665b085f24001882f3f33a400c.tar.gz/md5 b/deps/checksums/Statistics-42f46093985058665b085f24001882f3f33a400c.tar.gz/md5 deleted file mode 100644 index cf856f514f1fe..0000000000000 --- a/deps/checksums/Statistics-42f46093985058665b085f24001882f3f33a400c.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -14b820d6b0c164e36440329304dd8dbb diff --git a/deps/checksums/Statistics-42f46093985058665b085f24001882f3f33a400c.tar.gz/sha512 b/deps/checksums/Statistics-42f46093985058665b085f24001882f3f33a400c.tar.gz/sha512 deleted file mode 100644 index b7c828d720ff7..0000000000000 --- a/deps/checksums/Statistics-42f46093985058665b085f24001882f3f33a400c.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -7160582d061aeeed18d24fe8981a85e02086e2dbe3cda4f3786382351f1764117701a01d5f217b82d9263e0ac63f2caa2ce6ee5ad20dfc6e5cebba6af03b8826 diff --git a/deps/checksums/Statistics-cde87c8062032883165cd242f4a5c6b7943cb0b1.tar.gz/md5 b/deps/checksums/Statistics-cde87c8062032883165cd242f4a5c6b7943cb0b1.tar.gz/md5 new file mode 100644 index 0000000000000..a7f8d6e48bf8b --- /dev/null +++ b/deps/checksums/Statistics-cde87c8062032883165cd242f4a5c6b7943cb0b1.tar.gz/md5 @@ -0,0 +1 @@ +f038b99cd73f2ed8d132b88676b4ec64 diff --git a/deps/checksums/Statistics-cde87c8062032883165cd242f4a5c6b7943cb0b1.tar.gz/sha512 b/deps/checksums/Statistics-cde87c8062032883165cd242f4a5c6b7943cb0b1.tar.gz/sha512 new file mode 100644 index 0000000000000..3c6eb1a4a45cd --- /dev/null +++ b/deps/checksums/Statistics-cde87c8062032883165cd242f4a5c6b7943cb0b1.tar.gz/sha512 @@ -0,0 +1 @@ +7c3b7086e74e53465405c7130182c8016d894151a89f16af8037018aebde495cf599edfd631c7fc14faca5a5052c168b1f0373bc124bec3c0ac7851667689bcf diff --git a/stdlib/Statistics.version b/stdlib/Statistics.version index 7cfb1ca67170b..49937c2aa5c99 100644 --- a/stdlib/Statistics.version +++ b/stdlib/Statistics.version @@ -1,2 +1,3 @@ STATISTICS_BRANCH = master -STATISTICS_SHA1 = 42f46093985058665b085f24001882f3f33a400c +STATISTICS_SHA1 = cde87c8062032883165cd242f4a5c6b7943cb0b1 + From ea15599fde9be8e41982e10c123cd5db1339ffab Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Mon, 8 Jun 2020 16:27:09 -0700 Subject: [PATCH 22/29] Allow non-Function callables to be used in count(f, itr) (#36187) (cherry picked from commit a51015cd4e9f313fe1b72d75d306a6bcfdd7b0f4) --- base/reduce.jl | 2 +- test/reduce.jl | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/base/reduce.jl b/base/reduce.jl index 6d19fa50e3037..e772929787f5a 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -840,7 +840,7 @@ end ## count -_bool(f::Function) = x->f(x)::Bool +_bool(f) = x->f(x)::Bool """ count(p, itr) -> Integer diff --git a/test/reduce.jl b/test/reduce.jl index 9501f41f8b77c..03aada7d3f3c0 100644 --- a/test/reduce.jl +++ b/test/reduce.jl @@ -468,6 +468,11 @@ end @test count(!iszero, Int[1]) == 1 @test count(!iszero, [1, 0, 2, 0, 3, 0, 4]) == 4 +struct NonFunctionIsZero end +(::NonFunctionIsZero)(x) = iszero(x) +@test count(NonFunctionIsZero(), []) == 0 +@test count(NonFunctionIsZero(), [0]) == 1 +@test count(NonFunctionIsZero(), [1]) == 0 ## cumsum, cummin, cummax From 6c65ec84f939c272d005d1352f891a4af7336a5b Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Mon, 15 Jun 2020 18:34:40 +0200 Subject: [PATCH 23/29] fix #36272: Error with optional argument in anonymous function defined in macro (#36273) (cherry picked from commit 8d91b1123f4be3c03e587710fa8b0777762c5e07) --- src/macroexpand.scm | 7 +++++-- test/syntax.jl | 6 ++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/macroexpand.scm b/src/macroexpand.scm index 13d8cf4104e86..0777c9c61846e 100644 --- a/src/macroexpand.scm +++ b/src/macroexpand.scm @@ -210,7 +210,7 @@ ((atom? v) '()) (else (case (car v) - ((... kw |::|) (try-arg-name (cadr v))) + ((... kw |::| =) (try-arg-name (cadr v))) ((escape) (list v)) ((hygienic-scope) (try-arg-name (cadr v))) ((meta) ;; allow certain per-argument annotations @@ -275,6 +275,9 @@ ,@(map (lambda (x) (resolve-expansion-vars-with-new-env x env m parent-scope #t)) (cddr e)))) + ((tuple) `(tuple ,@(map (lambda (x) + (resolve-expansion-vars-with-new-env x env m parent-scope #t)) + (cdr e)))) (else (other e)))) (define (new-expansion-env-for x env (outermost #f)) @@ -367,7 +370,7 @@ (resolve-expansion-vars- x env m parent-scope #f))) (cdr e)))) - ((= function) + ((= function ->) (if (and (pair? (cadr e)) (function-def? e)) ;; in (kw x 1) inside an arglist, the x isn't actually a kwarg `(,(car e) ,(resolve-in-function-lhs (cadr e) env m parent-scope inarg) diff --git a/test/syntax.jl b/test/syntax.jl index 5000b71c718af..37edb1280a502 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -2276,3 +2276,9 @@ x = let var"'"(x) = 2x 3' end @test x == 6 + +# issue #36272 +macro m36272() + :((a, b=1) -> a*b) +end +@test @m36272()(1) == 1 From 8dec8f10bd76518ae0bdc84eded25ce76139221e Mon Sep 17 00:00:00 2001 From: Shan Sikdar Date: Mon, 8 Jun 2020 16:14:42 -0400 Subject: [PATCH 24/29] Fix Broadcasting of Bidiagonal (#35281) (cherry picked from commit 0e062e9a239bf1bb10135030afdc388ef25baf8d) --- .../LinearAlgebra/src/structuredbroadcast.jl | 20 ++++++--- .../LinearAlgebra/test/structuredbroadcast.jl | 45 +++++++++++++++++++ 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/stdlib/LinearAlgebra/src/structuredbroadcast.jl b/stdlib/LinearAlgebra/src/structuredbroadcast.jl index 3b5ba2475aeb1..a665e21731752 100644 --- a/stdlib/LinearAlgebra/src/structuredbroadcast.jl +++ b/stdlib/LinearAlgebra/src/structuredbroadcast.jl @@ -60,13 +60,21 @@ structured_broadcast_alloc(bc, ::Type{<:Diagonal}, ::Type{ElType}, n) where {ElT # Bidiagonal is tricky as we need to know if it's upper or lower. The promotion # system will return Tridiagonal when there's more than one Bidiagonal, but when # there's only one, we need to make figure out upper or lower -find_bidiagonal() = throw(ArgumentError("could not find Bidiagonal within broadcast expression")) -find_bidiagonal(a::Bidiagonal, rest...) = a -find_bidiagonal(bc::Broadcast.Broadcasted, rest...) = find_bidiagonal(find_bidiagonal(bc.args...), rest...) -find_bidiagonal(x, rest...) = find_bidiagonal(rest...) +merge_uplos(::Nothing, ::Nothing) = nothing +merge_uplos(a, ::Nothing) = a +merge_uplos(::Nothing, b) = b +merge_uplos(a, b) = a == b ? a : 'T' + +find_uplo(a::Bidiagonal) = a.uplo +find_uplo(a) = nothing +find_uplo(bc::Broadcasted) = mapreduce(find_uplo, merge_uplos, bc.args, init=nothing) + function structured_broadcast_alloc(bc, ::Type{<:Bidiagonal}, ::Type{ElType}, n) where {ElType} - ex = find_bidiagonal(bc) - return Bidiagonal(Array{ElType}(undef, n),Array{ElType}(undef, n-1), ex.uplo) + uplo = find_uplo(bc) + if uplo == 'T' + return Tridiagonal(Array{ElType}(undef, n-1), Array{ElType}(undef, n), Array{ElType}(undef, n-1)) + end + return Bidiagonal(Array{ElType}(undef, n),Array{ElType}(undef, n-1), uplo) end structured_broadcast_alloc(bc, ::Type{<:SymTridiagonal}, ::Type{ElType}, n) where {ElType} = SymTridiagonal(Array{ElType}(undef, n),Array{ElType}(undef, n-1)) diff --git a/stdlib/LinearAlgebra/test/structuredbroadcast.jl b/stdlib/LinearAlgebra/test/structuredbroadcast.jl index 72d304ac6da3b..b8f5e97311588 100644 --- a/stdlib/LinearAlgebra/test/structuredbroadcast.jl +++ b/stdlib/LinearAlgebra/test/structuredbroadcast.jl @@ -160,4 +160,49 @@ end @test L .+ UnitL .+ UnitU .+ U .+ D == L + UnitL + UnitU + U + D @test L .+ U .+ D .+ D .+ D .+ D == L + U + D + D + D + D end +@testset "Broadcast Returned Types" begin + # Issue 35245 + N = 3 + dV = rand(N) + evu = rand(N-1) + evl = rand(N-1) + + Bu = Bidiagonal(dV, evu, :U) + Bl = Bidiagonal(dV, evl, :L) + T = Tridiagonal(evl, dV * 2, evu) + + @test typeof(Bu .+ Bl) <: Tridiagonal + @test typeof(Bl .+ Bu) <: Tridiagonal + @test typeof(Bu .+ Bu) <: Bidiagonal + @test typeof(Bl .+ Bl) <: Bidiagonal + @test Bu .+ Bl == T + @test Bl .+ Bu == T + @test Bu .+ Bu == Bidiagonal(dV * 2, evu * 2, :U) + @test Bl .+ Bl == Bidiagonal(dV * 2, evl * 2, :L) + + + @test typeof(Bu .* Bl) <: Tridiagonal + @test typeof(Bl .* Bu) <: Tridiagonal + @test typeof(Bu .* Bu) <: Bidiagonal + @test typeof(Bl .* Bl) <: Bidiagonal + + @test Bu .* Bl == Tridiagonal(zeros(N-1), dV .* dV, zeros(N-1)) + @test Bl .* Bu == Tridiagonal(zeros(N-1), dV .* dV, zeros(N-1)) + @test Bu .* Bu == Bidiagonal(dV .* dV, evu .* evu, :U) + @test Bl .* Bl == Bidiagonal(dV .* dV, evl .* evl, :L) + + Bu2 = Bu .* 2 + @test typeof(Bu2) <: Bidiagonal && Bu2.uplo == 'U' + Bu2 = 2 .* Bu + @test typeof(Bu2) <: Bidiagonal && Bu2.uplo == 'U' + Bl2 = Bl .* 2 + @test typeof(Bl2) <: Bidiagonal && Bl2.uplo == 'L' + Bu2 = 2 .* Bl + @test typeof(Bl2) <: Bidiagonal && Bl2.uplo == 'L' + + # Example of Nested Brodacasts + tmp = (1 .* 2) .* (Bidiagonal(1:3, 1:2, 'U') .* (3 .* 4)) .* (5 .* Bidiagonal(1:3, 1:2, 'L')) + @test typeof(tmp) <: Tridiagonal + +end end From ee413108f89a5fd4576167ea1fa97ea851d63db4 Mon Sep 17 00:00:00 2001 From: Liozou Date: Tue, 16 Jun 2020 19:30:02 +0200 Subject: [PATCH 25/29] Promote on Rational binary operations (#36279) (cherry picked from commit 6c760d2f478ed7713ad6e6fb1c24f458da802137) --- base/rational.jl | 18 +++++++++--------- test/rational.jl | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/base/rational.jl b/base/rational.jl index 05b4a062d8711..0462554664fcc 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -61,16 +61,16 @@ julia> (3 // 5) // (2 // 1) //(n::Integer, d::Integer) = Rational(n,d) function //(x::Rational, y::Integer) - xn, yn = divgcd(x.num,y) + xn, yn = divgcd(promote(x.num, y)...) checked_den(xn, checked_mul(x.den, yn)) end function //(x::Integer, y::Rational) - xn, yn = divgcd(x,y.num) + xn, yn = divgcd(promote(x, y.num)...) checked_den(checked_mul(xn, y.den), yn) end function //(x::Rational, y::Rational) - xn,yn = divgcd(x.num,y.num) - xd,yd = divgcd(x.den,y.den) + xn,yn = divgcd(promote(x.num, y.num)...) + xd,yd = divgcd(promote(x.den, y.den)...) checked_den(checked_mul(xn, yd), checked_mul(xd, yn)) end @@ -280,7 +280,7 @@ end for (op,chop) in ((:+,:checked_add), (:-,:checked_sub), (:rem,:rem), (:mod,:mod)) @eval begin function ($op)(x::Rational, y::Rational) - xd, yd = divgcd(x.den, y.den) + xd, yd = divgcd(promote(x.den, y.den)...) Rational(($chop)(checked_mul(x.num,yd), checked_mul(y.num,xd)), checked_mul(x.den,yd)) end @@ -305,16 +305,16 @@ for (op,chop) in ((:rem,:rem), (:mod,:mod)) end function *(x::Rational, y::Rational) - xn, yd = divgcd(x.num, y.den) - xd, yn = divgcd(x.den, y.num) + xn, yd = divgcd(promote(x.num, y.den)...) + xd, yn = divgcd(promote(x.den, y.num)...) unsafe_rational(checked_mul(xn, yn), checked_mul(xd, yd)) end function *(x::Rational, y::Integer) - xd, yn = divgcd(x.den, y) + xd, yn = divgcd(promote(x.den, y)...) unsafe_rational(checked_mul(x.num, yn), xd) end function *(y::Integer, x::Rational) - yn, xd = divgcd(y, x.den) + yn, xd = divgcd(promote(y, x.den)...) unsafe_rational(checked_mul(yn, x.num), xd) end /(x::Rational, y::Union{Rational, Integer, Complex{<:Union{Integer,Rational}}}) = x//y diff --git a/test/rational.jl b/test/rational.jl index 4b2d48305660b..81a9ab16c5ff7 100644 --- a/test/rational.jl +++ b/test/rational.jl @@ -575,3 +575,22 @@ end @test -Int32(1) // typemax(Int32) - Int32(1) == typemin(Int32) // typemax(Int32) @test 1 // (typemax(Int128) + BigInt(1)) - 2 == (1 + BigInt(2)*typemin(Int128)) // (BigInt(1) + typemax(Int128)) end + +@testset "Promotions on binary operations with Rationals (#36277)" begin + inttypes = (Base.BitInteger_types..., BigInt) + for T in inttypes, S in inttypes + U = Rational{promote_type(T, S)} + @test typeof(one(Rational{T}) + one(S)) == typeof(one(S) + one(Rational{T})) == typeof(one(Rational{T}) + one(Rational{S})) == U + @test typeof(one(Rational{T}) - one(S)) == typeof(one(S) - one(Rational{T})) == typeof(one(Rational{T}) - one(Rational{S})) == U + @test typeof(one(Rational{T}) * one(S)) == typeof(one(S) * one(Rational{T})) == typeof(one(Rational{T}) * one(Rational{S})) == U + @test typeof(one(Rational{T}) // one(S)) == typeof(one(S) // one(Rational{T})) == typeof(one(Rational{T}) // one(Rational{S})) == U + end + @test (-40//3) // 0x5 == 0x5 // (-15//8) == -8//3 + @test (-4//7) // (0x1//0x3) == (0x4//0x7) // (-1//3) == -12//7 + @test -3//2 + 0x1//0x1 == -3//2 + 0x1 == 0x1//0x1 + (-3//2) == 0x1 + (-3//2) == -1//2 + @test 0x3//0x5 - 2//3 == 3//5 - 0x2//0x3 == -1//15 + @test rem(-12//5, 0x2//0x1) == rem(-12//5, 0x2) == -2//5 + @test mod(0x3//0x1, -4//7) == mod(0x3, -4//7) == -3//7 + @test -1//5 * 0x3//0x2 == 0x3//0x2 * -1//5 == -3//10 + @test -2//3 * 0x1 == 0x1 * -2//3 == -2//3 +end From 1cf4720ef76a83a1d93bdbe0cf0b4af3e206377b Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Tue, 16 Jun 2020 10:46:54 -0700 Subject: [PATCH 26/29] Remove `init` from `count!` docstring (#36305) (cherry picked from commit 33659c73c9c7d8d0636697a22377bbf8fd8368cf) --- base/reducedim.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/base/reducedim.jl b/base/reducedim.jl index d1e5001492fc4..75ba333211cf3 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -390,11 +390,10 @@ count(A::AbstractArrayOrBroadcasted; dims=:) = count(identity, A, dims=dims) count(f, A::AbstractArrayOrBroadcasted; dims=:) = mapreduce(_bool(f), add_sum, A, dims=dims, init=0) """ - count!([f=identity,] r, A; init=true) + count!([f=identity,] r, A) Count the number of elements in `A` for which `f` returns `true` over the singleton dimensions of `r`, writing the result into `r` in-place. -If `init` is `true`, values in `r` are initialized to zero. !!! compat "Julia 1.5" inplace `count!` was added in Julia 1.5. From e2cfc6f80b62a1b655f543d280ac5f8ca2b7ba95 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Tue, 16 Jun 2020 19:47:24 +0200 Subject: [PATCH 27/29] deleteat! : check bounds for the first passed index (#36231) * deleteat! : check bounds for the first passed index All other indices are bound-checked. Currently, the behavior looks like: ```julia julia> deleteat!([1:1000;], [-100]) signal (11): Segmentation fault [...] julia> deleteat!(BigInt[0], [0]) free(): invalid next size (normal) signal (6): Aborted [...] julia> deleteat!(BigInt[0], [-100]) ERROR: UndefRefError: access to undefined reference [...] julia> deleteat!([0], [0]) Int64[] julia> deleteat!([0], [2]) 1-element Array{Int64,1}: 0 julia> deleteat!([0], [3]) ERROR: InexactError: check_top_bit(UInt64, -1) [...] ``` With this commit, all these expressions throw a `BoundsError`. * Update base/array.jl Co-authored-by: Simeon Schaub Co-authored-by: Simeon Schaub (cherry picked from commit 6cdfcf9b48c0c4d4cd4022539ec7e5083df9e8e3) --- base/array.jl | 4 ++-- test/arrayops.jl | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/base/array.jl b/base/array.jl index 8954f3e5b9d23..bd6807853c93e 100644 --- a/base/array.jl +++ b/base/array.jl @@ -1352,9 +1352,9 @@ function _deleteat!(a::Vector, inds, dltd=Nowhere()) n = length(a) y = iterate(inds) y === nothing && return a - n == 0 && throw(BoundsError(a, inds)) (p, s) = y - p <= n && push!(dltd, @inbounds a[p]) + checkbounds(a, p) + push!(dltd, @inbounds a[p]) q = p+1 while true y = iterate(inds, s) diff --git a/test/arrayops.jl b/test/arrayops.jl index 9ecd9f4a0bab2..e8acde4c8826e 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -1446,11 +1446,15 @@ end @test deleteat!(a, [1,3,5,7:10...]) == [2,4,6] @test_throws BoundsError deleteat!(a, 13) @test_throws BoundsError deleteat!(a, [1,13]) - @test_throws ArgumentError deleteat!(a, [5,3]) + @test_throws ArgumentError deleteat!(a, [3,2]) # not sorted @test_throws BoundsError deleteat!(a, 5:20) @test_throws BoundsError deleteat!(a, Bool[]) @test_throws BoundsError deleteat!(a, [true]) @test_throws BoundsError deleteat!(a, falses(11)) + @test_throws BoundsError deleteat!(a, [0]) + @test_throws BoundsError deleteat!(a, [4]) + @test_throws BoundsError deleteat!(a, [5]) + @test_throws BoundsError deleteat!(a, [5, 3]) @test_throws BoundsError deleteat!([], 1) @test_throws BoundsError deleteat!([], [1]) From d3bc87f4623a57fe0b3c97a560d4a8a54845e307 Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Thu, 18 Jun 2020 01:33:53 -0700 Subject: [PATCH 28/29] Switch `httpbin` tests over to JuliaLang-hosted `httpbin` mock server (#36336) (cherry picked from commit 96fc2aa03b8f09619e737c17962990d97ec9cb62) --- test/download.jl | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/test/download.jl b/test/download.jl index 31b8217827476..3f56b04dc4e43 100644 --- a/test/download.jl +++ b/test/download.jl @@ -1,6 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -let urls = ["http://httpbin.org/ip", "https://httpbin.org/ip"] +# Test that `Base.download_url()` is altered by `Base.DOWNLOAD_HOOKS`. +let urls = ["http://httpbin.julialang.org/ip", "https://httpbin.julialang.org/ip"] for url in urls @test Base.download_url(url) == url end @@ -17,14 +18,14 @@ end mktempdir() do temp_dir # Download a file file = joinpath(temp_dir, "ip") - @test download("http://httpbin.org/ip", file) == file + @test download("https://httpbin.julialang.org/ip", file) == file @test isfile(file) @test !isempty(read(file)) ip = read(file, String) # Test download rewrite hook push!(Base.DOWNLOAD_HOOKS, url->replace(url, r"/status/404$" => "/ip")) - @test download("http://httpbin.org/status/404", file) == file + @test download("https://httpbin.julialang.org/status/404", file) == file @test isfile(file) @test !isempty(read(file)) @test ip == read(file, String) @@ -32,22 +33,24 @@ mktempdir() do temp_dir # Download an empty file empty_file = joinpath(temp_dir, "empty") - @test download("http://httpbin.org/status/200", empty_file) == empty_file + @test download("https://httpbin.julialang.org/status/200", empty_file) == empty_file # Windows and older versions of curl do not create the empty file (https://github.com/curl/curl/issues/183) @test !isfile(empty_file) || isempty(read(empty_file)) # Make sure that failed downloads do not leave files around missing_file = joinpath(temp_dir, "missing") - @test_throws ProcessFailedException download("http://httpbin.org/status/404", missing_file) + @test_throws ProcessFailedException download("https://httpbin.julialang.org/status/404", missing_file) @test !isfile(missing_file) - # Make sure we properly handle metachar ' - metachar_file = joinpath(temp_dir, "metachar") - download("https://httpbin.org/get?test='^'", metachar_file) - metachar_string = read(metachar_file, String) - m = match(r"\"url\"\s*:\s*\"(.*)\"", metachar_string) - @test m.captures[1] == "https://httpbin.org/get?test='^'" + # Make sure we properly handle metachar ' on windows with ^ escaping + if Sys.iswindows() + metachar_file = joinpath(temp_dir, "metachar") + Base.download_powershell("https://httpbin.julialang.org/get?test='^'", metachar_file) + metachar_string = read(metachar_file, String) + m = match(r"\"test\"\s*:\s*\"(.*)\"", metachar_string) + @test m.captures[1] == "'^'" + end # Use a TEST-NET (192.0.2.0/24) address which shouldn't be bound invalid_host_file = joinpath(temp_dir, "invalid_host") From 3e5174f6ea2ec3ed7e1c0db673d95ff9bdca9a29 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 26 May 2020 13:18:55 -0400 Subject: [PATCH 29/29] more precise inference of `splatnew` (#35976) This allows constant-folding NamedTuple constructors, in turn allowing constant prop through keyword arguments. (cherry picked from commit 7124472a3db233506fa580401e08bb2acad2ad5b) --- base/compiler/abstractinterpretation.jl | 11 +++++++++++ test/compiler/inference.jl | 13 +++++++++++++ 2 files changed, 24 insertions(+) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index c9bdbe7dbc7d2..2660e7362e2e3 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -1026,6 +1026,17 @@ function abstract_eval(@nospecialize(e), vtypes::VarTable, sv::InferenceState) end elseif e.head === :splatnew t = instanceof_tfunc(abstract_eval(e.args[1], vtypes, sv))[1] + if length(e.args) == 2 && isconcretetype(t) && !t.mutable + at = abstract_eval(e.args[2], vtypes, sv) + n = fieldcount(t) + if isa(at, Const) && isa(at.val, Tuple) && n == length(at.val) && + _all(i->at.val[i] isa fieldtype(t, i), 1:n) + t = Const(ccall(:jl_new_structt, Any, (Any, Any), t, at.val)) + elseif isa(at, PartialStruct) && at ⊑ Tuple && n == length(at.fields) && + _all(i->at.fields[i] ⊑ fieldtype(t, i), 1:n) + t = PartialStruct(t, at.fields) + end + end elseif e.head === :& abstract_eval(e.args[1], vtypes, sv) t = Any diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index fd2e6138e561d..84d8073fb450e 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -2586,3 +2586,16 @@ f() = _foldl_iter(step, (Missing[],), [0.0], 1) end @test Core.Compiler.typesubtract(Tuple{Union{Int,Char}}, Tuple{Char}) == Tuple{Int} @test Base.return_types(Issue35566.f) == [Val{:expected}] + +# constant prop through keyword arguments +_unstable_kw(;x=1,y=2) = x == 1 ? 0 : "" +_use_unstable_kw_1() = _unstable_kw(x = 2) +_use_unstable_kw_2() = _unstable_kw(x = 2, y = rand()) +@test Base.return_types(_use_unstable_kw_1) == Any[String] +@test Base.return_types(_use_unstable_kw_2) == Any[String] +@eval struct StructWithSplatNew + x::Int + StructWithSplatNew(t) = $(Expr(:splatnew, :StructWithSplatNew, :t)) +end +_construct_structwithsplatnew() = StructWithSplatNew(("",)) +@test Base.return_types(_construct_structwithsplatnew) == Any[StructWithSplatNew]