From d40a6b1f963ea8b6f35dc43d71565262eaa81da3 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Fri, 10 Aug 2018 15:39:03 +0100 Subject: [PATCH 001/166] Documentation introduction fixed for 1.0 (#28548) (cherry picked from commit 53d2e7c7f26142d534552957cb40758a2e73242e) --- doc/make.jl | 14 +++++++------- doc/src/index.md | 10 +++++++--- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/doc/make.jl b/doc/make.jl index b2b3107949103..466d4705814af 100644 --- a/doc/make.jl +++ b/doc/make.jl @@ -40,16 +40,16 @@ cd(joinpath(@__DIR__, "src")) do end end -# Generate a suitable markdown file from NEWS.md and put it in src -str = read(joinpath(@__DIR__, "..", "NEWS.md"), String) -splitted = split(str, "") -@assert length(splitted) == 2 -replaced_links = replace(splitted[1], r"\[\#([0-9]*?)\]" => s"[#\g<1>](https://github.com/JuliaLang/julia/issues/\g<1>)") -write(joinpath(@__DIR__, "src", "NEWS.md"), replaced_links) +# # Generate a suitable markdown file from NEWS.md and put it in src +# str = read(joinpath(@__DIR__, "..", "NEWS.md"), String) +# splitted = split(str, "") +# @assert length(splitted) == 2 +# replaced_links = replace(splitted[1], r"\[\#([0-9]*?)\]" => s"[#\g<1>](https://github.com/JuliaLang/julia/issues/\g<1>)") +# write(joinpath(@__DIR__, "src", "NEWS.md"), replaced_links) const PAGES = [ "Home" => "index.md", - hide("NEWS.md"), + # hide("NEWS.md"), "Manual" => [ "manual/getting-started.md", "manual/variables.md", diff --git a/doc/src/index.md b/doc/src/index.md index c7420bce1656a..855e45db671f1 100644 --- a/doc/src/index.md +++ b/doc/src/index.md @@ -1,8 +1,12 @@ -# Julia 0.7 Documentation +# Julia 1.0 Documentation -Welcome to the documentation for Julia 0.7. +Welcome to the documentation for Julia 1.0. -Please read the [release notes](NEWS.md) to see what has changed since the last release. +Please read the [release blog post](https://julialang.org/blog/2018/08/one-point-zero) for a general overview of the language and +many of the changes since Julia v0.6. Note that version 0.7 was released alongside +1.0 to provide an upgrade path for packages and code that predates the 1.0 release. +The only difference between 0.7 and 1.0 is the removal of deprecation warnings. +For a complete list of all the changes since 0.6, see the [release notes for version 0.7](https://docs.julialang.org/en/v0.7.0/NEWS/) ### [Introduction](@id man-introduction) From 4e1178c77e06b24ab31380e7d4f18a808e31dc66 Mon Sep 17 00:00:00 2001 From: Harrison Grodin Date: Sat, 11 Aug 2018 11:43:52 +0100 Subject: [PATCH 002/166] Autogenerate documented REPL banner (#28520) * Update documented REPL banner for 1.0 (cherry picked from commit 7c9383fc989c644c2bf6c5d09d7c3d97e7269190) --- stdlib/REPL/docs/src/index.md | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/stdlib/REPL/docs/src/index.md b/stdlib/REPL/docs/src/index.md index 42348a1eae06a..0920ab36549c3 100644 --- a/stdlib/REPL/docs/src/index.md +++ b/stdlib/REPL/docs/src/index.md @@ -6,18 +6,12 @@ it has a searchable history, tab-completion, many helpful keybindings, and dedic shell modes. The REPL can be started by simply calling `julia` with no arguments or double-clicking on the executable: -``` -$ julia - _ - _ _ _(_)_ | A fresh approach to technical computing - (_) | (_) (_) | Documentation: https://docs.julialang.org - _ _ _| |_ __ _ | Type "?help" for help. - | | | | | | |/ _` | | - | | |_| | | | (_| | | Version 0.6.0-dev.2493 (2017-01-31 18:53 UTC) - _/ |\__'_|_|_|\__'_| | Commit c99e12c* (0 days old master) -|__/ | x86_64-linux-gnu - -julia> +```@eval +io = IOBuffer() +Base.banner(io) +banner = String(take!(io)) +import Markdown +Markdown.parse("```\n\$ julia\n\n$(banner)\njulia>\n```") ``` To exit the interactive session, type `^D` -- the control key together with the `d` key on a blank From 44dedda3c44d6c920bf2bd1a4e4950488cfaeb9a Mon Sep 17 00:00:00 2001 From: anderson15 <4404456+anderson15@users.noreply.github.com> Date: Sat, 11 Aug 2018 11:24:00 -0400 Subject: [PATCH 003/166] update link to ConEmu terminal (#28578) (cherry picked from commit 7cb8531a2bc1d03663d4f0e6829c3ead33cb616d) --- README.windows.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.windows.md b/README.windows.md index 76056b69959ed..a13c1ba5a86b0 100644 --- a/README.windows.md +++ b/README.windows.md @@ -23,7 +23,7 @@ Instructions for adding fonts to the terminal are available at Additionally, rather than sticking with the default command prompt, you may want to use a different terminal emulator program, such as -[Conemu](https://code.google.com/p/conemu-maximus5/) or [Mintty]( +[Conemu](https://conemu.github.io/) or [Mintty]( https://github.com/mintty/mintty) (note that running Julia on Mintty needs a copy of `stty.exe` in your `%PATH%` to work properly). Alternatively, you may prefer the features of a more full-function IDE, such as [Juno](http://junolab.org), From c4c4199f962c3f05bc51a6382829eaa22a3b5b84 Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Sun, 12 Aug 2018 08:44:47 +0100 Subject: [PATCH 004/166] Fix vec of adjoint vector (#28568) (cherry picked from commit 04f4884873c9a91ac506d422638b34f050897c7e) --- stdlib/LinearAlgebra/src/adjtrans.jl | 2 +- stdlib/LinearAlgebra/test/adjtrans.jl | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/stdlib/LinearAlgebra/src/adjtrans.jl b/stdlib/LinearAlgebra/src/adjtrans.jl index f75c42117ec8e..208c2f884c563 100644 --- a/stdlib/LinearAlgebra/src/adjtrans.jl +++ b/stdlib/LinearAlgebra/src/adjtrans.jl @@ -150,7 +150,7 @@ similar(A::AdjOrTrans, ::Type{T}, dims::Dims{N}) where {T,N} = similar(A.parent, # sundry basic definitions parent(A::AdjOrTrans) = A.parent -vec(v::AdjOrTransAbsVec) = v.parent +vec(v::TransposeAbsVec) = parent(v) cmp(A::AdjOrTransAbsVec, B::AdjOrTransAbsVec) = cmp(parent(A), parent(B)) isless(A::AdjOrTransAbsVec, B::AdjOrTransAbsVec) = isless(parent(A), parent(B)) diff --git a/stdlib/LinearAlgebra/test/adjtrans.jl b/stdlib/LinearAlgebra/test/adjtrans.jl index 5abba308fcec0..ba3faac50374d 100644 --- a/stdlib/LinearAlgebra/test/adjtrans.jl +++ b/stdlib/LinearAlgebra/test/adjtrans.jl @@ -271,8 +271,10 @@ end @testset "Adjoint and Transpose vector vec methods" begin intvec = [1, 2] - @test vec(Adjoint(intvec)) === intvec + @test vec(Adjoint(intvec)) == intvec @test vec(Transpose(intvec)) === intvec + cvec = [1 + 1im] + @test vec(cvec')[1] == cvec[1]' end @testset "horizontal concatenation of Adjoint/Transpose-wrapped vectors and Numbers" begin From 7da396b7faac1b8b98013c7aa4d4341564bdbdd9 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 11 Aug 2018 12:56:41 +0100 Subject: [PATCH 005/166] fix #28576, parsing `?` at end of input in conditional expression (cherry picked from commit d7e45841de3101283af91ac744e7e0c7b10c1608) --- src/julia-parser.scm | 4 ++-- test/syntax.jl | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/julia-parser.scm b/src/julia-parser.scm index e319d9cc3ecca..9d832894f9bb1 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -779,7 +779,7 @@ (begin (if (not (ts:space? s)) (error "space required before \"?\" operator")) (take-token s) ; take the ? - (let ((t (with-whitespace-newline (without-range-colon (peek-token s))))) + (let ((t (with-whitespace-newline (without-range-colon (require-token s))))) (if (not (ts:space? s)) (error "space required after \"?\" operator"))) (let ((then (without-range-colon (parse-eq* s)))) @@ -788,7 +788,7 @@ (if (not (ts:space? s)) (error "space required before colon in \"?\" expression")) (take-token s) ; take the : - (let ((t (with-whitespace-newline (peek-token s)))) + (let ((t (with-whitespace-newline (require-token s)))) (if (not (ts:space? s)) (error "space required after colon in \"?\" expression"))) (list 'if ex then (parse-eq* s))))) diff --git a/test/syntax.jl b/test/syntax.jl index 935c7ce58add5..4e4417dd5a3b6 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -1642,3 +1642,7 @@ end for ex in [:([x=1]), :(T{x=1})] @test Meta.lower(@__MODULE__, ex) == Expr(:error, string("misplaced assignment statement in \"", ex, "\"")) end + +# issue #28576 +@test Meta.isexpr(Meta.parse("1 == 2 ?"), :incomplete) +@test Meta.isexpr(Meta.parse("1 == 2 ? 3 :"), :incomplete) From 3ba7d6610f9e2fd81d28bc7b703435846110f2f6 Mon Sep 17 00:00:00 2001 From: Jim Garrison Date: Mon, 13 Aug 2018 03:04:42 -0400 Subject: [PATCH 006/166] Fix #28619, logabsdet for singular matrices (#28620) (cherry picked from commit 0846eb56548a52f07998f5ee354562fbff85a8f7) --- stdlib/LinearAlgebra/src/generic.jl | 2 +- stdlib/LinearAlgebra/test/generic.jl | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/generic.jl b/stdlib/LinearAlgebra/src/generic.jl index ac55b9ed696ae..ea23e8d51cee7 100644 --- a/stdlib/LinearAlgebra/src/generic.jl +++ b/stdlib/LinearAlgebra/src/generic.jl @@ -1274,7 +1274,7 @@ julia> logabsdet(B) (0.6931471805599453, 1.0) ``` """ -logabsdet(A::AbstractMatrix) = logabsdet(lu(A)) +logabsdet(A::AbstractMatrix) = logabsdet(lu(A, check=false)) """ logdet(M) diff --git a/stdlib/LinearAlgebra/test/generic.jl b/stdlib/LinearAlgebra/test/generic.jl index 1c38883356efb..13d18e1d29b23 100644 --- a/stdlib/LinearAlgebra/test/generic.jl +++ b/stdlib/LinearAlgebra/test/generic.jl @@ -80,6 +80,8 @@ n = 5 # should be odd @test logdet(A) ≈ log(det(A)) @test logabsdet(A)[1] ≈ log(abs(det(A))) @test logabsdet(Matrix{elty}(-I, n, n))[2] == -1 + infinity = convert(float(elty), Inf) + @test logabsdet(zeros(elty, n, n)) == (-infinity, zero(elty)) if elty <: Real @test logabsdet(A)[2] == sign(det(A)) @test_throws DomainError logdet(Matrix{elty}(-I, n, n)) From 5cc92a76865fd2be6c11a1535477f8858be3fb62 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Mon, 13 Aug 2018 09:16:08 -0400 Subject: [PATCH 007/166] Doc IndexLinear and IndexCartesian (#28476) * Doc IndexLinear and IndexCartesian (cherry picked from commit d15b0912fe092e3256fc03e48e5ecea1bce7b33a) --- base/cartesian.jl | 2 +- base/indices.jl | 33 +++++++++++++++++++++++++++++---- base/iterators.jl | 6 +++--- doc/src/base/arrays.md | 2 ++ 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/base/cartesian.jl b/base/cartesian.jl index 526cff67bd706..865b766664708 100644 --- a/base/cartesian.jl +++ b/base/cartesian.jl @@ -32,7 +32,7 @@ would generate: end end -If you want just a post-expression, supply `nothing` for the pre-expression. Using +If you want just a post-expression, supply [`nothing`](@ref) for the pre-expression. Using parentheses and semicolons, you can supply multi-statement expressions. """ macro nloops(N, itersym, rangeexpr, args...) diff --git a/base/indices.jl b/base/indices.jl index adec164f080b5..800280c90f57e 100644 --- a/base/indices.jl +++ b/base/indices.jl @@ -13,7 +13,32 @@ Indices{N} = NTuple{N,AbstractUnitRange} ## Traits for array types ## abstract type IndexStyle end +""" + IndexLinear() + +Subtype of [`IndexStyle`](@ref) used to describe arrays which +are optimally indexed by one linear index. + +A linear indexing style uses one integer to describe the position in the array +(even if it's a multidimensional array) and column-major +ordering is used to access the elements. For example, +if `A` were a `(2, 3)` custom matrix type with linear indexing, +and we referenced `A[5]` (using linear style), this would +be equivalent to referencing `A[1, 3]` (since `2*1 + 3 = 5`). +See also [`IndexCartesian`](@ref). +""" struct IndexLinear <: IndexStyle end +""" + IndexCartesian() + +Subtype of [`IndexStyle`](@ref) used to describe arrays which +are optimally indexed by a Cartesian index. + +A cartesian indexing style uses multiple integers/indices to describe the position in the array. +For example, if `A` were a `(2, 3, 4)` custom matrix type with cartesian indexing, +we could reference `A[2, 1, 3]` and Julia would automatically convert this into the +correct location in the underlying memory. See also [`IndexLinear`](@ref). +""" struct IndexCartesian <: IndexStyle end """ @@ -21,14 +46,14 @@ struct IndexCartesian <: IndexStyle end IndexStyle(typeof(A)) `IndexStyle` specifies the "native indexing style" for array `A`. When -you define a new `AbstractArray` type, you can choose to implement -either linear indexing or cartesian indexing. If you decide to -implement linear indexing, then you must set this trait for your array +you define a new [`AbstractArray`](@ref) type, you can choose to implement +either linear indexing (with [`IndexLinear`](@ref)) or cartesian indexing. +If you decide to implement linear indexing, then you must set this trait for your array type: Base.IndexStyle(::Type{<:MyArray}) = IndexLinear() -The default is `IndexCartesian()`. +The default is [`IndexCartesian()`](@ref). Julia's internal indexing machinery will automatically (and invisibly) convert all indexing operations into the preferred style. This allows users diff --git a/base/iterators.jl b/base/iterators.jl index 396b1744482f7..1564ffa1be9a1 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -181,9 +181,9 @@ Also similar to `enumerate(A)`, except `i` will be a valid index for `A`, while `enumerate` always counts from 1 regardless of the indices of `A`. -Specifying `IndexLinear()` ensures that `i` will be an integer; -specifying `IndexCartesian()` ensures that `i` will be a -`CartesianIndex`; specifying `IndexStyle(A)` chooses whichever has +Specifying [`IndexLinear()`](@ref) ensures that `i` will be an integer; +specifying [`IndexCartesian()`](@ref) ensures that `i` will be a +[`CartesianIndex`](@ref); specifying `IndexStyle(A)` chooses whichever has been defined as the native indexing style for array `A`. Mutation of the bounds of the underlying array will invalidate this iterator. diff --git a/doc/src/base/arrays.md b/doc/src/base/arrays.md index 521cbc2d3dea8..260649a3a36cf 100644 --- a/doc/src/base/arrays.md +++ b/doc/src/base/arrays.md @@ -53,6 +53,8 @@ Base.axes(::AbstractArray, ::Any) Base.length(::AbstractArray) Base.eachindex Base.IndexStyle +Base.IndexLinear +Base.IndexCartesian Base.conj! Base.stride Base.strides From 25ed51e13f71bdaf61a993cd416ff6b7d13f63fa Mon Sep 17 00:00:00 2001 From: chromezh <32255369+chromezh@users.noreply.github.com> Date: Mon, 13 Aug 2018 21:59:23 +0800 Subject: [PATCH 008/166] Fix typo (#28594) Add a punctuation (cherry picked from commit 883c8a38920985e0c02df169ff8c379731d88fc6) --- doc/src/manual/noteworthy-differences.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/noteworthy-differences.md b/doc/src/manual/noteworthy-differences.md index 9aff0df12fe68..c45d7b1ef8e44 100644 --- a/doc/src/manual/noteworthy-differences.md +++ b/doc/src/manual/noteworthy-differences.md @@ -253,7 +253,7 @@ For users coming to Julia from R, these are some noteworthy differences: Floating point literals are closer in behavior to C/C++. Octal (prefixed with `0o`) and binary (prefixed with `0b`) literals are also treated as unsigned. * String literals can be delimited with either `"` or `"""`, `"""` delimited literals can contain - `"` characters without quoting it like `"\""` String literals can have values of other variables + `"` characters without quoting it like `"\""`. String literals can have values of other variables or expressions interpolated into them, indicated by `$variablename` or `$(expression)`, which evaluates the variable name or the expression in the context of the function. * `//` indicates a [`Rational`](@ref) number, and not a single-line comment (which is `#` in Julia) From 1d651adaf8a1ef23d39fff04856aa959e970f61d Mon Sep 17 00:00:00 2001 From: Sebastian Pfitzner Date: Mon, 13 Aug 2018 23:37:00 +0100 Subject: [PATCH 009/166] fix various `printstyled` calls (#28586) (cherry picked from commit decee6537e7924d53174768880dadfa1854d0bf1) --- base/compiler/ssair/show.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base/compiler/ssair/show.jl b/base/compiler/ssair/show.jl index c1b396f22a6ab..97d74be275702 100644 --- a/base/compiler/ssair/show.jl +++ b/base/compiler/ssair/show.jl @@ -327,7 +327,7 @@ function show_ir(io::IO, code::IRCode, expr_type_printer=default_expr_type_print bb_idx = 1 new_nodes = code.new_nodes if any(i -> !isassigned(code.new_nodes, i), 1:length(code.new_nodes)) - printstyled(io, :red, "ERROR: New node array has unset entry\n") + printstyled(io, "ERROR: New node array has unset entry\n", color=:red) new_nodes = new_nodes[filter(i -> isassigned(code.new_nodes, i), 1:length(code.new_nodes))] end for nn in new_nodes @@ -354,7 +354,7 @@ function show_ir(io::IO, code::IRCode, expr_type_printer=default_expr_type_print if !isassigned(stmts, idx) # This is invalid, but do something useful rather # than erroring, to make debugging easier - printstyled(io, :red, "#UNDEF\n") + printstyled(io, "#UNDEF\n", color=:red) continue end stmt = stmts[idx] @@ -495,7 +495,7 @@ function show_ir(io::IO, code::CodeInfo, expr_type_printer=default_expr_type_pri if !isassigned(stmts, idx) # This is invalid, but do something useful rather # than erroring, to make debugging easier - printstyled(io, :red, "#UNDEF\n") + printstyled(io, "#UNDEF\n", color=:red) continue end stmt = stmts[idx] From 6ef9630507d640220ef733d02faa7baa7cc91814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Tue, 14 Aug 2018 00:37:43 +0200 Subject: [PATCH 010/166] fix print docstring (#28609) (cherry picked from commit 2fcad41676403255c075e3acf8d997892d2fcfc8) --- base/strings/io.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/strings/io.jl b/base/strings/io.jl index bd82fd37494b3..4df79c223ac69 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -11,7 +11,7 @@ of values `xs` if there is one, otherwise call [`show`](@ref). The representation used by `print` includes minimal formatting and tries to avoid Julia-specific details. -Printing `nothing` is deprecated and will throw an error in the future. +Printing `nothing` is not allowed and throws an error. # Examples ```jldoctest @@ -132,7 +132,7 @@ string_with_env(env, xs...) = print_to_string(xs...; env=env) """ string(xs...) -Create a string from any values using the [`print`](@ref) function. +Create a string from any values, except `nothing`, using the [`print`](@ref) function. # Examples ```jldoctest From 2417246291d165806b018aba074262f1b895722c Mon Sep 17 00:00:00 2001 From: Affan Date: Tue, 14 Aug 2018 13:21:05 -0400 Subject: [PATCH 011/166] fixes issue 28553, improves error message for missing packages (#28555) (cherry picked from commit 3d8091fb1ed9482a5a44e79f5d589197ce61929c) --- base/loading.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/loading.jl b/base/loading.jl index 7feb1cdd26d85..f55f75498d90e 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -816,7 +816,7 @@ function require(into::Module, mod::Symbol) if where.uuid === nothing throw(ArgumentError(""" Package $mod not found in current path: - - Run `Pkg.add($(repr(String(mod))))` to install the $mod package. + - Run `import Pkg; Pkg.add($(repr(String(mod))))` to install the $mod package. """)) else s = """ From ffa7047265b8a3306afff35e73c5245a8ccee154 Mon Sep 17 00:00:00 2001 From: Patrick Kofod Mogensen Date: Tue, 14 Aug 2018 20:30:39 +0200 Subject: [PATCH 012/166] Keep parametric information when constructing a SparseMatrixCSC from a SparseMatrixCSC. (#28642) (cherry picked from commit 686ffdb98bab3e9a3db7c5654bcbf85ecf56cee7) --- stdlib/SparseArrays/src/sparsematrix.jl | 1 + stdlib/SparseArrays/test/sparse.jl | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/stdlib/SparseArrays/src/sparsematrix.jl b/stdlib/SparseArrays/src/sparsematrix.jl index a88f27edd90d1..f954d33393d61 100644 --- a/stdlib/SparseArrays/src/sparsematrix.jl +++ b/stdlib/SparseArrays/src/sparsematrix.jl @@ -356,6 +356,7 @@ similar(S::SparseMatrixCSC, ::Type{TvNew}, ::Type{TiNew}, m::Integer, n::Integer # converting between SparseMatrixCSC types +SparseMatrixCSC(S::SparseMatrixCSC) = copy(S) AbstractMatrix{Tv}(A::SparseMatrixCSC) where {Tv} = SparseMatrixCSC{Tv}(A) SparseMatrixCSC{Tv}(S::SparseMatrixCSC{Tv}) where {Tv} = copy(S) SparseMatrixCSC{Tv}(S::SparseMatrixCSC) where {Tv} = SparseMatrixCSC{Tv,eltype(S.colptr)}(S) diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index f88c6dde06493..0c17946d7a5d8 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -2289,4 +2289,10 @@ end @test adjoint(MC) == copy(adjoint(SC)) end +@testset "Issue #28634" begin + a = SparseMatrixCSC{Int8, Int16}([1 2; 3 4]) + na = SparseMatrixCSC(a) + @test typeof(a) === typeof(na) +end + end # module From ecc1300c2b616a698cb38f51687c1a37b6ad4893 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Wed, 15 Aug 2018 01:44:49 +0200 Subject: [PATCH 013/166] stop specializing on argument types of `display` (#28616) there is no real advantage in specializing on the argument types for display since it goes through a quite complicated machinery of trying to find applicable displays. Before: julia> let @time precompile(Tuple{typeof(Base.Multimedia.display), Int32}) @time precompile(Tuple{typeof(Base.Multimedia.display), Vector{Int}}) @time precompile(Tuple{typeof(Base.Multimedia.display), Float64}) @time precompile(Tuple{typeof(Base.Multimedia.display), Symbol}) end 0.034542 seconds (37.08 k allocations: 1.916 MiB) 0.042272 seconds (92.57 k allocations: 4.810 MiB) 0.039003 seconds (90.20 k allocations: 4.758 MiB) 0.030826 seconds (61.08 k allocations: 3.066 MiB) After: julia> let @time precompile(Tuple{typeof(Base.Multimedia.display), Int32}) @time precompile(Tuple{typeof(Base.Multimedia.display), Vector{Int}}) @time precompile(Tuple{typeof(Base.Multimedia.display), Float64}) @time precompile(Tuple{typeof(Base.Multimedia.display), Symbol}) end 0.000041 seconds (12 allocations: 640 bytes) 0.000029 seconds (10 allocations: 544 bytes) 0.000024 seconds (9 allocations: 496 bytes) 0.000021 seconds (9 allocations: 496 bytes) (cherry picked from commit eabb601ec8cccb4ff40f18eb4f046ab4608f1840) --- base/multimedia.jl | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/base/multimedia.jl b/base/multimedia.jl index 3ec70cc12b663..9e17f05d7312b 100644 --- a/base/multimedia.jl +++ b/base/multimedia.jl @@ -43,8 +43,8 @@ julia> showable("img/png", rand(5)) false ``` """ -showable(::MIME{mime}, x) where {mime} = hasmethod(show, Tuple{IO, MIME{mime}, typeof(x)}) -showable(m::AbstractString, x) = showable(MIME(m), x) +showable(::MIME{mime}, @nospecialize x) where {mime} = hasmethod(show, Tuple{IO, MIME{mime}, typeof(x)}) +showable(m::AbstractString, @nospecialize x) = showable(MIME(m), x) """ show(io, mime, x) @@ -175,8 +175,8 @@ end abstract type AbstractDisplay end # it is convenient to accept strings instead of ::MIME -display(d::AbstractDisplay, mime::AbstractString, x) = display(d, MIME(mime), x) -display(mime::AbstractString, x) = display(MIME(mime), x) +display(d::AbstractDisplay, mime::AbstractString, @nospecialize x) = display(d, MIME(mime), x) +display(mime::AbstractString, @nospecialize x) = display(MIME(mime), x) """ displayable(mime) -> Bool @@ -201,12 +201,12 @@ objects are printed in the Julia REPL.) struct TextDisplay <: AbstractDisplay io::IO end -display(d::TextDisplay, M::MIME"text/plain", x) = show(d.io, M, x) -display(d::TextDisplay, x) = display(d, MIME"text/plain"(), x) +display(d::TextDisplay, M::MIME"text/plain", @nospecialize x) = show(d.io, M, x) +display(d::TextDisplay, @nospecialize x) = display(d, MIME"text/plain"(), x) # if you explicitly call display("text/foo", x), it should work on a TextDisplay: displayable(d::TextDisplay, M::MIME) = istextmime(M) -function display(d::TextDisplay, M::MIME, x) +function display(d::TextDisplay, M::MIME, @nospecialize x) displayable(d, M) || throw(MethodError(display, (d, M, x))) show(d.io, M, x) end @@ -254,7 +254,7 @@ function reinit_displays() pushdisplay(TextDisplay(stdout)) end -xdisplayable(D::AbstractDisplay, args...) = applicable(display, D, args...) +xdisplayable(D::AbstractDisplay, @nospecialize args...) = applicable(display, D, args...) """ display(x) @@ -280,7 +280,7 @@ variants, one can also supply the "raw" data in the requested MIME type by passi `x::AbstractString` (for MIME types with text-based storage, such as text/html or application/postscript) or `x::Vector{UInt8}` (for binary MIME types). """ -function display(x) +function display(@nospecialize x) for i = length(displays):-1:1 if xdisplayable(displays[i], x) try @@ -294,7 +294,7 @@ function display(x) throw(MethodError(display, (x,))) end -function display(m::MIME, x) +function display(m::MIME, @nospecialize x) for i = length(displays):-1:1 if xdisplayable(displays[i], m, x) try @@ -339,7 +339,7 @@ Using `redisplay` is also a hint to the backend that `x` may be redisplayed several times, and the backend may choose to defer the display until (for example) the next interactive prompt. """ -function redisplay(x) +function redisplay(@nospecialize x) for i = length(displays):-1:1 if xdisplayable(displays[i], x) try @@ -353,7 +353,7 @@ function redisplay(x) throw(MethodError(redisplay, (x,))) end -function redisplay(m::Union{MIME,AbstractString}, x) +function redisplay(m::Union{MIME,AbstractString}, @nospecialize x) for i = length(displays):-1:1 if xdisplayable(displays[i], m, x) try @@ -368,8 +368,8 @@ function redisplay(m::Union{MIME,AbstractString}, x) end # default redisplay is simply to call display -redisplay(d::AbstractDisplay, x) = display(d, x) -redisplay(d::AbstractDisplay, m::Union{MIME,AbstractString}, x) = display(d, m, x) +redisplay(d::AbstractDisplay, @nospecialize x) = display(d, x) +redisplay(d::AbstractDisplay, m::Union{MIME,AbstractString}, @nospecialize x) = display(d, m, x) ########################################################################### From cd654a3dde92cf624ca907b8f10218782786f01e Mon Sep 17 00:00:00 2001 From: anderson15 <4404456+anderson15@users.noreply.github.com> Date: Wed, 15 Aug 2018 03:12:52 -0400 Subject: [PATCH 014/166] Change quit() to exit() (#28660) To get out of REPL. (cherry picked from commit 548d83fe60831b425869a27b219b7d25e4a4bb1d) --- stdlib/REPL/docs/src/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/REPL/docs/src/index.md b/stdlib/REPL/docs/src/index.md index 0920ab36549c3..2afa93dfb32ea 100644 --- a/stdlib/REPL/docs/src/index.md +++ b/stdlib/REPL/docs/src/index.md @@ -15,7 +15,7 @@ Markdown.parse("```\n\$ julia\n\n$(banner)\njulia>\n```") ``` To exit the interactive session, type `^D` -- the control key together with the `d` key on a blank -line -- or type `quit()` followed by the return or enter key. The REPL greets you with a banner +line -- or type `exit()` followed by the return or enter key. The REPL greets you with a banner and a `julia>` prompt. ## The different prompt modes From c097ec3006a23894902a73f2186fceb793106e7d Mon Sep 17 00:00:00 2001 From: Patrick Kofod Mogensen Date: Wed, 15 Aug 2018 09:13:34 +0200 Subject: [PATCH 015/166] Fix input args in rem_pio2_kernel doc string (#28657) It was once an argument, but it's calculated on the first line, so... (cherry picked from commit bcce68d79862e99403166c0bbbf7f1565beb658d) --- base/special/rem_pio2.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/special/rem_pio2.jl b/base/special/rem_pio2.jl index 67cb067955f7a..c8d1018cd7881 100644 --- a/base/special/rem_pio2.jl +++ b/base/special/rem_pio2.jl @@ -208,7 +208,7 @@ function paynehanek(x::Float64) end """ - rem_pio2_kernel(x, xhp) + rem_pio2_kernel(x) Return the remainder of `x` modulo π/2 as a double-double pair, along with a `k` such that ``k \\mod 3 == K \\mod 3`` where ``K*π/2 = x - rem``. Note, that it is From 5da38de474e5c0dfadb583dd644a2e58aac6224c Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Wed, 15 Aug 2018 17:04:58 +0900 Subject: [PATCH 016/166] remove redundant text in a docstring (#28663) (cherry picked from commit 4e098f1717169cfc1340dbeaf99f25fcb8ea0227) --- base/strings/io.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/strings/io.jl b/base/strings/io.jl index 4df79c223ac69..1584b529beada 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -223,7 +223,7 @@ IOBuffer(s::SubString{String}) = IOBuffer(view(unsafe_wrap(Vector{UInt8}, s.stri Join an array of `strings` into a single string, inserting the given delimiter between adjacent strings. If `last` is given, it will be used instead of `delim` between the last two strings. If `io` is given, the result is written to `io` rather than returned as -as a `String`. For example, +as a `String`. # Examples ```jldoctest From ef041dc30570a70a9d095659ec7d51ec2444cc74 Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Wed, 15 Aug 2018 17:12:33 +0900 Subject: [PATCH 017/166] fix typo in a docstring (#28664) (cherry picked from commit 7ffe704320543edd943f19a9ffd9c84df2a1df4a) --- base/strings/io.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/strings/io.jl b/base/strings/io.jl index 1584b529beada..64b9a613c084e 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -81,7 +81,7 @@ of the buffer (in bytes). The optional keyword argument `context` can be set to `:key=>value` pair or an `IO` or [`IOContext`](@ref) object whose attributes are used for the I/O -stream passed to `f`. The optional `sizehint` is a suggersted (in bytes) +stream passed to `f`. The optional `sizehint` is a suggested size (in bytes) to allocate for the buffer used to write the string. # Examples From 1169109ebe997d983d1b1e309a5d06af385d1e8c Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Wed, 15 Aug 2018 21:04:00 +0200 Subject: [PATCH 018/166] improve performance for number to string conversion functions (#28661) * improve performance for number to string conversion functions (cherry picked from commit 472fe5fdbec40fad8ae61bb6f250294726b19f94) --- base/intfuncs.jl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index c3ec78eeb31e9..2b75f09ac62e7 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -543,11 +543,11 @@ function bin(x::Unsigned, pad::Int, neg::Bool) i = neg + max(pad,sizeof(x)<<3-leading_zeros(x)) a = StringVector(i) while i > neg - a[i] = '0'+(x&0x1) + @inbounds a[i] = 48+(x&0x1) x >>= 1 i -= 1 end - if neg; a[1]='-'; end + if neg; @inbounds a[1]=0x2d; end String(a) end @@ -555,11 +555,11 @@ function oct(x::Unsigned, pad::Int, neg::Bool) i = neg + max(pad,div((sizeof(x)<<3)-leading_zeros(x)+2,3)) a = StringVector(i) while i > neg - a[i] = '0'+(x&0x7) + @inbounds a[i] = 48+(x&0x7) x >>= 3 i -= 1 end - if neg; a[1]='-'; end + if neg; @inbounds a[1]=0x2d; end String(a) end @@ -567,11 +567,11 @@ function dec(x::Unsigned, pad::Int, neg::Bool) i = neg + ndigits(x, base=10, pad=pad) a = StringVector(i) while i > neg - a[i] = '0'+rem(x,10) + @inbounds a[i] = 48+rem(x,10) x = oftype(x,div(x,10)) i -= 1 end - if neg; a[1]='-'; end + if neg; @inbounds a[1]=0x2d; end String(a) end @@ -580,11 +580,11 @@ function hex(x::Unsigned, pad::Int, neg::Bool) a = StringVector(i) while i > neg d = x & 0xf - a[i] = '0'+d+39*(d>9) + @inbounds a[i] = 48+d+39*(d>9) x >>= 4 i -= 1 end - if neg; a[1]='-'; end + if neg; @inbounds a[1]=0x2d; end String(a) end From 881d197320dfbade01299020b9d34eb65d46ad62 Mon Sep 17 00:00:00 2001 From: Jim Garrison Date: Wed, 15 Aug 2018 18:02:44 -0400 Subject: [PATCH 019/166] Fix throw_complex_domainerror error message for log[1p] (#28621) * Fix throw_complex_domainerror error message for log[1p] This seems pretty clearly unintentional. Relevant history is in d4229beb7e8d2c665fe6bd3fc9624ec2ffa4d096 and d555a9a3874f4c47e16d1fdcbae4866cc0d3917f. * Require `Symbol` as first argument to `throw_complex_domainerror` (cherry picked from commit a3a2b7a058e1b5ff1a1d86c78318391b7f49eb0e) --- base/math.jl | 20 ++++++++++---------- base/special/log.jl | 8 ++++---- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/base/math.jl b/base/math.jl index 6e758cf7b83e2..2d58744d61b0d 100644 --- a/base/math.jl +++ b/base/math.jl @@ -27,7 +27,7 @@ using Core.Intrinsics: sqrt_llvm using .Base: IEEEFloat -@noinline function throw_complex_domainerror(f, x) +@noinline function throw_complex_domainerror(f::Symbol, x) throw(DomainError(x, string("$f will only return a complex result if called with a ", "complex argument. Try $f(Complex(x))."))) end @@ -198,17 +198,17 @@ julia> log(4,2) 0.5 julia> log(-2, 3) -ERROR: DomainError with log: --2.0 will only return a complex result if called with a complex argument. Try -2.0(Complex(x)). +ERROR: DomainError with -2.0: +log will only return a complex result if called with a complex argument. Try log(Complex(x)). Stacktrace: - [1] throw_complex_domainerror(::Float64, ::Symbol) at ./math.jl:31 + [1] throw_complex_domainerror(::Symbol, ::Float64) at ./math.jl:31 [...] julia> log(2, -3) -ERROR: DomainError with log: --3.0 will only return a complex result if called with a complex argument. Try -3.0(Complex(x)). +ERROR: DomainError with -3.0: +log will only return a complex result if called with a complex argument. Try log(Complex(x)). Stacktrace: - [1] throw_complex_domainerror(::Float64, ::Symbol) at ./math.jl:31 + [1] throw_complex_domainerror(::Symbol, ::Float64) at ./math.jl:31 [...] ``` @@ -459,10 +459,10 @@ julia> log1p(0) 0.0 julia> log1p(-2) -ERROR: DomainError with log1p: --2.0 will only return a complex result if called with a complex argument. Try -2.0(Complex(x)). +ERROR: DomainError with -2.0: +log1p will only return a complex result if called with a complex argument. Try log1p(Complex(x)). Stacktrace: - [1] throw_complex_domainerror(::Float64, ::Symbol) at ./math.jl:31 + [1] throw_complex_domainerror(::Symbol, ::Float64) at ./math.jl:31 [...] ``` """ diff --git a/base/special/log.jl b/base/special/log.jl index 7e52c39c2a5d9..4b6429adf7c2d 100644 --- a/base/special/log.jl +++ b/base/special/log.jl @@ -282,7 +282,7 @@ function log(x::Float64) elseif isnan(x) NaN else - throw_complex_domainerror(x, :log) + throw_complex_domainerror(:log, x) end end @@ -318,7 +318,7 @@ function log(x::Float32) elseif isnan(x) NaN32 else - throw_complex_domainerror(x, :log) + throw_complex_domainerror(:log, x) end end @@ -353,7 +353,7 @@ function log1p(x::Float64) elseif isnan(x) NaN else - throw_complex_domainerror(x, :log1p) + throw_complex_domainerror(:log1p, x) end end @@ -386,7 +386,7 @@ function log1p(x::Float32) elseif isnan(x) NaN32 else - throw_complex_domainerror(x, :log1p) + throw_complex_domainerror(:log1p, x) end end From 6abac45b97b49eb42626c914a7a9b2b91ea4436c Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 15 Aug 2018 18:04:07 -0400 Subject: [PATCH 020/166] fix #28641, passing typevars to `<:` in typejoin and tuplemerge (#28655) (cherry picked from commit 290684d3180bb3b38259343d74479f90dccd9b04) --- base/compiler/typelimits.jl | 3 +++ base/promotion.jl | 10 +++++----- test/compiler/compiler.jl | 13 +++++++++++++ test/core.jl | 2 ++ 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/base/compiler/typelimits.jl b/base/compiler/typelimits.jl index 83ca2a386b119..f8220375e4518 100644 --- a/base/compiler/typelimits.jl +++ b/base/compiler/typelimits.jl @@ -412,6 +412,9 @@ function tuplemerge(a::DataType, b::DataType) for loop_b = (false, true) for i = (lt + 1):(loop_b ? lbr : lar) ti = unwrapva(loop_b ? bp[i] : ap[i]) + while ti isa TypeVar + ti = ti.ub + end # compare (ti <-> tail), (wrapper ti <-> tail), (ti <-> wrapper tail), then (wrapper ti <-> wrapper tail) # until we find the first element that contains the other in the pair # TODO: this result would be more stable (and more associative and more commutative) diff --git a/base/promotion.jl b/base/promotion.jl index 78a1954da55eb..319284beaaaf9 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -14,7 +14,11 @@ typejoin(@nospecialize(t)) = (@_pure_meta; t) typejoin(@nospecialize(t), ts...) = (@_pure_meta; typejoin(t, typejoin(ts...))) function typejoin(@nospecialize(a), @nospecialize(b)) @_pure_meta - if a <: b + if isa(a, TypeVar) + return typejoin(a.ub, b) + elseif isa(b, TypeVar) + return typejoin(a, b.ub) + elseif a <: b return b elseif b <: a return a @@ -22,10 +26,6 @@ function typejoin(@nospecialize(a), @nospecialize(b)) return UnionAll(a.var, typejoin(a.body, b)) elseif isa(b, UnionAll) return UnionAll(b.var, typejoin(a, b.body)) - elseif isa(a, TypeVar) - return typejoin(a.ub, b) - elseif isa(b, TypeVar) - return typejoin(a, b.ub) elseif isa(a, Union) return typejoin(typejoin(a.a, a.b), b) elseif isa(b, Union) diff --git a/test/compiler/compiler.jl b/test/compiler/compiler.jl index 904695982e030..7ddca137ed2c4 100644 --- a/test/compiler/compiler.jl +++ b/test/compiler/compiler.jl @@ -1977,3 +1977,16 @@ function bar28444() e[1] end @test bar28444() == 1 + +# issue #28641 +struct VoxelIndices{T <: Integer} + voxCrnrPos::NTuple{8,NTuple{3,T}} + voxEdgeCrnrs::NTuple{19, NTuple{2,T}} + voxEdgeDir::NTuple{19,T} + voxEdgeIx::NTuple{8,NTuple{8,T}} + subTets::NTuple{6,NTuple{4,T}} + tetEdgeCrnrs::NTuple{6,NTuple{2,T}} + tetTri::NTuple{16,NTuple{6,T}} +end +f28641(x::VoxelIndices, f) = getfield(x, f) +@test Base.return_types(f28641, (Any,Symbol)) == Any[Tuple] diff --git a/test/core.jl b/test/core.jl index 7dd27fefe03fc..d8981f352ffb1 100644 --- a/test/core.jl +++ b/test/core.jl @@ -141,6 +141,8 @@ end @test typejoin(Tuple{Vararg{Int,2}}, Tuple{Int,Int,Int}) === Tuple{Int,Int,Vararg{Int}} @test typejoin(Tuple{Vararg{Int,2}}, Tuple{Vararg{Int}}) === Tuple{Vararg{Int}} +@test typejoin(NTuple{3,Tuple}, NTuple{2,T} where T) == Tuple{Any,Any,Vararg{Tuple}} + # issue #26321 struct T26321{N,S<:NTuple{N}} t::S From bd1ae7deb3eef46adf796b54dacf8ca8f07c02b6 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 15 Aug 2018 18:04:25 -0400 Subject: [PATCH 021/166] fix #28499, calling `cluster_cookie` before cluster starts (#28656) (cherry picked from commit 630f53acdd37df3a23d96080deec9a25a1355494) --- stdlib/Distributed/src/cluster.jl | 3 ++- stdlib/Distributed/test/distributed_exec.jl | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/stdlib/Distributed/src/cluster.jl b/stdlib/Distributed/src/cluster.jl index 0d1614b7e972a..49df11b6eef0d 100644 --- a/stdlib/Distributed/src/cluster.jl +++ b/stdlib/Distributed/src/cluster.jl @@ -644,7 +644,7 @@ end Return the cluster cookie. """ -cluster_cookie() = LPROC.cookie +cluster_cookie() = (init_multi(); LPROC.cookie) """ cluster_cookie(cookie) -> cookie @@ -652,6 +652,7 @@ cluster_cookie() = LPROC.cookie Set the passed cookie as the cluster cookie, then returns it. """ function cluster_cookie(cookie) + init_multi() # The cookie must be an ASCII string with length <= HDR_COOKIE_LEN @assert isascii(cookie) @assert length(cookie) <= HDR_COOKIE_LEN diff --git a/stdlib/Distributed/test/distributed_exec.jl b/stdlib/Distributed/test/distributed_exec.jl index 04ef09d495a2d..f17d97697c27e 100644 --- a/stdlib/Distributed/test/distributed_exec.jl +++ b/stdlib/Distributed/test/distributed_exec.jl @@ -3,6 +3,8 @@ using Test, Distributed, Random, Serialization, Sockets import Distributed: launch, manage +@test cluster_cookie() isa String + include(joinpath(Sys.BINDIR, "..", "share", "julia", "test", "testenv.jl")) @test Distributed.extract_imports(:(begin; import Foo, Bar; let; using Baz; end; end)) == From 72f54d3ab6a05200acae091543d2f7e177308432 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 15 Aug 2018 18:04:49 -0400 Subject: [PATCH 022/166] fix #28597, error for empty arrays with some negative dim sizes (#28659) (cherry picked from commit 5c1f6b061c2a486f69f959173039117382c9b95a) --- src/array.c | 5 +++-- test/core.jl | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/array.c b/src/array.c index 746d474b97b18..6a893f96cf43e 100644 --- a/src/array.c +++ b/src/array.c @@ -61,8 +61,9 @@ static jl_array_t *_new_array_(jl_value_t *atype, uint32_t ndims, size_t *dims, jl_array_t *a; for(i=0; i < ndims; i++) { - wideint_t prod = (wideint_t)nel * (wideint_t)dims[i]; - if (prod > (wideint_t) MAXINTVAL) + size_t di = dims[i]; + wideint_t prod = (wideint_t)nel * (wideint_t)di; + if (prod > (wideint_t) MAXINTVAL || di > MAXINTVAL) jl_error("invalid Array dimensions"); nel = prod; } diff --git a/test/core.jl b/test/core.jl index d8981f352ffb1..822fa6fca76c7 100644 --- a/test/core.jl +++ b/test/core.jl @@ -6697,3 +6697,8 @@ function repackage28445() true end @test repackage28445() + +# issue #28597 +@test_throws ErrorException Array{Int, 2}(undef, 0, -10) +@test_throws ErrorException Array{Int, 2}(undef, -10, 0) +@test_throws ErrorException Array{Int, 2}(undef, -1, -1) From b843f9ea6f0b34ad3e57d3dac024e31afcf78a24 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Thu, 16 Aug 2018 10:25:49 +0200 Subject: [PATCH 023/166] fix performance in printf (#28670) (cherry picked from commit 4629a212afc5055a4cb8cb752be8eb666f7def43) --- base/printf.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base/printf.jl b/base/printf.jl index 5010503949819..85a066be43bca 100644 --- a/base/printf.jl +++ b/base/printf.jl @@ -863,7 +863,7 @@ function decode_oct(d::Integer) @handle_zero x digits pt = i = div((sizeof(x)<<3)-leading_zeros(x)+2,3) while i > 0 - digits[i] = '0'+(x&0x7) + digits[i] = 48+(x&0x7) x >>= 3 i -= 1 end @@ -876,7 +876,7 @@ function decode_0ct(d::Integer) pt = i = div((sizeof(x)<<3)-leading_zeros(x)+5,3) digits = DIGITSs[Threads.threadid()] while i > 0 - digits[i] = '0'+(x&0x7) + digits[i] = 48+(x&0x7) x >>= 3 i -= 1 end @@ -889,7 +889,7 @@ function decode_dec(d::Integer) @handle_zero x digits pt = i = Base.ndigits0z(x) while i > 0 - digits[i] = '0'+rem(x,10) + digits[i] = 48+rem(x,10) x = div(x,10) i -= 1 end From a80df297e467d43eff41a964e6a006a6ff978913 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Thu, 16 Aug 2018 13:17:33 +0200 Subject: [PATCH 024/166] LinearAlgebra remove unused export (#28684) (cherry picked from commit e23515d97c3d371973d30f33e82a0d4e1faa7ecc) --- stdlib/LinearAlgebra/src/LinearAlgebra.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/LinearAlgebra.jl b/stdlib/LinearAlgebra/src/LinearAlgebra.jl index 48f5b34ca81f7..0da7dadb67434 100644 --- a/stdlib/LinearAlgebra/src/LinearAlgebra.jl +++ b/stdlib/LinearAlgebra/src/LinearAlgebra.jl @@ -60,7 +60,6 @@ export axpby!, bunchkaufman, bunchkaufman!, - chol, cholesky, cholesky!, cond, From 1834ed48409f3af2be63ab68e186f29d717d75b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Besan=C3=A7on?= Date: Thu, 16 Aug 2018 19:20:44 +0200 Subject: [PATCH 025/166] Complete uuids (#28649) * documented UUID type * fixed typo * improved sentence structure from doc (cherry picked from commit c62555ba7b16810497471d831cfca4328f449798) --- base/uuid.jl | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/base/uuid.jl b/base/uuid.jl index cf422724eb928..75bf21d4697cb 100644 --- a/base/uuid.jl +++ b/base/uuid.jl @@ -1,5 +1,10 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +""" + Represents a Universally Unique Identifier (UUID). + Can be built from one `UInt128` (all byte values), two `UInt64`, or four `UInt32`. + Conversion from a string will check the UUID validity. +""" struct UUID value::UInt128 end @@ -8,18 +13,18 @@ UUID(u::NTuple{4, UInt32}) = UUID((UInt128(u[1]) << 96) | (UInt128(u[2]) << 64) (UInt128(u[3]) << 32) | UInt128(u[4])) function convert(::Type{NTuple{2, UInt64}}, uuid::UUID) - uuid = uuid.value - hi = UInt64((uuid >> 64) & 0xffffffffffffffff) - lo = UInt64(uuid & 0xffffffffffffffff) + bytes = uuid.value + hi = UInt64((bytes >> 64) & 0xffffffffffffffff) + lo = UInt64(bytes & 0xffffffffffffffff) return (hi, lo) end function convert(::Type{NTuple{4, UInt32}}, uuid::UUID) - uuid = uuid.value - hh = UInt32((uuid >> 96) & 0xffffffff) - hl = UInt32((uuid >> 64) & 0xffffffff) - lh = UInt32((uuid >> 32) & 0xffffffff) - ll = UInt32(uuid & 0xffffffff) + bytes = uuid.value + hh = UInt32((bytes >> 96) & 0xffffffff) + hl = UInt32((bytes >> 64) & 0xffffffff) + lh = UInt32((bytes >> 32) & 0xffffffff) + ll = UInt32(bytes & 0xffffffff) return (hh, hl, lh, ll) end From a95f0680bb5756e590d64d753eb36d67d5b3c5d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felipe=20A=2E=20V=2E=20de=20Bragan=C3=A7a=20Alves?= Date: Thu, 16 Aug 2018 13:22:00 -0400 Subject: [PATCH 026/166] Fix issue #28624 (#28635) (cherry picked from commit 2715fb2904f233e1e1b5f23c52612b9955ee6461) --- base/client.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/client.jl b/base/client.jl index 7f568d39d143d..5c5894fc7c8a3 100644 --- a/base/client.jl +++ b/base/client.jl @@ -56,7 +56,7 @@ function repl_cmd(cmd, out) # If it's intended to simulate `cd`, it should instead be doing # more nearly `cd $dir && printf %s \$PWD` (with appropriate quoting), # since shell `cd` does more than just `echo` the result. - dir = read(`$shell -c "printf %s $(shell_escape_posixly(dir))"`, String) + dir = read(`$shell -c "printf '%s' $(shell_escape_posixly(dir))"`, String) end cd(dir) end From fa8f0e6cce088c591973f03c914d4262db1913a8 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Thu, 16 Aug 2018 21:04:48 +0200 Subject: [PATCH 027/166] add a code quote to a word (#28699) (cherry picked from commit 08bf3e11dc4cbe0e654d3d7f534196b22f662420) --- base/essentials.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/essentials.jl b/base/essentials.jl index 3bf9ecfad81d3..edd7e75d2f949 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -795,7 +795,7 @@ isdone(itr, state...) = missing iterate(iter [, state]) -> Union{Nothing, Tuple{Any, Any}} Advance the iterator to obtain the next element. If no elements -remain, nothing should be returned. Otherwise, a 2-tuple of the +remain, `nothing` should be returned. Otherwise, a 2-tuple of the next element and the new iteration state should be returned. """ function iterate end From 18ab3a4812f07e8f6ae7ba80b3d33a01d2fa43cf Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 16 Aug 2018 17:13:23 -0400 Subject: [PATCH 028/166] smarter order of checks in jl_types_equal (#28677) this works around the test issue in RDatasets (cherry picked from commit af3c452fa3c379d58678538e7a8d9c164e380f4f) --- src/subtype.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/subtype.c b/src/subtype.c index 33baf50bac0ee..6b566415ee273 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -1188,6 +1188,13 @@ JL_DLLEXPORT int jl_types_equal(jl_value_t *a, jl_value_t *b) { if (obviously_egal(a, b)) return 1; if (obviously_unequal(a, b)) return 0; + if (jl_is_datatype(a) && !jl_is_concrete_type(b)) { + // if one type looks more likely to be abstract, check it on the left + // first in order to reject more quickly. + jl_value_t *temp = a; + a = b; + b = temp; + } return jl_subtype(a, b) && jl_subtype(b, a); } From ca151cc35c0300b2912c9ff6c99f84f8738f3b76 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Fri, 17 Aug 2018 00:18:30 +0200 Subject: [PATCH 029/166] fix some exported undefined variables and test this does not happen (#28693) (cherry picked from commit cc0de4389b6ced991efb83297a4fd47fdba51dc8) --- stdlib/LinearAlgebra/src/LinearAlgebra.jl | 1 - stdlib/Random/src/Random.jl | 4 +--- test/misc.jl | 8 ++++++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/stdlib/LinearAlgebra/src/LinearAlgebra.jl b/stdlib/LinearAlgebra/src/LinearAlgebra.jl index 0da7dadb67434..f84e56883b436 100644 --- a/stdlib/LinearAlgebra/src/LinearAlgebra.jl +++ b/stdlib/LinearAlgebra/src/LinearAlgebra.jl @@ -133,7 +133,6 @@ export tr, transpose, transpose!, - transpose_type, tril, triu, tril!, diff --git a/stdlib/Random/src/Random.jl b/stdlib/Random/src/Random.jl index 42aebc1344d42..1ac74ad5e64fd 100644 --- a/stdlib/Random/src/Random.jl +++ b/stdlib/Random/src/Random.jl @@ -23,9 +23,7 @@ export rand!, randn!, shuffle, shuffle!, randperm, randperm!, randcycle, randcycle!, - AbstractRNG, MersenneTwister, RandomDevice, - randjump - + AbstractRNG, MersenneTwister, RandomDevice ## general definitions diff --git a/test/misc.jl b/test/misc.jl index beec7c1033a31..c280fc79d145e 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -678,3 +678,11 @@ end # Just checking that this doesn't stack overflow on construction @test Test27970Empty() == Test27970Empty() end + +@testset "exports of modules" begin + for (_, mod) in Base.loaded_modules + for v in names(mod) + @test isdefined(mod, v) + end + end +end From a4bdb8b4f3c78628f47a4fe11670072149d9c3ba Mon Sep 17 00:00:00 2001 From: Danny Hermes Date: Thu, 16 Aug 2018 18:01:32 -0500 Subject: [PATCH 030/166] Use code font for `jl_value_t` in h2 (#28702) By just using text, the underscores around value are interpreted as begin/end italics. (cherry picked from commit 1fee8a48f5e5ca78d236228eabab91ae129468c2) --- doc/src/devdocs/object.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/devdocs/object.md b/doc/src/devdocs/object.md index cf9223f768d96..49d1e46724301 100644 --- a/doc/src/devdocs/object.md +++ b/doc/src/devdocs/object.md @@ -1,6 +1,6 @@ # Memory layout of Julia Objects -## Object layout (jl_value_t) +## Object layout (`jl_value_t`) The `jl_value_t` struct is the name for a block of memory owned by the Julia Garbage Collector, representing the data associated with a Julia object in memory. Absent any type information, it From abc36a7b7aa7d7b75f53ca9b5fdb1465b88c08c5 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Fri, 17 Aug 2018 07:55:39 +0200 Subject: [PATCH 031/166] fix REPL completions not always being unique (#28694) * fix REPLcompletions not unique, fix #28692 (cherry picked from commit cd5e5a38c5565703bb747c6a66b2d23cf3dd5994) --- stdlib/REPL/src/REPL.jl | 6 +++--- stdlib/REPL/test/replcompletions.jl | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index 2ce39a860bc51..977c4af6edb92 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -346,7 +346,7 @@ function complete_line(c::REPLCompletionProvider, s) partial = beforecursor(s.input_buffer) full = LineEdit.input_string(s) ret, range, should_complete = completions(full, lastindex(partial)) - return map(completion_text, ret), partial[range], should_complete + return unique!(map(completion_text, ret)), partial[range], should_complete end function complete_line(c::ShellCompletionProvider, s) @@ -354,14 +354,14 @@ function complete_line(c::ShellCompletionProvider, s) partial = beforecursor(s.input_buffer) full = LineEdit.input_string(s) ret, range, should_complete = shell_completions(full, lastindex(partial)) - return map(completion_text, ret), partial[range], should_complete + return unique!(map(completion_text, ret)), partial[range], should_complete end function complete_line(c::LatexCompletions, s) partial = beforecursor(LineEdit.buffer(s)) full = LineEdit.input_string(s) ret, range, should_complete = bslash_completions(full, lastindex(partial))[2] - return map(completion_text, ret), partial[range], should_complete + return unique!(map(completion_text, ret)), partial[range], should_complete end mutable struct REPLHistoryProvider <: HistoryProvider diff --git a/stdlib/REPL/test/replcompletions.jl b/stdlib/REPL/test/replcompletions.jl index 2d03dbf925d32..2e8ae033ee0d0 100644 --- a/stdlib/REPL/test/replcompletions.jl +++ b/stdlib/REPL/test/replcompletions.jl @@ -102,6 +102,11 @@ let s = "" @test s[r] == "" end +let s = "using REP" + c, r = test_complete(s) + @test count(isequal("REPL"), c) == 1 +end + let s = "Comp" c, r = test_complete(s) @test "CompletionFoo" in c From b24e624818bb910c0629a974c46638477afc36e5 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 16 Aug 2018 17:45:37 -0400 Subject: [PATCH 032/166] Fix reinterpret performance This fixes #25014 by making it more obvious what's going on to LLVM. Instead of a memcpy loop, we use a ccall to :memcpy and turn this into llvm.memcpy at the IR level, which is enough for LLVM to fold everything away. In the benchmark from #25014, we still see some regressions from 0.6, but that is because it needs to dereference through the pointers in the reinterpret and reshape wrappers. In any real code, that dereferencing should be loop-invariantly moved out of the inner loop. (cherry picked from commit 777810b8ea5cb84eacda87ecce5304788f86ebd4) --- base/reinterpretarray.jl | 34 +++++++++++++--------------------- base/reshapedarray.jl | 2 +- src/ccall.cpp | 14 ++++++++++++++ 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/base/reinterpretarray.jl b/base/reinterpretarray.jl index 2cde44e9a386d..60b268465c14a 100644 --- a/base/reinterpretarray.jl +++ b/base/reinterpretarray.jl @@ -104,6 +104,8 @@ end _getindex_ra(a, inds[1], tail(inds)) end +@inline _memcpy!(dst, src, n) = ccall(:memcpy, Cvoid, (Ptr{UInt8}, Ptr{UInt8}, Csize_t), dst, src, n) + @inline @propagate_inbounds function _getindex_ra(a::ReinterpretArray{T,N,S}, i1::Int, tailinds::TT) where {T,N,S,TT} # Make sure to match the scalar reinterpret if that is applicable if sizeof(T) == sizeof(S) && (fieldcount(T) + fieldcount(S)) == 0 @@ -123,11 +125,9 @@ end # once it knows the data layout while nbytes_copied < sizeof(T) s[] = a.parent[ind_start + i, tailinds...] - while nbytes_copied < sizeof(T) && sidx < sizeof(S) - unsafe_store!(tptr, unsafe_load(sptr, sidx + 1), nbytes_copied + 1) - sidx += 1 - nbytes_copied += 1 - end + nb = min(sizeof(S) - sidx, sizeof(T)-nbytes_copied) + _memcpy!(tptr + nbytes_copied, sptr + sidx, nb) + nbytes_copied += nb sidx = 0 i += 1 end @@ -173,34 +173,26 @@ end # element from the original array and overwrite the relevant parts if sidx != 0 s[] = a.parent[ind_start + i, tailinds...] - while nbytes_copied < sizeof(T) && sidx < sizeof(S) - unsafe_store!(sptr, unsafe_load(tptr, nbytes_copied + 1), sidx + 1) - sidx += 1 - nbytes_copied += 1 - end + nb = min(sizeof(S) - sidx, sizeof(T)) + _memcpy!(sptr + sidx, tptr, nb) + nbytes_copied += nb a.parent[ind_start + i, tailinds...] = s[] i += 1 sidx = 0 end # Deal with the main body of elements while nbytes_copied < sizeof(T) && (sizeof(T) - nbytes_copied) > sizeof(S) - while nbytes_copied < sizeof(T) && sidx < sizeof(S) - unsafe_store!(sptr, unsafe_load(tptr, nbytes_copied + 1), sidx + 1) - sidx += 1 - nbytes_copied += 1 - end + nb = min(sizeof(S), sizeof(T) - nbytes_copied) + _memcpy!(sptr, tptr + nbytes_copied, nb) + nbytes_copied += nb a.parent[ind_start + i, tailinds...] = s[] i += 1 - sidx = 0 end # Deal with trailing partial elements if nbytes_copied < sizeof(T) s[] = a.parent[ind_start + i, tailinds...] - while nbytes_copied < sizeof(T) && sidx < sizeof(S) - unsafe_store!(sptr, unsafe_load(tptr, nbytes_copied + 1), sidx + 1) - sidx += 1 - nbytes_copied += 1 - end + nb = min(sizeof(S), sizeof(T) - nbytes_copied) + _memcpy!(sptr, tptr + nbytes_copied, nb) a.parent[ind_start + i, tailinds...] = s[] end end diff --git a/base/reshapedarray.jl b/base/reshapedarray.jl index ebd2efba68b36..18b2008f2c4d1 100644 --- a/base/reshapedarray.jl +++ b/base/reshapedarray.jl @@ -222,7 +222,7 @@ end I = ind2sub_rs(axes(A.parent), A.mi, i) _unsafe_getindex_rs(parent(A), I) end -_unsafe_getindex_rs(A, i::Integer) = (@inbounds ret = A[i]; ret) +@inline _unsafe_getindex_rs(A, i::Integer) = (@inbounds ret = A[i]; ret) @inline _unsafe_getindex_rs(A, I) = (@inbounds ret = A[I...]; ret) @inline function setindex!(A::ReshapedArrayLF, val, index::Int) diff --git a/src/ccall.cpp b/src/ccall.cpp index 23e8d1c3ad980..30a919e027427 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -1820,6 +1820,20 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) JL_GC_POP(); return mark_or_box_ccall_result(ctx, strp, retboxed, rt, unionall, static_rt); } + else if (is_libjulia_func(memcpy)) { + const jl_cgval_t &dst = argv[0]; + const jl_cgval_t &src = argv[1]; + const jl_cgval_t &n = argv[2]; + ctx.builder.CreateMemCpy( + ctx.builder.CreateIntToPtr( + emit_unbox(ctx, T_size, dst, (jl_value_t*)jl_voidpointer_type), T_pint8), + ctx.builder.CreateIntToPtr( + emit_unbox(ctx, T_size, src, (jl_value_t*)jl_voidpointer_type), T_pint8), + emit_unbox(ctx, T_size, n, (jl_value_t*)jl_ulong_type), 1, + false); + JL_GC_POP(); + return ghostValue(jl_void_type); + } jl_cgval_t retval = sig.emit_a_ccall( ctx, From ff8361ac9e2de549e43d776bf785e2c4848f7818 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Fri, 17 Aug 2018 15:47:24 -0400 Subject: [PATCH 033/166] Doc sorting algos (#28514) (cherry picked from commit e21c1bbda787645bcbe9760f61ef7991943edaa9) --- base/sort.jl | 60 ++++++++++++++++++++++++++++++++++++++++++++ doc/src/base/sort.md | 12 ++++++--- 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/base/sort.jl b/base/sort.jl index c5cd7232e65c4..e04829a3191c4 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -370,6 +370,20 @@ struct InsertionSortAlg <: Algorithm end struct QuickSortAlg <: Algorithm end struct MergeSortAlg <: Algorithm end +""" + PartialQuickSort{T <: Union{Int,OrdinalRange}} + +Indicate that a sorting function should use the partial quick sort +algorithm. Partial quick sort returns the smallest `k` elements sorted from smallest +to largest, finding them and sorting them using [`QuickSort`](@ref). + +Characteristics: + * *not stable*: does not preserve the ordering of elements which + compare equal (e.g. "a" and "A" in a sort of letters which + ignores case). + * *in-place* in memory. + * *divide-and-conquer*: sort strategy similar to [`MergeSort`](@ref). +""" struct PartialQuickSort{T <: Union{Int,OrdinalRange}} <: Algorithm k::T end @@ -379,8 +393,54 @@ Base.last(a::PartialQuickSort{Int}) = a.k Base.first(a::PartialQuickSort) = first(a.k) Base.last(a::PartialQuickSort) = last(a.k) +""" + InsertionSort + +Indicate that a sorting function should use the insertion sort +algorithm. Insertion sort traverses the collection one element +at a time, inserting each element into its correct, sorted position in +the output list. + +Characteristics: + * *stable*: preserves the ordering of elements which + compare equal (e.g. "a" and "A" in a sort of letters + which ignores case). + * *in-place* in memory. + * *quadratic performance* in the number of elements to be sorted: + it is well-suited to small collections but should not be used for large ones. +""" const InsertionSort = InsertionSortAlg() +""" + QuickSort + +Indicate that a sorting function should use the quick sort +algorithm, which is *not* stable. + +Characteristics: + * *not stable*: does not preserve the ordering of elements which + compare equal (e.g. "a" and "A" in a sort of letters which + ignores case). + * *in-place* in memory. + * *divide-and-conquer*: sort strategy similar to [`MergeSort`](@ref). + * *good performance* for large collections. +""" const QuickSort = QuickSortAlg() +""" + MergeSort + +Indicate that a sorting function should use the merge sort +algorithm. Merge sort divides the collection into +subcollections and repeatedly merges them, sorting each +subcollection at each step, until the entire +collection has been recombined in sorted form. + +Characteristics: + * *stable*: preserves the ordering of elements which compare + equal (e.g. "a" and "A" in a sort of letters which ignores + case). + * *not in-place* in memory. + * *divide-and-conquer* sort strategy. +""" const MergeSort = MergeSortAlg() const DEFAULT_UNSTABLE = QuickSort diff --git a/doc/src/base/sort.md b/doc/src/base/sort.md index a3c3b7c3df338..17a9b8c5ed97d 100644 --- a/doc/src/base/sort.md +++ b/doc/src/base/sort.md @@ -110,6 +110,10 @@ can be specified via the `lt` keyword. Base.sort! Base.sort Base.sortperm +Base.InsertionSort +Base.MergeSort +Base.QuickSort +Base.PartialQuickSort Base.Sort.sortperm! Base.Sort.sortslices ``` @@ -131,10 +135,10 @@ Base.Sort.partialsortperm! There are currently four sorting algorithms available in base Julia: - * `InsertionSort` - * `QuickSort` - * `PartialQuickSort(k)` - * `MergeSort` + * [`InsertionSort`](@ref) + * [`QuickSort`](@ref) + * [`PartialQuickSort(k)`](@ref) + * [`MergeSort`](@ref) `InsertionSort` is an O(n^2) stable sorting algorithm. It is efficient for very small `n`, and is used internally by `QuickSort`. From f22e4fc53e7a4357356dc67647206a8a71e77aa9 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Sat, 18 Aug 2018 21:30:41 +0200 Subject: [PATCH 034/166] Misc doc improvements (#28719) * doc: remove unused file. * doc: improve docstring of at-big_str * doc: fix some broken links (cherry picked from commit dbcc152fcdf03be537032a045117e8c8caf08b51) --- base/int.jl | 15 ++++++++++++--- doc/src/base/numbers.md | 16 +++++++++------- doc/src/manual/index.md | 39 --------------------------------------- 3 files changed, 21 insertions(+), 49 deletions(-) delete mode 100644 doc/src/manual/index.md diff --git a/base/int.jl b/base/int.jl index e6610e9af4774..718542e0e13ea 100644 --- a/base/int.jl +++ b/base/int.jl @@ -579,9 +579,18 @@ end @big_str str @big_str(str) -`@big_str` parses a string into a BigInt -Throws an `ArgumentError` if the string is not a valid integer -Removes all underscores `_` from the string +Parse a string into a [`BigInt`](@ref) or [`BigFloat`](@ref), +and throw an `ArgumentError` if the string is not a valid number. +For integers `_` is allowed in the string as a separator. + +# Examples +```jldoctest +julia> big"123_456" +123456 + +julia> big"7891.5" +7.8915e+03 +``` """ macro big_str(s) if '_' in s diff --git a/doc/src/base/numbers.md b/doc/src/base/numbers.md index 190584bb0f8f4..50e6d2b7134da 100644 --- a/doc/src/base/numbers.md +++ b/doc/src/base/numbers.md @@ -89,8 +89,6 @@ Base.isinteger Base.isreal Core.Float32(::Any) Core.Float64(::Any) -Base.GMP.BigInt(::Any) -Base.MPFR.BigFloat(::Any) Base.Rounding.rounding Base.Rounding.setrounding(::Type, ::Any) Base.Rounding.setrounding(::Function, ::Type, ::RoundingMode) @@ -113,18 +111,22 @@ Base.@int128_str Base.@uint128_str ``` -## BigFloats +## BigFloats and BigInts -The [`BigFloat`](@ref) type implements arbitrary-precision floating-point arithmetic using -the [GNU MPFR library](http://www.mpfr.org/). +The [`BigFloat`](@ref) and [`BigInt`](@ref) types implements +arbitrary-precision floating point and integer arithmetic, respectively. For +[`BigFloat`](@ref) the [GNU MPFR library](http://www.mpfr.org/) is used, +and for [`BigInt`](@ref) the [GNU Multiple Precision Arithmetic Library (GMP)] +(https://gmplib.org) is used. ```@docs +Base.MPFR.BigFloat(::Any) Base.precision Base.MPFR.precision(::Type{BigFloat}) Base.MPFR.setprecision Base.MPFR.BigFloat(x, prec::Int) -BigFloat(x::Union{Integer, AbstractFloat, String}, rounding::RoundingMode) +Base.MPFR.BigFloat(x::Union{Integer, AbstractFloat, String}, rounding::RoundingMode) Base.MPFR.BigFloat(x, prec::Int, rounding::RoundingMode) -Base.MPFR.BigFloat(x::String) +Base.GMP.BigInt(::Any) Base.@big_str ``` diff --git a/doc/src/manual/index.md b/doc/src/manual/index.md deleted file mode 100644 index 3ae00cff847e6..0000000000000 --- a/doc/src/manual/index.md +++ /dev/null @@ -1,39 +0,0 @@ -# The Julia Manual - - * [Introduction](@ref man-introduction) - * [Getting Started](@ref man-getting-started) - * [Variables](@ref) - * [Integers and Floating-Point Numbers](@ref) - * [Mathematical Operations and Elementary Functions](@ref) - * [Complex and Rational Numbers](@ref) - * [Strings](@ref) - * [Functions](@ref) - * [Control Flow](@ref) - * [Scope of Variables](@ref scope-of-variables) - * [Types](@ref man-types) - * [Methods](@ref) - * [Constructors](@ref man-constructors) - * [Conversion and Promotion](@ref conversion-and-promotion) - * [Interfaces](@ref) - * [Modules](@ref) - * [Documentation](@ref) - * [Metaprogramming](@ref) - * [Multi-dimensional Arrays](@ref man-multi-dim-arrays) - * [Missing Values](@ref missing) - * [Networking and Streams](@ref) - * [Parallel Computing](@ref) - * [Dates](@ref) - * [Running External Programs](@ref) - * [Calling C and Fortran Code](@ref) - * [Handling Operating System Variation](@ref) - * [Environment Variables](@ref) - * [Embedding Julia](@ref) - * [Profiling](@ref) - * [Memory allocation analysis](@ref) - * [Stack Traces](@ref) - * [Performance Tips](@ref man-performance-tips) - * [Workflow Tips](@ref man-workflow-tips) - * [Style Guide](@ref) - * [Frequently Asked Questions](@ref) - * [Noteworthy Differences from other Languages](@ref) - * [Unicode Input](@ref) From 02db5952c0cb26f00f038812e0a329fd462857af Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Sat, 18 Aug 2018 15:23:14 -0400 Subject: [PATCH 035/166] Fix another missing GC root (cherry picked from commit 54bc9ee6687a8f38c52154baf32ecb9bd6e43b31) --- src/interpreter.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/interpreter.c b/src/interpreter.c index 030fb4a709912..61d803cbf043a 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -397,7 +397,9 @@ SECT_INTERP static jl_value_t *eval_value(jl_value_t *e, interpreter_state *s) if (jl_is_pinode(e)) { jl_value_t *val = eval_value(jl_fieldref_noalloc(e, 0), s); #ifndef JL_NDEBUG + JL_GC_PUSH1(&val); jl_typeassert(val, jl_fieldref_noalloc(e, 1)); + JL_GC_POP(); #endif return val; } From a871cb637ae3cb3d5a13806d92b5a2172a80bd98 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Sat, 18 Aug 2018 18:15:26 -0400 Subject: [PATCH 036/166] Fix missing gc root in jl_cglobal Static analysis complains that the jl_fieldref could allocate, which then gets passed to jl_bitcast unrooted. I believe it's right about that. While we're here, also fix what I believe is a typo (`ty` vs `v`). (cherry picked from commit af3331b7782c08e63a076b9f143b1f6dad512ba8) --- src/runtime_intrinsics.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/runtime_intrinsics.c b/src/runtime_intrinsics.c index 5caa7bf6f137f..92c19c8fe5898 100644 --- a/src/runtime_intrinsics.c +++ b/src/runtime_intrinsics.c @@ -78,8 +78,9 @@ JL_DLLEXPORT jl_value_t *jl_pointerset(jl_value_t *p, jl_value_t *x, jl_value_t JL_DLLEXPORT jl_value_t *jl_cglobal(jl_value_t *v, jl_value_t *ty) { JL_TYPECHK(cglobal, type, ty); + JL_GC_PUSH1(&v); jl_value_t *rt = - v == (jl_value_t*)jl_void_type ? (jl_value_t*)jl_voidpointer_type : // a common case + ty == (jl_value_t*)jl_void_type ? (jl_value_t*)jl_voidpointer_type : // a common case (jl_value_t*)jl_apply_type1((jl_value_t*)jl_pointer_type, ty); if (!jl_is_concrete_type(rt)) @@ -88,8 +89,11 @@ JL_DLLEXPORT jl_value_t *jl_cglobal(jl_value_t *v, jl_value_t *ty) if (jl_is_tuple(v) && jl_nfields(v) == 1) v = jl_fieldref(v, 0); - if (jl_is_pointer(v)) - return jl_bitcast(rt, v); + if (jl_is_pointer(v)) { + v = jl_bitcast(rt, v); + JL_GC_POP(); + return v; + } char *f_lib = NULL; if (jl_is_tuple(v) && jl_nfields(v) > 1) { @@ -120,6 +124,7 @@ JL_DLLEXPORT jl_value_t *jl_cglobal(jl_value_t *v, jl_value_t *ty) jl_value_t *jv = jl_gc_alloc_1w(); jl_set_typeof(jv, rt); *(void**)jl_data_ptr(jv) = ptr; + JL_GC_POP(); return jv; } From a39334b1fbdf67b880225a5d0cf9e5ba3d283bb0 Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Sun, 19 Aug 2018 16:39:35 +0900 Subject: [PATCH 037/166] add document on JULIA_PROJECT environment variable (#28556) * add document on JULIA_PROJECT environment variable * wrap file names with backticks [ci skip] (cherry picked from commit 2805ebeb5b1da1d3933aa08514d50af034d031dd) --- doc/src/manual/environment-variables.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/src/manual/environment-variables.md b/doc/src/manual/environment-variables.md index b27ff27729afc..d38aa0f21a067 100644 --- a/doc/src/manual/environment-variables.md +++ b/doc/src/manual/environment-variables.md @@ -65,6 +65,15 @@ and a global configuration search path of /etc/julia/startup.jl ``` +### `JULIA_PROJECT` + +A directory path that points to the current Julia project. Setting this +environment variable has the same effect as specifying the `--project` start-up +option, but `--project` has higher precedence. If the variable is set to `@.`, +Julia tries to find a project directory that contains `Project.toml` or +`JuliaProject.toml` file from the current directory and its parents. See also +the chapter on [Code Loading](@ref). + ### `JULIA_LOAD_PATH` A separated list of absolute paths that are to be appended to the variable From 5c6d9f4ad94fa5ea5eb4d422226fb47b733740de Mon Sep 17 00:00:00 2001 From: annainfo Date: Sun, 19 Aug 2018 10:02:35 +0200 Subject: [PATCH 038/166] Update style-guide.md (#28754) s/Julia's Base/Julia Base - as elsewhere, e.g. Julia Base (notably in intro of https://github.com/JuliaLang/julia/commits/master/doc/src/base/base.md), Julia functions, Julia variables, Julia Function Pointers, Julia startup, Julia runtime (cherry picked from commit a288a2dae4193c245205b05055869d115b08bdba) --- doc/src/manual/style-guide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/manual/style-guide.md b/doc/src/manual/style-guide.md index 624297d8a10fa..a39697d124456 100644 --- a/doc/src/manual/style-guide.md +++ b/doc/src/manual/style-guide.md @@ -130,7 +130,7 @@ a = Vector{Union{Int,AbstractString,Tuple,Array}}(undef, n) In this case `Vector{Any}(undef, n)` is better. It is also more helpful to the compiler to annotate specific uses (e.g. `a[i]::Int`) than to try to pack many alternatives into one type. -## Use naming conventions consistent with Julia's `base/` +## Use naming conventions consistent with Julia `base/` * modules and type names use capitalization and camel case: `module SparseArrays`, `struct UnitRange`. * functions are lowercase ([`maximum`](@ref), [`convert`](@ref)) and, when readable, with multiple @@ -143,7 +143,7 @@ uses (e.g. `a[i]::Int`) than to try to pack many alternatives into one type. If a function name requires multiple words, consider whether it might represent more than one concept and might be better split into pieces. -## Write functions with argument ordering similar to Julia's Base +## Write functions with argument ordering similar to Julia Base As a general rule, the Base library uses the following order of arguments to functions, as applicable: From 238dbcfbfe1967041008562af74000a64889c7a6 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Sat, 18 Aug 2018 21:05:40 -0400 Subject: [PATCH 039/166] Fix three missing gc roots in subtyping All found by static analysis. I'm hoping one of them might have been the cause of CI failures like this one: https://circleci.com/gh/JuliaLang/julia/33846?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link (cherry picked from commit 640fc09189ed513c9f168bee56c43b9245f2f615) --- src/subtype.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index 6b566415ee273..6ecea1840559f 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -598,8 +598,9 @@ static jl_value_t *fix_inferred_var_bound(jl_tvar_t *var, jl_value_t *ty) { if (!jl_is_typevar(ty) && jl_has_free_typevars(ty)) { jl_value_t *ans = ty; - jl_array_t *vs = jl_find_free_typevars(ty); + jl_array_t *vs = NULL; JL_GC_PUSH2(&ans, &vs); + vs = jl_find_free_typevars(ty); int i; for (i = 0; i < jl_array_len(vs); i++) { ans = jl_type_unionall((jl_tvar_t*)jl_array_ptr_ref(vs, i), ans); @@ -630,7 +631,7 @@ static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8 btemp = btemp->prev; } jl_varbinding_t vb = { u->var, u->var->lb, u->var->ub, R, NULL, 0, 0, 0, 0, e->invdepth, 0, NULL, e->vars }; - JL_GC_PUSH3(&u, &vb.lb, &vb.ub); + JL_GC_PUSH4(&u, &vb.lb, &vb.ub, &vb.innervars); e->vars = &vb; int ans; if (R) { @@ -1731,7 +1732,9 @@ static int intersect_vararg_length(jl_value_t *v, ssize_t n, jl_stenv_t *e, int8 // only do the check if N is free in the tuple type's last parameter if (jl_is_typevar(N) && N != (jl_value_t*)va_p1 && N != (jl_value_t*)va_p2) { jl_value_t *len = jl_box_long(n); + JL_GC_PUSH1(&len); jl_value_t *il = R ? intersect(len, N, e, 2) : intersect(N, len, e, 2); + JL_GC_POP(); if (il == jl_bottom_type) return 0; } From 6770dd1d09e373c32537318947de832eb4fbd5a7 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Sun, 19 Aug 2018 21:14:54 +0200 Subject: [PATCH 040/166] Remove mention of `reload` from the docs; fix #28572 (#28644) * Remove mention of `reload` from the docs (cherry picked from commit 64580598afc67308c3f1cd638901274344759aac) --- doc/src/manual/modules.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/doc/src/manual/modules.md b/doc/src/manual/modules.md index 74065606cc4e4..ef073cbe6db23 100644 --- a/doc/src/manual/modules.md +++ b/doc/src/manual/modules.md @@ -232,13 +232,10 @@ For file dependencies, a change is determined by examining whether the modificat of each file loaded by `include` or added explicitly by `include_dependency` is unchanged, or equal to the modification time truncated to the nearest second (to accommodate systems that can't copy mtime with sub-second accuracy). It also takes into account whether the path to the file chosen -by the search logic in `require` matches the path that had created the precompile file. - -It also takes into account the set of dependencies already loaded into the current process and -won't recompile those modules, even if their files change or disappear, in order to avoid creating -incompatibilities between the running system and the precompile cache. If you want to have changes -to the source reflected in the running system, you should call `reload("Module")` on the module -you changed, and any module that depended on it in which you want to see the change reflected. +by the search logic in `require` matches the path that had created the precompile file. It also takes +into account the set of dependencies already loaded into the current process and won't recompile those +modules, even if their files change or disappear, in order to avoid creating incompatibilities between +the running system and the precompile cache. If you know that a module is *not* safe to precompile your module (for example, for one of the reasons described below), you should From 0e190025c065785ab9d070c0044ed27835292e92 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Sun, 19 Aug 2018 21:17:56 +0200 Subject: [PATCH 041/166] fix shuffle! on empty arrays (#28727) shuffle([]) doesn't work anymore since nextpow2(n) has been replaced by nextpow(2, n), where n == 0. (cherry picked from commit 728d31d6c5e6a88f5f27ef929fe44c13caa72dfd) --- stdlib/Random/src/misc.jl | 1 + stdlib/Random/test/runtests.jl | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/stdlib/Random/src/misc.jl b/stdlib/Random/src/misc.jl index 0e7bb9782e500..7b94abb062314 100644 --- a/stdlib/Random/src/misc.jl +++ b/stdlib/Random/src/misc.jl @@ -182,6 +182,7 @@ julia> shuffle!(rng, Vector(1:16)) function shuffle!(r::AbstractRNG, a::AbstractArray) @assert !has_offset_axes(a) n = length(a) + n <= 1 && return a # nextpow below won't work with n == 0 @assert n <= Int64(2)^52 mask = nextpow(2, n) - 1 for i = n:-1:2 diff --git a/stdlib/Random/test/runtests.jl b/stdlib/Random/test/runtests.jl index 91d3db9eb994a..83e4b44e83697 100644 --- a/stdlib/Random/test/runtests.jl +++ b/stdlib/Random/test/runtests.jl @@ -686,3 +686,11 @@ end @test Random.gentype(Random.UInt52(UInt128)) == UInt128 @test Random.gentype(Random.UInt104()) == UInt128 end + +@testset "shuffle[!]" begin + a = [] + @test shuffle(a) == a # issue #28727 + @test shuffle!(a) === a + a = rand(Int, 1) + @test shuffle(a) == a +end From 877495abcb148c57915f4a45752c20c14bffba83 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Fri, 17 Aug 2018 16:00:37 -0400 Subject: [PATCH 042/166] Example for parentindices (cherry picked from commit 24df8fb5b49e12a36166af3dff86ad2e48d17b0a) --- base/subarray.jl | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/base/subarray.jl b/base/subarray.jl index b74290ba26e1e..ff640b3e73db4 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -66,7 +66,20 @@ parentindices(V::SubArray) = V.indices """ parentindices(A) -From an array view `A`, returns the corresponding indices in the parent. +Return the indices in the [`parent`](@ref) which correspond to the array view `A`. + +# Examples +```jldoctest +julia> A = [1 2; 3 4]; + +julia> V = view(A, 1, :) +2-element view(::Array{Int64,2}, 1, :) with eltype Int64: + 1 + 2 + +julia> parentindices(V) +(1, Base.Slice(Base.OneTo(2))) +``` """ parentindices(a::AbstractArray) = map(OneTo, size(a)) From 68d4536e90e352db445de182786628f250c05b4d Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Tue, 14 Aug 2018 13:35:16 -0400 Subject: [PATCH 043/166] Add doctest example for broadcast! (cherry picked from commit 80747267edea739b506f54cde45d4375fac50679) --- base/broadcast.jl | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/base/broadcast.jl b/base/broadcast.jl index 88d83d2377e19..a95cc8bbfed29 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -713,6 +713,30 @@ Like [`broadcast`](@ref), but store the result of Note that `dest` is only used to store the result, and does not supply arguments to `f` unless it is also listed in the `As`, as in `broadcast!(f, A, A, B)` to perform `A[:] = broadcast(f, A, B)`. + +# Examples +```jldoctest +julia> A = [1.0; 0.0]; B = [0.0; 0.0]; + +julia> broadcast!(+, B, A, (0, -2.0)); + +julia> B +2-element Array{Float64,1}: + 1.0 + -2.0 + +julia> A +2-element Array{Float64,1}: + 1.0 + 0.0 + +julia> broadcast!(+, A, A, (0, -2.0)); + +julia> A +2-element Array{Float64,1}: + 1.0 + -2.0 +``` """ broadcast!(f::Tf, dest, As::Vararg{Any,N}) where {Tf,N} = (materialize!(dest, broadcasted(f, As...)); dest) From 64e3ec32210c4bde8a904661dafed5f939b17a21 Mon Sep 17 00:00:00 2001 From: scls19fr Date: Mon, 20 Aug 2018 00:15:35 +0200 Subject: [PATCH 044/166] Update Enums.jl (#28769) Helps #28768 (cherry picked from commit b6b471c8c10558a71eefab58a9fa47326d7b024a) --- base/Enums.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/base/Enums.jl b/base/Enums.jl index 021c8c4bea561..4c457443f678d 100644 --- a/base/Enums.jl +++ b/base/Enums.jl @@ -44,6 +44,9 @@ f (generic function with 1 method) julia> f(apple) "I'm a Fruit with value: 1" + +julia> Fruit(1) +apple::Fruit = 1 ``` Values can also be specified inside a `begin` block, e.g. From 79a7efd587cf27084d26bcae21c50e642b3567c9 Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Mon, 20 Aug 2018 18:09:45 +0900 Subject: [PATCH 045/166] fix description of kwargs... (#28757) * fix description of kwargs... * clarify the key type of dicts passed as kwargs (cherry picked from commit 3a54c14e24aa19741f3dd7d00991def9de7c7c85) --- doc/src/manual/functions.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/src/manual/functions.md b/doc/src/manual/functions.md index 45c170bf9b1a6..5b57f6a2a435d 100644 --- a/doc/src/manual/functions.md +++ b/doc/src/manual/functions.md @@ -541,6 +541,10 @@ function f(x; y=0, kwargs...) end ``` +Inside `f`, `kwargs` will be a key-value iterator over a named tuple. Named +tuples (as well as dictionaries with keys of `Symbol`) can be passed as keyword +arguments using a semicolon in a call, e.g. `f(x, z=1; kwargs...)`. + If a keyword argument is not assigned a default value in the method definition, then it is *required*: an [`UndefKeywordError`](@ref) exception will be thrown if the caller does not assign it a value: @@ -552,9 +556,6 @@ f(3, y=5) # ok, y is assigned f(3) # throws UndefKeywordError(:y) ``` -Inside `f`, `kwargs` will be a named tuple. Named tuples (as well as dictionaries) can be passed as -keyword arguments using a semicolon in a call, e.g. `f(x, z=1; kwargs...)`. - One can also pass `key => value` expressions after a semicolon. For example, `plot(x, y; :width => 2)` is equivalent to `plot(x, y, width=2)`. This is useful in situations where the keyword name is computed at runtime. From 2747c9cb71ede6a09b76a7e0dd59e8d15ebe3737 Mon Sep 17 00:00:00 2001 From: ExpandingMan Date: Mon, 20 Aug 2018 05:16:47 -0400 Subject: [PATCH 046/166] added documentation for read command methods (#28748) * added documentation for read command methods * fixed docs (cherry picked from commit f6c48ebf83983016c158f790a466b354ece7addc) --- base/process.jl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/base/process.jl b/base/process.jl index d9b15b2e5bfe3..ef690c454d263 100644 --- a/base/process.jl +++ b/base/process.jl @@ -625,6 +625,11 @@ function open(f::Function, cmds::AbstractCmd, args...) return ret end +""" + read(command::Cmd) + +Run `command` and return the resulting output as an array of bytes. +""" function read(cmd::AbstractCmd) procs = open(cmd, "r", devnull) bytes = read(procs.out) @@ -632,6 +637,11 @@ function read(cmd::AbstractCmd) return bytes end +""" + read(command::Cmd, String) + +Run `command` and return the resulting output as a `String`. +""" read(cmd::AbstractCmd, ::Type{String}) = String(read(cmd)) """ From bfd465bc4626e1abd75ad72c6f012e4c941d764c Mon Sep 17 00:00:00 2001 From: James Shaw Date: Mon, 20 Aug 2018 16:46:04 +0100 Subject: [PATCH 047/166] fix two typos (#28731) (cherry picked from commit 302a507c470ab2b69193b6a071daa477f12d87c2) --- doc/src/manual/variables-and-scoping.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/manual/variables-and-scoping.md b/doc/src/manual/variables-and-scoping.md index 496730a4376fa..ab6f1962be0c6 100644 --- a/doc/src/manual/variables-and-scoping.md +++ b/doc/src/manual/variables-and-scoping.md @@ -495,7 +495,7 @@ are constant by default. Note that `const` only affects the variable binding; the variable may be bound to a mutable object (such as an array), and that object may still be modified. Additionally when one tries -to assign a value a variable that is declared constant the following scenarios are possible: +to assign a value to a variable that is declared constant the following scenarios are possible: * if a new value has a different type than the type of the constant then an error is thrown: ```jldoctest @@ -522,7 +522,7 @@ julia> const z = 100 julia> z = 100 100 ``` -The last rule applies for immutable objects even if the vairable binding would change, e.g.: +The last rule applies for immutable objects even if the variable binding would change, e.g.: ```julia-repl julia> const s1 = "1" "1" From fe7fda36a323016d8a9fe6e373154a6349949bc2 Mon Sep 17 00:00:00 2001 From: annainfo Date: Mon, 20 Aug 2018 19:15:38 +0200 Subject: [PATCH 048/166] Update integers-and-floating-point-numbers.md (#28744) (cherry picked from commit ae0738ebc78a4bb79c709e37371e9d6834a014fa) --- doc/src/manual/integers-and-floating-point-numbers.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/manual/integers-and-floating-point-numbers.md b/doc/src/manual/integers-and-floating-point-numbers.md index b218ab8d582e4..8478d497d91ad 100644 --- a/doc/src/manual/integers-and-floating-point-numbers.md +++ b/doc/src/manual/integers-and-floating-point-numbers.md @@ -215,7 +215,7 @@ UInt128: [0,340282366920938463463374607431768211455] ``` The values returned by [`typemin`](@ref) and [`typemax`](@ref) are always of the given argument -type. (The above expression uses several features we have yet to introduce, including [for loops](@ref man-loops), +type. (The above expression uses several features that have yet to be introduced, including [for loops](@ref man-loops), [Strings](@ref man-strings), and [Interpolation](@ref), but should be easy enough to understand for users with some existing programming experience.) @@ -678,7 +678,7 @@ where syntactic conflicts arise: * The 32-bit floating-point literal expression `1.5f22` could be interpreted as the numeric literal `1.5` multiplied by the variable `f22`. -In all cases, we resolve the ambiguity in favor of interpretation as numeric literals: +In all cases the ambiguity is resolved in favor of interpretation as numeric literals: * Expressions starting with `0x` are always hexadecimal literals. * Expressions starting with a numeric literal followed by `e` or `E` are always floating-point literals. From c0980d10427b24fe4ed45d06614f10a774ba8ed3 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Tue, 21 Aug 2018 06:12:58 -0700 Subject: [PATCH 049/166] Resolve all method ambiguities in LinearAlgebra (#28749) * Add a test to check method ambiguities * Use StridedMatrix to avoid method ambiguity; fixes #27405 * Avoid method ambiguity in promote_leaf_eltypes This change is only for making Test.detect_ambiguities and shouldn't introduce any change in working code (unless it depends on MethodError). Before this change, we have: julia> LinearAlgebra.promote_leaf_eltypes(()) ERROR: MethodError: LinearAlgebra.promote_leaf_eltypes(::Tuple{}) is ambiguous. Candidates: With this change, we have: julia> LinearAlgebra.promote_leaf_eltypes(()) Bool (cherry picked from commit 4498d27c3c3e11effdfdfdce822d025079f01a0a) --- stdlib/LinearAlgebra/src/diagonal.jl | 6 +++--- stdlib/LinearAlgebra/src/generic.jl | 4 ++-- stdlib/LinearAlgebra/test/matmul.jl | 4 ++++ 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/stdlib/LinearAlgebra/src/diagonal.jl b/stdlib/LinearAlgebra/src/diagonal.jl index 2d2557510cca0..1a5eca3c0ce05 100644 --- a/stdlib/LinearAlgebra/src/diagonal.jl +++ b/stdlib/LinearAlgebra/src/diagonal.jl @@ -277,9 +277,9 @@ mul!(out::AbstractVector, A::Diagonal, in::AbstractVector) = out .= A.diag .* in mul!(out::AbstractVector, A::Adjoint{<:Any,<:Diagonal}, in::AbstractVector) = out .= adjoint.(A.parent.diag) .* in mul!(out::AbstractVector, A::Transpose{<:Any,<:Diagonal}, in::AbstractVector) = out .= transpose.(A.parent.diag) .* in -mul!(out::AbstractMatrix, A::Diagonal, in::AbstractMatrix) = out .= A.diag .* in -mul!(out::AbstractMatrix, A::Adjoint{<:Any,<:Diagonal}, in::AbstractMatrix) = out .= adjoint.(A.parent.diag) .* in -mul!(out::AbstractMatrix, A::Transpose{<:Any,<:Diagonal}, in::AbstractMatrix) = out .= transpose.(A.parent.diag) .* in +mul!(out::AbstractMatrix, A::Diagonal, in::StridedMatrix) = out .= A.diag .* in +mul!(out::AbstractMatrix, A::Adjoint{<:Any,<:Diagonal}, in::StridedMatrix) = out .= adjoint.(A.parent.diag) .* in +mul!(out::AbstractMatrix, A::Transpose{<:Any,<:Diagonal}, in::StridedMatrix) = out .= transpose.(A.parent.diag) .* in # ambiguities with Symmetric/Hermitian # RealHermSymComplex[Sym]/[Herm] only include Number; invariant to [c]transpose diff --git a/stdlib/LinearAlgebra/src/generic.jl b/stdlib/LinearAlgebra/src/generic.jl index ea23e8d51cee7..ca747db604fc8 100644 --- a/stdlib/LinearAlgebra/src/generic.jl +++ b/stdlib/LinearAlgebra/src/generic.jl @@ -1324,8 +1324,8 @@ julia> promote_leaf_eltypes(a) Complex{Float64} ``` """ -promote_leaf_eltypes(x::Union{AbstractArray{T},Tuple{Vararg{T}}}) where {T<:Number} = T -promote_leaf_eltypes(x::Union{AbstractArray{T},Tuple{Vararg{T}}}) where {T<:NumberArray} = eltype(T) +promote_leaf_eltypes(x::Union{AbstractArray{T},Tuple{T,Vararg{T}}}) where {T<:Number} = T +promote_leaf_eltypes(x::Union{AbstractArray{T},Tuple{T,Vararg{T}}}) where {T<:NumberArray} = eltype(T) promote_leaf_eltypes(x::T) where {T} = T promote_leaf_eltypes(x::Union{AbstractArray,Tuple}) = mapreduce(promote_leaf_eltypes, promote_type, x; init=Bool) diff --git a/stdlib/LinearAlgebra/test/matmul.jl b/stdlib/LinearAlgebra/test/matmul.jl index 7ac8924e63447..a61445128e263 100644 --- a/stdlib/LinearAlgebra/test/matmul.jl +++ b/stdlib/LinearAlgebra/test/matmul.jl @@ -445,4 +445,8 @@ end @test Xv1'*Xv3' ≈ XcXc end +@testset "method ambiguity" begin + @test detect_ambiguities(LinearAlgebra, Base; imported=true, recursive=true) == [] +end + end # module TestMatmul From 271441b6c89c55e9bf637ba3e4f0bf574cce3f20 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Wed, 22 Aug 2018 12:10:22 +0200 Subject: [PATCH 050/166] improve performance of parse (#28787) (cherry picked from commit 81850b6eaa7cc079005db752d1e381f7fb654196) --- base/parse.jl | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/base/parse.jl b/base/parse.jl index d0037ca6a6574..50b76e0577eb1 100644 --- a/base/parse.jl +++ b/base/parse.jl @@ -106,14 +106,21 @@ function tryparse_internal(::Type{T}, s::AbstractString, startpos::Int, endpos:: return nothing end - base = convert(T,base) - m::T = div(typemax(T)-base+1,base) + base = convert(T, base) + m::T = div(typemax(T) - base + 1, base) n::T = 0 a::Int = base <= 36 ? 10 : 36 + _0 = UInt32('0') + _9 = UInt32('9') + _A = UInt32('A') + _a = UInt32('a') + _Z = UInt32('Z') + _z = UInt32('z') while n <= m - d::T = '0' <= c <= '9' ? c-'0' : - 'A' <= c <= 'Z' ? c-'A'+10 : - 'a' <= c <= 'z' ? c-'a'+a : base + _c = UInt32(c) + d::T = _0 <= _c <= _9 ? _c-_0 : + _A <= _c <= _Z ? _c-_A+ UInt32(10) : + _a <= _c <= _z ? _c-_a+a : base if d >= base raise && throw(ArgumentError("invalid base $base digit $(repr(c)) in $(repr(SubString(s,startpos,endpos)))")) return nothing @@ -129,9 +136,10 @@ function tryparse_internal(::Type{T}, s::AbstractString, startpos::Int, endpos:: end (T <: Signed) && (n *= sgn) while !isspace(c) - d::T = '0' <= c <= '9' ? c-'0' : - 'A' <= c <= 'Z' ? c-'A'+10 : - 'a' <= c <= 'z' ? c-'a'+a : base + _c = UInt32(c) + d::T = _0 <= _c <= _9 ? _c-_0 : + _A <= _c <= _Z ? _c-_A+ UInt32(10) : + _a <= _c <= _z ? _c-_a+a : base if d >= base raise && throw(ArgumentError("invalid base $base digit $(repr(c)) in $(repr(SubString(s,startpos,endpos)))")) return nothing From e49de7c7f8496d1b996dd2ab47fcaaf9fb90617a Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Tue, 21 Aug 2018 20:56:41 -0700 Subject: [PATCH 051/166] Run ambiguity test inside a clean process; fixes 28804 (cherry picked from commit f31e28a50e029942d5d96977f5993defb2f60c13) --- stdlib/LinearAlgebra/test/ambiguous_exec.jl | 4 ++++ stdlib/LinearAlgebra/test/matmul.jl | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 stdlib/LinearAlgebra/test/ambiguous_exec.jl diff --git a/stdlib/LinearAlgebra/test/ambiguous_exec.jl b/stdlib/LinearAlgebra/test/ambiguous_exec.jl new file mode 100644 index 0000000000000..6dce4926f4610 --- /dev/null +++ b/stdlib/LinearAlgebra/test/ambiguous_exec.jl @@ -0,0 +1,4 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + +using Test, LinearAlgebra +@test detect_ambiguities(LinearAlgebra; imported=true, recursive=true) == [] diff --git a/stdlib/LinearAlgebra/test/matmul.jl b/stdlib/LinearAlgebra/test/matmul.jl index a61445128e263..bd1cc3072bc79 100644 --- a/stdlib/LinearAlgebra/test/matmul.jl +++ b/stdlib/LinearAlgebra/test/matmul.jl @@ -446,7 +446,11 @@ end end @testset "method ambiguity" begin - @test detect_ambiguities(LinearAlgebra, Base; imported=true, recursive=true) == [] + # Ambiguity test is run inside a clean process. + # https://github.com/JuliaLang/julia/issues/28804 + script = joinpath(@__DIR__, "ambiguous_exec.jl") + cmd = `$(Base.julia_cmd()) --startup-file=no $script` + @test success(pipeline(cmd; stdout=stdout, stderr=stderr)) end end # module TestMatmul From a8850d051c7c950934ec3cbbff9150938dec3086 Mon Sep 17 00:00:00 2001 From: Nikita Sirgienko Date: Thu, 23 Aug 2018 10:16:28 +0300 Subject: [PATCH 052/166] Update info about `versioninfo` in devdocs (#28810) (cherry picked from commit b411a58b4ef620f9a92770a5cb2deaed87d6beeb) --- doc/src/devdocs/backtraces.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/devdocs/backtraces.md b/doc/src/devdocs/backtraces.md index ca750b79a320d..a65a494bbc3a4 100644 --- a/doc/src/devdocs/backtraces.md +++ b/doc/src/devdocs/backtraces.md @@ -15,10 +15,10 @@ and follow the instructions to generate the debugging information requested. Ta ## [Version/Environment info](@id dev-version-info) No matter the error, we will always need to know what version of Julia you are running. When Julia -first starts up, a header is printed out with a version number and date. Please also include the -output of `versioninfo()` in any report you create: +first starts up, a header is printed out with a version number and date. Please also include the output of `versioninfo()` (exported from the [`InteractiveUtils`](@ref InteractiveUtils.versioninfo) standard library) in any report you create: ```@repl +using InteractiveUtils versioninfo() ``` From 93bce58e933006be8248b2a756ee6790618cd615 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Tue, 21 Aug 2018 14:16:38 +0200 Subject: [PATCH 053/166] doc: change the canonical url to v1 instead of stable. (cherry picked from commit c366143deb8a5a1b279187d822ee3569e466afdc) --- doc/make.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/make.jl b/doc/make.jl index 466d4705814af..126ef0a81eac5 100644 --- a/doc/make.jl +++ b/doc/make.jl @@ -162,7 +162,7 @@ makedocs( analytics = "UA-28835595-6", pages = PAGES, html_prettyurls = ("deploy" in ARGS), - html_canonical = ("deploy" in ARGS) ? "https://docs.julialang.org/en/stable/" : nothing, + html_canonical = ("deploy" in ARGS) ? "https://docs.julialang.org/en/v1/" : nothing, assets = ["assets/julia-manual.css", ] ) From d4020433d9ee095d8cb68f15e5fa290e78697248 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Wed, 22 Aug 2018 23:05:50 +0200 Subject: [PATCH 054/166] Patch Documenter v0.19.6 to create a correct version selector Co-authored-by: Morten Piibeleht Co-authored-by: Fredrik Ekre (cherry picked from commit f9f3c4f45a5b22dacd1bc8d4cde33b5b05550fa6) --- doc/make.jl | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/doc/make.jl b/doc/make.jl index 126ef0a81eac5..e4d849ec167bf 100644 --- a/doc/make.jl +++ b/doc/make.jl @@ -166,6 +166,36 @@ makedocs( assets = ["assets/julia-manual.css", ] ) +# This overloads the function in Documenter that generates versions.js, to include +# v1/ in the version selector, instead of stable/. +# +# The function is identical to the version found in Documenter v0.19.6, except that +# it includes "v1" instead of "stable". +# +# Original: +# https://github.com/JuliaDocs/Documenter.jl/blob/v0.19.6/src/Writers/HTMLWriter.jl#L481-L506 +# +import Documenter.Writers.HTMLWriter: generate_version_file +function generate_version_file(dir::AbstractString) + named_folders = ["v1", "latest"] + tag_folders = [] + for each in readdir(dir) + each == "v1" && continue # skip the v1 symlink + occursin(Base.VERSION_REGEX, each) && push!(tag_folders, each) + end + # sort tags by version number + sort!(tag_folders, lt = (x, y) -> VersionNumber(x) < VersionNumber(y), rev = true) + open(joinpath(dir, "versions.js"), "w") do buf + println(buf, "var DOC_VERSIONS = [") + for group in (named_folders, tag_folders) + for folder in group + println(buf, " \"", folder, "\",") + end + end + println(buf, "];") + end +end + # Only deploy docs from 64bit Linux to avoid committing multiple versions of the same # docs from different workers. if "deploy" in ARGS && Sys.ARCH === :x86_64 && Sys.KERNEL === :Linux From 2a447e73f66cee31df4383e81686d5d444c5e2c1 Mon Sep 17 00:00:00 2001 From: Christian Kurz Date: Thu, 23 Aug 2018 12:00:57 +0200 Subject: [PATCH 055/166] add `Regex` documentation (#28703) add `Regex` documentation. (#26919) (cherry picked from commit 31c9ae94e3767a506ef5ca6cb2043cf1e7b286cd) --- base/regex.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/base/regex.jl b/base/regex.jl index 41745eddd2a21..384d6ca3dfa21 100644 --- a/base/regex.jl +++ b/base/regex.jl @@ -7,6 +7,16 @@ include("pcre.jl") const DEFAULT_COMPILER_OPTS = PCRE.UTF | PCRE.NO_UTF_CHECK | PCRE.ALT_BSUX | PCRE.UCP const DEFAULT_MATCH_OPTS = PCRE.NO_UTF_CHECK +""" + Regex(pattern[, flags]) + +A type representing a regular expression. `Regex` objects can be used to match strings +with [`match`](@ref). + +`Regex` objects can be created using the [`@r_str`](@ref) string macro. The +`Regex(pattern[, flags])` constructor is usually used if the `pattern` string needs +to be interpolated. See the documentation of the string macro for details on flags. +""" mutable struct Regex pattern::String compile_options::UInt32 @@ -81,6 +91,8 @@ listed after the ending quote, to change its behaviour: `\\s`, `\\W`, `\\w`, etc. match based on Unicode character properties. With this option, these sequences only match ASCII characters. +See `Regex` if interpolation is needed. + # Examples ```jldoctest julia> match(r"a+.*b+.*?d\$"ism, "Goodbye,\\nOh, angry,\\nBad world\\n") From a41626c17db0e75f165d59e13acad9f4ad60a765 Mon Sep 17 00:00:00 2001 From: Sukera <11753998+Seelengrab@users.noreply.github.com> Date: Thu, 23 Aug 2018 12:01:59 +0200 Subject: [PATCH 056/166] Added seekstart to getpass in base/util.jl (#28828) (#28832) (cherry picked from commit b6756c52958e0c93da81ab59ed29c5a2e08e0fe8) --- base/util.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/util.jl b/base/util.jl index e3423491aa84d..80c790770af74 100644 --- a/base/util.jl +++ b/base/util.jl @@ -476,7 +476,7 @@ function getpass(input::TTY, output::IO, prompt::AbstractString) write(s, c) end end - return s + return seekstart(s) end else function getpass(input::TTY, output::IO, prompt::AbstractString) From bd573ba995f7bdabafb9512d202b1d4147bb0bd0 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Thu, 23 Aug 2018 12:02:46 +0200 Subject: [PATCH 057/166] make cmp with BigInt return in [-1, 0, 1] (#28780) * make cmp with BigInt return in [-1, 0, 1] (cherry picked from commit 472c178da7069ead7172861923c3f9418ec059ac) --- base/gmp.jl | 8 ++++---- test/bigint.jl | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index d80182646732e..4a7f6945e050d 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -487,13 +487,13 @@ count_ones_abs(x::BigInt) = iszero(x) ? 0 : MPZ.mpn_popcount(x) divrem(x::BigInt, y::BigInt) = MPZ.tdiv_qr(x, y) -cmp(x::BigInt, y::BigInt) = MPZ.cmp(x, y) -cmp(x::BigInt, y::ClongMax) = MPZ.cmp_si(x, y) -cmp(x::BigInt, y::CulongMax) = MPZ.cmp_ui(x, y) +cmp(x::BigInt, y::BigInt) = sign(MPZ.cmp(x, y)) +cmp(x::BigInt, y::ClongMax) = sign(MPZ.cmp_si(x, y)) +cmp(x::BigInt, y::CulongMax) = sign(MPZ.cmp_ui(x, y)) cmp(x::BigInt, y::Integer) = cmp(x, big(y)) cmp(x::Integer, y::BigInt) = -cmp(y, x) -cmp(x::BigInt, y::CdoubleMax) = isnan(y) ? -1 : MPZ.cmp_d(x, y) +cmp(x::BigInt, y::CdoubleMax) = isnan(y) ? -1 : sign(MPZ.cmp_d(x, y)) cmp(x::CdoubleMax, y::BigInt) = -cmp(y, x) isqrt(x::BigInt) = MPZ.sqrt(x) diff --git a/test/bigint.jl b/test/bigint.jl index 01acd5449b8c3..cd4c48f44873d 100644 --- a/test/bigint.jl +++ b/test/bigint.jl @@ -401,3 +401,27 @@ end # Issue #24298 @test mod(BigInt(6), UInt(5)) == mod(6, 5) + +@testset "cmp has values in [-1, 0, 1], issue #28780" begin + # _rand produces values whose log2 is better distributed than rand + _rand(::Type{BigInt}, n=1000) = let x = big(2)^rand(1:rand(1:n)) + rand(-x:x) + end + _rand(F::Type{<:AbstractFloat}) = F(_rand(BigInt, round(Int, log2(floatmax(F))))) + rand(F) + _rand(T) = rand(T) + for T in (Base.BitInteger_types..., BigInt, Float64, Float32, Float16) + @test cmp(big(2)^130, one(T)) === 1 + @test cmp(-big(2)^130, one(T)) === -1 + c = cmp(_rand(BigInt), _rand(T)) + @test c ∈ (-1, 0, 1) + @test c isa Int + (T <: Integer && T !== BigInt) || continue + x = rand(T) + @test cmp(big(2)^130, x) === cmp(x, -big(2)^130) === 1 + @test cmp(-big(2)^130, x) === cmp(x, big(2)^130) === -1 + @test cmp(big(x), x) === cmp(x, big(x)) === 0 + end + c = cmp(_rand(BigInt), _rand(BigInt)) + @test c ∈ (-1, 0, 1) + @test c isa Int +end From 8b90fadc68d2e27cd2a96f13d6603dfbac53cd44 Mon Sep 17 00:00:00 2001 From: Israel Herraiz Date: Thu, 23 Aug 2018 12:03:13 +0200 Subject: [PATCH 058/166] @schedule is deprecated, the code is no longer valid in 1.0 (#28800) * @schedule is deprecated, the code is no longer valid in 1.0 * Additional changes for 1.0 compliance (cherry picked from commit 6d4ff5e7f8fd3bfe033a9d400206e12a7184990c) --- doc/src/manual/parallel-computing.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/src/manual/parallel-computing.md b/doc/src/manual/parallel-computing.md index 5f18d97e75aa4..5ed9d0a795f4e 100644 --- a/doc/src/manual/parallel-computing.md +++ b/doc/src/manual/parallel-computing.md @@ -77,7 +77,7 @@ A channel can be visualized as a pipe, i.e., it has a write end and a read end : # we can schedule `n` instances of `foo` to be active concurrently. for _ in 1:n - @schedule foo() + @async foo() end ``` * Channels are created via the `Channel{T}(sz)` constructor. The channel will only hold objects @@ -184,16 +184,16 @@ julia> function make_jobs(n) julia> n = 12; -julia> @schedule make_jobs(n); # feed the jobs channel with "n" jobs +julia> @async make_jobs(n); # feed the jobs channel with "n" jobs julia> for i in 1:4 # start 4 tasks to process requests in parallel - @schedule do_work() + @async do_work() end julia> @elapsed while n > 0 # print out results job_id, exec_time = take!(results) - println("$job_id finished in $(round(exec_time,2)) seconds") - n = n - 1 + println("$job_id finished in $(round(exec_time; digits=2)) seconds") + global n = n - 1 end 4 finished in 0.22 seconds 3 finished in 0.45 seconds From 58f6dacbc679f54b0a5ee8871c29d2bbb3b2372a Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 23 Aug 2018 15:21:11 -0400 Subject: [PATCH 059/166] fix #28593, macro hygiene problems in type definitions (#28706) (cherry picked from commit cd850de63cce34f53ec9120e04b26bde7e38ac2c) --- src/julia-syntax.scm | 18 +++++++++++++----- src/macroexpand.scm | 36 ++++++++++++++++++++++++++---------- test/syntax.jl | 27 +++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 15 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index abce5e47b6c20..4a3d43613cff1 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -200,9 +200,17 @@ (let ((bounds (map analyze-typevar params))) (values (map car bounds) bounds))) +(define (unmangled-name v) + (if (eq? v '||) + v + (let ((s (string v))) + (if (eqv? (string.char s 0) #\#) + (symbol (last (string-split s "#"))) + v)))) + ;; construct expression to allocate a TypeVar -(define (bounds-to-TypeVar v) - (let ((v (car v)) +(define (bounds-to-TypeVar v (unmangle #f)) + (let ((v ((if unmangle unmangled-name identity) (car v))) (lb (cadr v)) (ub (caddr v))) `(call (core TypeVar) ',v @@ -836,7 +844,7 @@ (block (global ,name) (const ,name) ,@(map (lambda (v) `(local ,v)) params) - ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v))) params bounds) + ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v #t))) params bounds) (struct_type ,name (call (core svec) ,@params) (call (core svec) ,@(map quotify field-names)) ,super (call (core svec) ,@field-types) ,mut ,min-initialized))) @@ -877,7 +885,7 @@ (scope-block (block ,@(map (lambda (v) `(local ,v)) params) - ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v))) params bounds) + ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v #t))) params bounds) (abstract_type ,name (call (core svec) ,@params) ,super)))))) (define (primitive-type-def-expr n name params super) @@ -888,7 +896,7 @@ (scope-block (block ,@(map (lambda (v) `(local ,v)) params) - ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v))) params bounds) + ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v #t))) params bounds) (primitive_type ,name (call (core svec) ,@params) ,n ,super)))))) ;; take apart a type signature, e.g. T{X} <: S{Y} diff --git a/src/macroexpand.scm b/src/macroexpand.scm index 2c7a040e39f53..abad3407656fd 100644 --- a/src/macroexpand.scm +++ b/src/macroexpand.scm @@ -135,16 +135,21 @@ (if var (list 'varlist var) '())) ;; type definition - (pattern-lambda (struct mut (<: (curly tn . tvars) super) body) - (list* 'varlist (cons (unescape tn) (unescape tn)) '(new . new) - (typevar-names tvars))) - (pattern-lambda (struct mut (curly tn . tvars) body) - (list* 'varlist (cons (unescape tn) (unescape tn)) '(new . new) - (typevar-names tvars))) - (pattern-lambda (struct mut (<: tn super) body) - (list 'varlist (cons (unescape tn) (unescape tn)) '(new . new))) - (pattern-lambda (struct mut tn body) - (list 'varlist (cons (unescape tn) (unescape tn)) '(new . new))) + (pattern-lambda (struct mut spec body) + (let ((tn (typedef-expr-name spec)) + (tv (typedef-expr-tvars spec))) + (list* 'varlist (cons (unescape tn) (unescape tn)) '(new . new) + (typevar-names tv)))) + (pattern-lambda (abstract spec) + (let ((tn (typedef-expr-name spec)) + (tv (typedef-expr-tvars spec))) + (list* 'varlist (cons (unescape tn) (unescape tn)) + (typevar-names tv)))) + (pattern-lambda (primitive spec nb) + (let ((tn (typedef-expr-name spec)) + (tv (typedef-expr-tvars spec))) + (list* 'varlist (cons (unescape tn) (unescape tn)) + (typevar-names tv)))) )) ; vars-introduced-by-patterns @@ -178,6 +183,17 @@ (cadr e) e)) +(define (typedef-expr-name e) + (cond ((atom? e) e) + ((or (eq? (car e) 'curly) (eq? (car e) '<:)) (typedef-expr-name (cadr e))) + (else e))) + +(define (typedef-expr-tvars e) + (cond ((atom? e) '()) + ((eq? (car e) '<:) (typedef-expr-tvars (cadr e))) + ((eq? (car e) 'curly) (cddr e)) + (else '()))) + (define (typevar-expr-name e) (car (analyze-typevar e))) ;; get the list of names from a list of `where` variable expressions diff --git a/test/syntax.jl b/test/syntax.jl index 4e4417dd5a3b6..9e12206ad8325 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -1646,3 +1646,30 @@ end # issue #28576 @test Meta.isexpr(Meta.parse("1 == 2 ?"), :incomplete) @test Meta.isexpr(Meta.parse("1 == 2 ? 3 :"), :incomplete) + +# issue #28593 +macro a28593() + quote + abstract type A28593{S<:Real, V<:AbstractVector{S}} end + end +end + +macro b28593() + quote + struct B28593{S<:Real, V<:AbstractVector{S}} end + end +end + +macro c28593() + quote + primitive type C28593{S<:Real, V<:AbstractVector{S}} 32 end + end +end + +@a28593 +@b28593 +@c28593 + +@test A28593.var.name === :S +@test B28593.var.name === :S +@test C28593.var.name === :S From a1e78c1bd737ef10cb06675ffc40f18f0d52d1b4 Mon Sep 17 00:00:00 2001 From: tchr Date: Thu, 23 Aug 2018 15:00:26 -0400 Subject: [PATCH 060/166] fix doc-string references to bit-rotted variables x(->v) and v(->itr) in var, varm, std, stdm, & quantiles (cherry picked from commit 157fb343200e00abad048c47fc83de214532ac5c) --- stdlib/Statistics/src/Statistics.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/stdlib/Statistics/src/Statistics.jl b/stdlib/Statistics/src/Statistics.jl index 28d2cae7837e3..bc7a857079e88 100644 --- a/stdlib/Statistics/src/Statistics.jl +++ b/stdlib/Statistics/src/Statistics.jl @@ -248,7 +248,7 @@ end Compute the sample variance of a collection `v` with known mean(s) `m`, optionally over the given dimensions. `m` may contain means for each dimension of `v`. If `corrected` is `true`, then the sum is scaled with `n-1`, -whereas the sum is scaled with `n` if `corrected` is `false` where `n = length(x)`. +whereas the sum is scaled with `n` if `corrected` is `false` where `n = length(v)`. !!! note If array contains `NaN` or [`missing`](@ref) values, the result is also @@ -278,7 +278,7 @@ The algorithm will return an estimator of the generative distribution's variance under the assumption that each entry of `v` is an IID drawn from that generative distribution. This computation is equivalent to calculating `sum(abs2, v - mean(v)) / (length(v) - 1)`. If `corrected` is `true`, then the sum is scaled with `n-1`, -whereas the sum is scaled with `n` if `corrected` is `false` where `n = length(x)`. +whereas the sum is scaled with `n` if `corrected` is `false` where `n = length(v)`. The mean `mean` over the region may be provided. !!! note @@ -345,7 +345,7 @@ deviation under the assumption that each entry of `v` is an IID drawn from that distribution. This computation is equivalent to calculating `sqrt(sum((v - mean(v)).^2) / (length(v) - 1))`. A pre-computed `mean` may be provided. If `corrected` is `true`, then the sum is scaled with `n-1`, whereas the sum is scaled with `n` if `corrected` is -`false` where `n = length(x)`. +`false` where `n = length(v)`. !!! note If array contains `NaN` or [`missing`](@ref) values, the result is also @@ -376,7 +376,7 @@ std(iterable; corrected::Bool=true, mean=nothing) = Compute the sample standard deviation of a vector `v` with known mean `m`. If `corrected` is `true`, then the sum is scaled with `n-1`, whereas the sum is -scaled with `n` if `corrected` is `false` where `n = length(x)`. +scaled with `n` if `corrected` is `false` where `n = length(v)`. !!! note If array contains `NaN` or [`missing`](@ref) values, the result is also @@ -882,7 +882,7 @@ probabilities `p` on the interval [0,1]. The keyword argument `sorted` indicates `itr` can be assumed to be sorted. Quantiles are computed via linear interpolation between the points `((k-1)/(n-1), v[k])`, -for `k = 1:n` where `n = length(v)`. This corresponds to Definition 7 of Hyndman and Fan +for `k = 1:n` where `n = length(itr)`. This corresponds to Definition 7 of Hyndman and Fan (1996), and is the same as the R default. !!! note From 75b052f1091993753a7886f97a647b051c58ff3a Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Fri, 24 Aug 2018 21:12:14 +0200 Subject: [PATCH 061/166] Absolutify project path specified with --project and JULIA_PROJECT. (#28625) (cherry picked from commit eb8a9333b040b8dc86b2ed7a93bb23e70830cf14) --- base/initdefs.jl | 3 ++- src/init.c | 2 ++ test/loading.jl | 16 ++++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/base/initdefs.jl b/base/initdefs.jl index 0846a47534886..d93590af4d63c 100644 --- a/base/initdefs.jl +++ b/base/initdefs.jl @@ -138,8 +138,9 @@ function init_load_path() unsafe_string(Base.JLOptions().project) : get(ENV, "JULIA_PROJECT", nothing)) HOME_PROJECT[] = + project == nothing ? nothing : project == "" ? nothing : - project == "@." ? current_project() : project + project == "@." ? current_project() : abspath(project) append!(empty!(LOAD_PATH), paths) end diff --git a/src/init.c b/src/init.c index b293ab1a44b88..64a82792b685f 100644 --- a/src/init.c +++ b/src/init.c @@ -592,6 +592,8 @@ static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel) jl_options.outputbc = abspath(jl_options.outputbc, 0); if (jl_options.machine_file) jl_options.machine_file = abspath(jl_options.machine_file, 0); + if (jl_options.project && strncmp(jl_options.project, "@.", strlen(jl_options.project)) != 0) + jl_options.project = abspath(jl_options.project, 0); const char **cmdp = jl_options.cmds; if (cmdp) { diff --git a/test/loading.jl b/test/loading.jl index 289c25e582b0a..259f55a87c999 100644 --- a/test/loading.jl +++ b/test/loading.jl @@ -547,6 +547,22 @@ finally popfirst!(LOAD_PATH) end +@testset "--project and JULIA_PROJECT paths should be absolutified" begin + mktempdir() do dir; cd(dir) do + mkdir("foo") + script = """ + using Test + old = Base.active_project() + cd("foo") + @test Base.active_project() == old + """ + @test success(`$(Base.julia_cmd()) --project=foo -e $(script)`) + withenv("JULIA_PROJECT" => "foo") do + @test success(`$(Base.julia_cmd()) -e $(script)`) + end + end; end +end + ## cleanup after tests ## for env in keys(envs) From de44505b43a07067cd7af343c8529d8aaeec5858 Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Fri, 24 Aug 2018 23:56:39 +0300 Subject: [PATCH 062/166] Make sure iterate(::Tuple) does not throw (#28847) (cherry picked from commit 35c67e5fd81c21eef1dc8d05d22ad99af5f9728f) --- base/tuple.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/tuple.jl b/base/tuple.jl index 987b6764f1401..518715644f677 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -38,7 +38,7 @@ _setindex(v, i::Integer) = () ## iterating ## -iterate(t::Tuple, i::Int=1) = length(t) < i ? nothing : (t[i], i+1) +iterate(@nospecialize(t::Tuple), i::Int=1) = 1 <= i <= length(t) ? (@inbounds t[i], i+1) : nothing keys(@nospecialize t::Tuple) = OneTo(length(t)) From e727600a1c368f3c438d884df108ff1a0760cf74 Mon Sep 17 00:00:00 2001 From: Seth Bromberger Date: Fri, 24 Aug 2018 15:25:31 -0700 Subject: [PATCH 063/166] Support ranges with different integer widths in `preduce` (#28651) (cherry picked from commit 145224f3318af5178573c2771216b2d08814e5eb) --- stdlib/Distributed/src/macros.jl | 2 +- stdlib/Distributed/test/distributed_exec.jl | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/stdlib/Distributed/src/macros.jl b/stdlib/Distributed/src/macros.jl index f04ad345f10bc..15faadb3c31fa 100644 --- a/stdlib/Distributed/src/macros.jl +++ b/stdlib/Distributed/src/macros.jl @@ -251,7 +251,7 @@ end function preduce(reducer, f, R) N = length(R) - chunks = splitrange(N, nworkers()) + chunks = splitrange(Int(N), nworkers()) all_w = workers()[1:length(chunks)] w_exec = Task[] diff --git a/stdlib/Distributed/test/distributed_exec.jl b/stdlib/Distributed/test/distributed_exec.jl index f17d97697c27e..383a6783a311d 100644 --- a/stdlib/Distributed/test/distributed_exec.jl +++ b/stdlib/Distributed/test/distributed_exec.jl @@ -1527,6 +1527,14 @@ end a27933 = :_not_defined_27933 @test remotecall_fetch(()->a27933, first(workers())) === a27933 +# PR #28651 +for T in (UInt8, Int8, UInt16, Int16, UInt32, Int32, UInt64) + n = @distributed (+) for i in Base.OneTo(T(10)) + i + end + @test n == 55 +end + # Run topology tests last after removing all workers, since a given # cluster at any time only supports a single topology. rmprocs(workers()) From 19e0a354e1e8828686ed80f602457694dabe68b7 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Sat, 25 Aug 2018 17:45:59 +0200 Subject: [PATCH 064/166] fix doccing call overload without named argument (#28875) (cherry picked from commit 7e1f739d3c628e387cc5827a35ca086fc17006c6) --- base/docs/Docs.jl | 2 +- test/docs.jl | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/base/docs/Docs.jl b/base/docs/Docs.jl index c9de490bcb67f..d409eea9a6ca8 100644 --- a/base/docs/Docs.jl +++ b/base/docs/Docs.jl @@ -281,7 +281,7 @@ function astname(x::Expr, ismacro::Bool) ismacro ? macroname(x) : x # Call overloading, e.g. `(a::A)(b) = b` or `function (a::A)(b) b end` should document `A(b)` elseif (isexpr(x, :function) || isexpr(x, :(=))) && isexpr(x.args[1], :call) && isexpr(x.args[1].args[1], :(::)) - return astname(x.args[1].args[1].args[2], ismacro) + return astname(x.args[1].args[1].args[end], ismacro) else n = isexpr(x, (:module, :struct)) ? 2 : 1 astname(x.args[n], ismacro) diff --git a/test/docs.jl b/test/docs.jl index 3a925d65a4334..c6cbb3847ae28 100644 --- a/test/docs.jl +++ b/test/docs.jl @@ -1121,6 +1121,13 @@ struct A_20087 end @test docstrings_equal(@doc(A_20087()), doc"a") +struct B_20087 end + +"""b""" +(::B_20087)() = a + +@test docstrings_equal(@doc(B_20087()), doc"b") + # issue #27832 _last_atdoc = Core.atdoc From f7a1099ca3da56c950b6f5d2b6c39f6e95cafefd Mon Sep 17 00:00:00 2001 From: Ronan Arraes Jardim Chagas Date: Sat, 25 Aug 2018 12:46:24 -0300 Subject: [PATCH 065/166] Fix note tag in the documentation (#28877) (cherry picked from commit a5bfabccd8d9c351cc3b0026992fe7314ff022db) --- doc/src/manual/performance-tips.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/performance-tips.md b/doc/src/manual/performance-tips.md index cd81e9eaf0c59..a3e08d63ad605 100644 --- a/doc/src/manual/performance-tips.md +++ b/doc/src/manual/performance-tips.md @@ -1151,7 +1151,7 @@ The common idiom of using 1:n to index into an AbstractArray is not safe if the and may cause a segmentation fault if bounds checking is turned off. Use `LinearIndices(x)` or `eachindex(x)` instead (see also [offset-arrays](https://docs.julialang.org/en/latest/devdocs/offset-arrays)). -!!!note +!!! note While `@simd` needs to be placed directly in front of an innermost `for` loop, both `@inbounds` and `@fastmath` can be applied to either single expressions or all the expressions that appear within nested blocks of code, e.g., using `@inbounds begin` or `@inbounds for ...`. From 66c438bfab542da4e2e0ba56507ca88537788184 Mon Sep 17 00:00:00 2001 From: Jan Magnusson Date: Sun, 26 Aug 2018 11:50:28 +0200 Subject: [PATCH 066/166] improve docstring of pathof (#28817) * improve docstring of pathof (cherry picked from commit 304cbd991a84f981d160bdaeca7cdf8e762ba5cd) --- base/loading.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/base/loading.jl b/base/loading.jl index f55f75498d90e..18a8765d68480 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -254,6 +254,9 @@ locate_package(::Nothing) = nothing Return the path of `m.jl` file that was used to `import` module `m`, or `nothing` if `m` was not imported from a package. + +Use [`dirname`](@ref) to get the directory part and [`basename`](@ref) +to get the file name part of the path. """ function pathof(m::Module) pkgid = get(Base.module_keys, m, nothing) From 7248d44de0300d6652fbb142f7bd2d2f22aef44f Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 26 Aug 2018 04:51:56 -0500 Subject: [PATCH 067/166] issubset: check IteratorSize trait before calling length (#28871) (cherry picked from commit 24de931f41d205574b00e89b12388691210add3f) --- base/abstractset.jl | 17 +++++++++-------- test/sets.jl | 13 +++++++++++++ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/base/abstractset.jl b/base/abstractset.jl index 2c2ec47c0c041..100383a126a1d 100644 --- a/base/abstractset.jl +++ b/base/abstractset.jl @@ -226,14 +226,15 @@ end <=(l::AbstractSet, r::AbstractSet) = l ⊆ r function issubset(l, r) - - rlen = length(r) - #This threshold was empirically determined by repeatedly - #sampling using these two methods. - lenthresh = 70 - - if rlen > lenthresh && !isa(r, AbstractSet) - return issubset(l, Set(r)) + if haslength(r) + rlen = length(r) + #This threshold was empirically determined by repeatedly + #sampling using these two methods (see #26198) + lenthresh = 70 + + if rlen > lenthresh && !isa(r, AbstractSet) + return issubset(l, Set(r)) + end end for elt in l diff --git a/test/sets.jl b/test/sets.jl index ea523d43afb72..35155633abb9d 100644 --- a/test/sets.jl +++ b/test/sets.jl @@ -604,3 +604,16 @@ end end end end + +struct OpenInterval{T} + lower::T + upper::T +end +Base.in(x, i::OpenInterval) = i.lower < x < i.upper +Base.IteratorSize(::Type{<:OpenInterval}) = Base.SizeUnknown() + +@testset "Continuous sets" begin + i = OpenInterval(2, 4) + @test 3 ∈ i + @test issubset(3, i) +end From 30f03c6feb5fe5ea3cb8c4de889ef41df54d6b00 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Sun, 26 Aug 2018 12:16:46 +0200 Subject: [PATCH 068/166] improve performance for string(...) (#28876) * improve performance for various string methods (cherry picked from commit 731424953a325323fce325afa4c36433d96e2b51) --- base/strings/io.jl | 38 +++++++++++++++++++++++++------------- base/strings/substring.jl | 31 ++++++++++++++++++++++--------- test/strings/basic.jl | 1 + 3 files changed, 48 insertions(+), 22 deletions(-) diff --git a/base/strings/io.jl b/base/strings/io.jl index 64b9a613c084e..e2a759c473189 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -103,31 +103,43 @@ function sprint(f::Function, args...; context=nothing, sizehint::Integer=0) String(resize!(s.data, s.size)) end -tostr_sizehint(x) = 0 +tostr_sizehint(x) = 8 tostr_sizehint(x::AbstractString) = lastindex(x) tostr_sizehint(x::Float64) = 20 tostr_sizehint(x::Float32) = 12 -function print_to_string(xs...; env=nothing) +function print_to_string(xs...) if isempty(xs) return "" end + siz = 0 + for x in xs + siz += tostr_sizehint(x) + end # specialized for performance reasons - s = IOBuffer(sizehint=tostr_sizehint(xs[1])) - if env !== nothing - env_io = IOContext(s, env) - for x in xs - print(env_io, x) - end - else - for x in xs - print(s, x) - end + s = IOBuffer(sizehint=siz) + for x in xs + print(s, x) end String(resize!(s.data, s.size)) end -string_with_env(env, xs...) = print_to_string(xs...; env=env) +function string_with_env(env, xs...) + if isempty(xs) + return "" + end + siz = 0 + for x in xs + siz += tostr_sizehint(x) + end + # specialized for performance reasons + s = IOBuffer(sizehint=siz) + env_io = IOContext(s, env) + for x in xs + print(env_io, x) + end + String(resize!(s.data, s.size)) +end """ string(xs...) diff --git a/base/strings/substring.jl b/base/strings/substring.jl index d6fba1b41c9bf..9b9e0d1e7424b 100644 --- a/base/strings/substring.jl +++ b/base/strings/substring.jl @@ -142,19 +142,32 @@ function reverse(s::Union{String,SubString{String}})::String end end -function string(a::Union{String, SubString{String}}...) - if length(a) == 1 - return String(a[1]) - end +string(a::String) = String(a) +string(a::SubString{String}) = String(a) + +function string(a::Union{Char, String, SubString{String}}...) n = 0 - for str in a - n += sizeof(str) + for v in a + if v isa Char + n += codelen(v) + else + n += sizeof(v) + end end out = _string_n(n) offs = 1 - for str in a - unsafe_copyto!(pointer(out,offs), pointer(str), sizeof(str)) - offs += sizeof(str) + for v in a + if v isa Char + x = bswap(reinterpret(UInt32, v)) + for j in 1:codelen(v) + unsafe_store!(pointer(out, offs), x % UInt8) + offs += 1 + x >>= 8 + end + else + unsafe_copyto!(pointer(out,offs), pointer(v), sizeof(v)) + offs += sizeof(v) + end end return out end diff --git a/test/strings/basic.jl b/test/strings/basic.jl index 034d45bee9596..521dfa6d52b99 100644 --- a/test/strings/basic.jl +++ b/test/strings/basic.jl @@ -34,6 +34,7 @@ using Random @test string("∀∃", "1∀∃") === "∀∃1∀∃" @test string(SubString("∀∃"), SubString("1∀∃", 2)) === "∀∃∀∃" @test string(s"123") === s"123" + @test string("123", 'α', SubString("1∀∃", 2), 'a', "foo") === "123α∀∃afoo" codegen_egal_of_strings(x, y) = (x===y, x!==y) @test codegen_egal_of_strings(string("ab", 'c'), "abc") === (true, false) let strs = ["", "a", "a b c", "до свидания"] From e76071d72e9ba2ffff4741210c9710fbcac69da9 Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Sun, 26 Aug 2018 12:17:16 +0200 Subject: [PATCH 069/166] Compare Symbols and Chars more efficiently in Cholesky (#28873) (cherry picked from commit a2a1506b6e4174e4dc2489b04dece3b7d66c973d) --- stdlib/LinearAlgebra/src/cholesky.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stdlib/LinearAlgebra/src/cholesky.jl b/stdlib/LinearAlgebra/src/cholesky.jl index 3e95a92d3a0d4..5db318fabf999 100644 --- a/stdlib/LinearAlgebra/src/cholesky.jl +++ b/stdlib/LinearAlgebra/src/cholesky.jl @@ -340,11 +340,11 @@ function getproperty(C::Cholesky, d::Symbol) Cuplo = getfield(C, :uplo) info = getfield(C, :info) if d == :U - return UpperTriangular(Symbol(Cuplo) == d ? Cfactors : copy(Cfactors')) + return UpperTriangular(Cuplo === char_uplo(d) ? Cfactors : copy(Cfactors')) elseif d == :L - return LowerTriangular(Symbol(Cuplo) == d ? Cfactors : copy(Cfactors')) + return LowerTriangular(Cuplo === char_uplo(d) ? Cfactors : copy(Cfactors')) elseif d == :UL - return (Symbol(Cuplo) == :U ? UpperTriangular(Cfactors) : LowerTriangular(Cfactors)) + return (Cuplo === 'U' ? UpperTriangular(Cfactors) : LowerTriangular(Cfactors)) else return getfield(C, d) end From 67ee2733ae48f1a90dbc63c153ad3dfb2ae344f8 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Mon, 27 Aug 2018 10:15:56 +0200 Subject: [PATCH 070/166] accumulate: fix typo in docstring (cherry picked from commit 5013cfa897bf175e8c6bad4907b89cb534b32080) --- base/accumulate.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/accumulate.jl b/base/accumulate.jl index 1f30250f44ee5..74c1c3a8c58e0 100644 --- a/base/accumulate.jl +++ b/base/accumulate.jl @@ -191,7 +191,7 @@ cumprod(x::AbstractVector) = cumprod(x, dims=1) accumulate(op, A; dims::Integer, [init]) Cumulative operation `op` along the dimension `dims` of `A` (providing `dims` is optional -for vectors). An inital value `init` may optionally be privided by a keyword argument. See +for vectors). An inital value `init` may optionally be provided by a keyword argument. See also [`accumulate!`](@ref) to use a preallocated output array, both for performance and to control the precision of the output (e.g. to avoid overflow). For common operations there are specialized variants of `accumulate`, see: [`cumsum`](@ref), [`cumprod`](@ref) From eda9f051c1a60b2d9c3bb1c4990e1fd7de01ae0a Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Mon, 27 Aug 2018 12:53:42 +0200 Subject: [PATCH 071/166] fix typo in append! doc (cherry picked from commit 3ab56f19a81a1d658a02750b48abbd63950ef248) --- base/array.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/array.jl b/base/array.jl index 7559c29ab1d9d..a6364188b8977 100644 --- a/base/array.jl +++ b/base/array.jl @@ -888,7 +888,7 @@ julia> append!([1, 2, 3], [4, 5, 6]) ``` Use [`push!`](@ref) to add individual items to `collection` which are not already -themselves in another collection. The result is of the preceding example is equivalent to +themselves in another collection. The result of the preceding example is equivalent to `push!([1, 2, 3], 4, 5, 6)`. """ function append!(a::Array{<:Any,1}, items::AbstractVector) From 255171e87b435f9d61d3cb28f90804573d369753 Mon Sep 17 00:00:00 2001 From: timkittel <19408882+timkittel@users.noreply.github.com> Date: Wed, 29 Aug 2018 23:26:31 +0200 Subject: [PATCH 072/166] removed outdated paragraph on automatic broadcasting for binary operators (#28950) (cherry picked from commit bd1e46a6774120b4e42f477b3276102ba542da52) --- doc/src/manual/arrays.md | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/doc/src/manual/arrays.md b/doc/src/manual/arrays.md index de54a61617717..4b4c4be24a7ac 100644 --- a/doc/src/manual/arrays.md +++ b/doc/src/manual/arrays.md @@ -692,12 +692,7 @@ The following operators are supported for arrays: 2. Binary arithmetic -- `-`, `+`, `*`, `/`, `\`, `^` 3. Comparison -- `==`, `!=`, `≈` ([`isapprox`](@ref)), `≉` -Most of the binary arithmetic operators listed above also operate elementwise -when one argument is scalar: `-`, `+`, and `*` when either argument is scalar, -and `/` and `\` when the denominator is scalar. For example, `[1, 2] + 3 == [4, 5]` -and `[6, 4] / 2 == [3, 2]`. - -Additionally, to enable convenient vectorization of mathematical and other operations, +To enable convenient vectorization of mathematical and other operations, Julia [provides the dot syntax](@ref man-vectorized) `f.(args...)`, e.g. `sin.(x)` or `min.(x,y)`, for elementwise operations over arrays or mixtures of arrays and scalars (a [Broadcasting](@ref) operation); these have the additional advantage of From 664ea94333102f5a06bbf7d408bea16154b1753d Mon Sep 17 00:00:00 2001 From: Israel Herraiz Date: Wed, 29 Aug 2018 23:26:58 +0200 Subject: [PATCH 073/166] Fix call to round for Julia 1.0 (#28944) (cherry picked from commit 2346be896129f594ce2e6104f612828468e63bfc) --- doc/src/manual/parallel-computing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/parallel-computing.md b/doc/src/manual/parallel-computing.md index 5ed9d0a795f4e..d8942ebd2567e 100644 --- a/doc/src/manual/parallel-computing.md +++ b/doc/src/manual/parallel-computing.md @@ -1086,7 +1086,7 @@ julia> for p in workers() # start tasks on the workers to process requests in pa julia> @elapsed while n > 0 # print out results job_id, exec_time, where = take!(results) - println("$job_id finished in $(round(exec_time,2)) seconds on worker $where") + println("$job_id finished in $(round(exec_time; digits=2)) seconds on worker $where") n = n - 1 end 1 finished in 0.18 seconds on worker 4 From 8791fc1cdbf88a8354cf95e330d6b03ef3321709 Mon Sep 17 00:00:00 2001 From: Andrew Janke Date: Wed, 29 Aug 2018 15:55:16 -0400 Subject: [PATCH 074/166] Getting Started: Capitalize "CPU" for consistency (cherry picked from commit 8555aa0aa388f1f94fe2dd7b7621837f46e60939) --- doc/src/manual/getting-started.md | 2 +- src/jloptions.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/manual/getting-started.md b/doc/src/manual/getting-started.md index b41eab692e6e1..b648cf8699470 100644 --- a/doc/src/manual/getting-started.md +++ b/doc/src/manual/getting-started.md @@ -111,7 +111,7 @@ julia [switches] -- [programfile] [args...] |`--history-file={yes\|no}` |Load or save history| |`--depwarn={yes\|no\|error}` |Enable or disable syntax and method deprecation warnings (`error` turns warnings into errors)| |`--warn-overwrite={yes\|no}` |Enable or disable method overwrite warnings| -|`-C`, `--cpu-target ` |Limit usage of cpu features up to ; set to `help` to see the available options| +|`-C`, `--cpu-target ` |Limit usage of CPU features up to ``; set to `help` to see the available options| |`-O`, `--optimize={0,1,2,3}` |Set the optimization level (default level is 2 if unspecified or 3 if used without a level)| |`-g`, `-g ` |Enable / Set the level of debug info generation (default level is 1 if unspecified or 2 if used without a level)| |`--inline={yes\|no}` |Control whether inlining is permitted, including overriding `@inline` declarations| diff --git a/src/jloptions.c b/src/jloptions.c index 8f885179601f3..83c5121a5bff5 100644 --- a/src/jloptions.c +++ b/src/jloptions.c @@ -110,7 +110,7 @@ static const char opts[] = // code generation options //" --compile={yes|no|all|min}Enable or disable JIT compiler, or request exhaustive compilation\n" - " -C, --cpu-target Limit usage of cpu features up to ; set to \"help\" to see the available options\n" + " -C, --cpu-target Limit usage of CPU features up to ; set to \"help\" to see the available options\n" " -O, --optimize={0,1,2,3} Set the optimization level (default level is 2 if unspecified or 3 if used without a level)\n" " -g, -g Enable / Set the level of debug info generation" #ifdef JL_DEBUG_BUILD From 51f6390197e5cdcef41c18aa4aca26293fe11298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=AE=9E=E5=94=AF?= Date: Thu, 30 Aug 2018 11:56:04 +0800 Subject: [PATCH 075/166] fix typo in `?@specialize` (cherry picked from commit dabf70e6fe1a64717bada0ede58aebd63bbd81c0) --- base/essentials.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/essentials.jl b/base/essentials.jl index edd7e75d2f949..35a52e592434e 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -79,7 +79,7 @@ end @specialize Reset the specialization hint for an argument back to the default. -For details, see [`@specialize`](@ref). +For details, see [`@nospecialize`](@ref). """ macro specialize(vars...) if nfields(vars) === 1 From a16b7f40347cf4b423b9c33ebebfcad13840c35f Mon Sep 17 00:00:00 2001 From: angusmoore <18376371+angusmoore@users.noreply.github.com> Date: Sun, 2 Sep 2018 09:49:25 +1000 Subject: [PATCH 076/166] Cross reference hasmethod with applicable in docs (#28918) (cherry picked from commit c36c7ff34530c96af5ca95e6b15621ae09165062) --- base/docs/basedocs.jl | 2 ++ base/reflection.jl | 2 ++ 2 files changed, 4 insertions(+) diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 80100bfb6b3e4..062a9e554aa9a 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -1083,6 +1083,8 @@ InterruptException Determine whether the given generic function has a method applicable to the given arguments. +See also [`hasmethod`](@ref). + # Examples ```jldoctest julia> function f(x, y) diff --git a/base/reflection.jl b/base/reflection.jl index 25de43a3270dd..2382766b743d0 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -1008,6 +1008,8 @@ end Determine whether the given generic function has a method matching the given `Tuple` of argument types with the upper bound of world age given by `world`. +See also [`applicable`](@ref). + # Examples ```jldoctest julia> hasmethod(length, Tuple{Array}) From eefe789ce2bda5db101b7656f31976943c31e118 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Sat, 1 Sep 2018 16:50:31 -0700 Subject: [PATCH 077/166] Fix spelling of kernel in html id (#28936) (cherry picked from commit 5ee5de48214d163f6c709045ee7e6ecb50b3ef68) --- doc/src/manual/performance-tips.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/src/manual/performance-tips.md b/doc/src/manual/performance-tips.md index a3e08d63ad605..b830f34a07b1d 100644 --- a/doc/src/manual/performance-tips.md +++ b/doc/src/manual/performance-tips.md @@ -467,7 +467,7 @@ end ``` the annotation of `c` harms performance. To write performant code involving types constructed at -run-time, use the [function-barrier technique](@ref kernal-functions) discussed below, and ensure +run-time, use the [function-barrier technique](@ref kernel-functions) discussed below, and ensure that the constructed type appears among the argument types of the kernel function so that the kernel operations are properly specialized by the compiler. For example, in the above snippet, as soon as `b` is constructed, it can be passed to another function `k`, the kernel. If, for example, function @@ -576,7 +576,7 @@ optimize the body of the loop. There are several possible fixes: * Use an explicit conversion: `x = oneunit(Float64)` * Initialize with the first loop iteration, to `x = 1 / rand()`, then loop `for i = 2:10` -## [Separate kernel functions (aka, function barriers)](@id kernal-functions) +## [Separate kernel functions (aka, function barriers)](@id kernel-functions) Many functions follow a pattern of performing some set-up work, and then running many iterations to perform a core computation. Where possible, it is a good idea to put these core computations @@ -675,7 +675,7 @@ does not (and cannot) predict its value in advance. This means that code using t function has to be conservative, checking the type on each access of `A`; such code will be very slow. -Now, one very good way to solve such problems is by using the [function-barrier technique](@ref kernal-functions). +Now, one very good way to solve such problems is by using the [function-barrier technique](@ref kernel-functions). However, in some cases you might want to eliminate the type-instability altogether. In such cases, one approach is to pass the dimensionality as a parameter, for example through `Val{T}()` (see ["Value types"](@ref)): From 718b5608792036a2f7705d1b21bd90334b495f1d Mon Sep 17 00:00:00 2001 From: Stephan Hilb Date: Sun, 2 Sep 2018 13:27:46 +0200 Subject: [PATCH 078/166] doc/faq: move question to correct section (#28997) (cherry picked from commit f77c36bc7511fd384388561c69c0e79546e2aeae) --- doc/src/manual/faq.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/doc/src/manual/faq.md b/doc/src/manual/faq.md index 192aa287689fd..63011925ad498 100644 --- a/doc/src/manual/faq.md +++ b/doc/src/manual/faq.md @@ -41,6 +41,12 @@ obj3 = MyModule.someotherfunction(obj2, c) ... ``` +### How do I check if the current file is being run as the main script? + +When a file is run as the main script using `julia file.jl` one might want to activate extra +functionality like command line argument handling. A way to determine that a file is run in +this fashion is to check if `abspath(PROGRAM_FILE) == @__FILE__` is `true`. + ## Functions ### I passed an argument `x` to a function, modified it inside that function, but on the outside, the variable `x` is still unchanged. Why? @@ -645,13 +651,6 @@ as nothing but rather a tuple of zero values. The empty (or "bottom") type, written as `Union{}` (an empty union type), is a type with no values and no subtypes (except itself). You will generally not need to use this type. - -### How do I check if the current file is being run as the main script? - -When a file is run as the main script using `julia file.jl` one might want to activate extra -functionality like command line argument handling. A way to determine that a file is run in -this fashion is to check if `abspath(PROGRAM_FILE) == @__FILE__` is `true`. - ## Memory ### Why does `x += y` allocate memory when `x` and `y` are arrays? From d610b848f178190a51ad20688d41316ec517f18d Mon Sep 17 00:00:00 2001 From: Jan Magnusson Date: Mon, 3 Sep 2018 10:58:15 +0200 Subject: [PATCH 079/166] Docs for logging: write to file (#28927) * write log to file * Use julia-repl for highlighting, fix indentation (cherry picked from commit 2e603aabdf10f1ae4c28d2830232ed74f339d106) --- stdlib/Logging/docs/src/index.md | 37 ++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/stdlib/Logging/docs/src/index.md b/stdlib/Logging/docs/src/index.md index ba07f6602f3ae..bed0b1b0d2e98 100644 --- a/stdlib/Logging/docs/src/index.md +++ b/stdlib/Logging/docs/src/index.md @@ -193,6 +193,43 @@ Similarly, the environment variable can be used to enable debug logging of modules, such as `Pkg`, or module roots (see [`Base.moduleroot`](@ref)). To enable all debug logging, use the special value `all`. +## Writing log events to a file + +Sometimes it can be useful to write log events to a file. Here is an example +of how to use a task-local and global logger to write information to a text +file: + +```julia-repl +# Load the logging module +julia> using Logging + +# Open a textfile for writing +julia> io = open("log.txt", "w+") +IOStream() + +# Create a simple logger +julia> logger = SimpleLogger(io) +SimpleLogger(IOStream(), Info, Dict{Any,Int64}()) + +# Log a task-specific message +julia> with_logger(logger) do + @info("a context specific log message") + end + +# Write all buffered messages to the file +julia> flush(io) + +# Set the global logger to logger +julia> global_logger(logger) +SimpleLogger(IOStream(), Info, Dict{Any,Int64}()) + +# This message will now also be written to the file +julia> @info("a global log message") + +# Close the file +julia> close(io) +``` + ## Reference From cb7900e45200b35ae2c349ebcc3588651997e9d2 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 30 Aug 2018 14:49:56 -0400 Subject: [PATCH 080/166] Vector lowering improvents in GC placement Support for vectors of tracked pointer was incomplete in the GC placement pass. Try to fix as many cases as possible and add some tests. A refactor to make all of this nicer (vectors weren't originally part of the implementation might be good), but for now, let's get it correct first. Fixes #28536 (cherry picked from commit b1dac9fdb037adbebf3d781b25d4bf4b64be2486) --- src/llvm-late-gc-lowering.cpp | 236 +++++++++++++++++++++++----------- test/llvmpasses/gcroots.ll | 105 +++++++++++++++ 2 files changed, 266 insertions(+), 75 deletions(-) diff --git a/src/llvm-late-gc-lowering.cpp b/src/llvm-late-gc-lowering.cpp index d83f5785f9cb1..902e110cf05cf 100644 --- a/src/llvm-late-gc-lowering.cpp +++ b/src/llvm-late-gc-lowering.cpp @@ -349,8 +349,8 @@ struct LateLowerGCFrame: public FunctionPass { NoteUse(S, BBS, V, BBS.UpExposedUses); } Value *MaybeExtractUnion(std::pair Val, Instruction *InsertBefore); - int LiftPhi(State &S, PHINode *Phi); - int LiftSelect(State &S, SelectInst *SI); + void LiftPhi(State &S, PHINode *Phi, SmallVector &PHINumbers); + bool LiftSelect(State &S, SelectInst *SI); int Number(State &S, Value *V); std::vector NumberVector(State &S, Value *Vec); int NumberBase(State &S, Value *V, Value *Base); @@ -383,7 +383,10 @@ struct LateLowerGCFrame: public FunctionPass { }; static unsigned getValueAddrSpace(Value *V) { - return cast(V->getType())->getAddressSpace(); + Type *Ty = V->getType(); + if (isa(Ty)) + Ty = cast(V->getType())->getElementType(); + return cast(Ty)->getAddressSpace(); } static bool isSpecialPtr(Type *Ty) { @@ -508,42 +511,108 @@ Value *LateLowerGCFrame::MaybeExtractUnion(std::pair Val, Instructio return Val.first; } -int LateLowerGCFrame::LiftSelect(State &S, SelectInst *SI) { - Value *TrueBase = MaybeExtractUnion(FindBaseValue(S, SI->getTrueValue(), false), SI); - Value *FalseBase = MaybeExtractUnion(FindBaseValue(S, SI->getFalseValue(), false), SI); - if (getValueAddrSpace(TrueBase) != AddressSpace::Tracked) - TrueBase = ConstantPointerNull::get(cast(FalseBase->getType())); - if (getValueAddrSpace(FalseBase) != AddressSpace::Tracked) - FalseBase = ConstantPointerNull::get(cast(TrueBase->getType())); - if (getValueAddrSpace(TrueBase) != AddressSpace::Tracked) - return -1; - Value *SelectBase = SelectInst::Create(SI->getCondition(), - TrueBase, FalseBase, "gclift", SI); - int Number = ++S.MaxPtrNumber; - S.PtrNumbering[SelectBase] = S.AllPtrNumbering[SelectBase] = - S.AllPtrNumbering[SI] = Number; - S.ReversePtrNumbering[Number] = SelectBase; - return Number; +static Value *GetPtrForNumber(State &S, unsigned Num, Instruction *InsertionPoint) +{ + Value *Val = S.ReversePtrNumbering[Num]; + if (isSpecialPtrVec(Val->getType())) { + const std::vector &AllNums = S.AllVectorNumbering[Val]; + unsigned Idx = 0; + for (; Idx < AllNums.size(); ++Idx) { + if ((unsigned)AllNums[Idx] == Num) + break; + } + Val = ExtractElementInst::Create(Val, ConstantInt::get( + Type::getInt32Ty(Val->getContext()), Idx), "", InsertionPoint); + } + return Val; +} + +bool LateLowerGCFrame::LiftSelect(State &S, SelectInst *SI) { + if (isSpecialPtrVec(SI->getType())) { + VectorType *VT = cast(SI->getType()); + std::vector TrueNumbers = NumberVector(S, SI->getTrueValue()); + std::vector FalseNumbers = NumberVector(S, SI->getFalseValue()); + std::vector Numbers; + for (unsigned i = 0; i < VT->getNumElements(); ++i) { + SelectInst *LSI = SelectInst::Create(SI->getCondition(), + TrueNumbers[i] < 0 ? + ConstantPointerNull::get(cast(T_prjlvalue)) : + GetPtrForNumber(S, TrueNumbers[i], SI), + FalseNumbers[i] < 0 ? + ConstantPointerNull::get(cast(T_prjlvalue)) : + GetPtrForNumber(S, FalseNumbers[i], SI), + "gclift", SI); + int Number = ++S.MaxPtrNumber; + Numbers.push_back(Number); + S.PtrNumbering[LSI] = S.AllPtrNumbering[LSI] = Number; + S.ReversePtrNumbering[Number] = LSI; + } + S.AllVectorNumbering[SI] = Numbers; + } else { + Value *TrueBase = MaybeExtractUnion(FindBaseValue(S, SI->getTrueValue(), false), SI); + Value *FalseBase = MaybeExtractUnion(FindBaseValue(S, SI->getFalseValue(), false), SI); + if (getValueAddrSpace(TrueBase) != AddressSpace::Tracked) + TrueBase = ConstantPointerNull::get(cast(FalseBase->getType())); + if (getValueAddrSpace(FalseBase) != AddressSpace::Tracked) + FalseBase = ConstantPointerNull::get(cast(TrueBase->getType())); + if (getValueAddrSpace(TrueBase) != AddressSpace::Tracked) + return false; + Value *SelectBase = SelectInst::Create(SI->getCondition(), + TrueBase, FalseBase, "gclift", SI); + int Number = ++S.MaxPtrNumber; + S.PtrNumbering[SelectBase] = S.AllPtrNumbering[SelectBase] = + S.AllPtrNumbering[SI] = Number; + S.ReversePtrNumbering[Number] = SelectBase; + } + return true; } -int LateLowerGCFrame::LiftPhi(State &S, PHINode *Phi) +void LateLowerGCFrame::LiftPhi(State &S, PHINode *Phi, SmallVector &PHINumbers) { - PHINode *lift = PHINode::Create(T_prjlvalue, Phi->getNumIncomingValues(), "gclift", Phi); - for (unsigned i = 0; i < Phi->getNumIncomingValues(); ++i) { - Value *Incoming = Phi->getIncomingValue(i); - Value *Base = MaybeExtractUnion(FindBaseValue(S, Incoming, false), - Phi->getIncomingBlock(i)->getTerminator()); - if (getValueAddrSpace(Base) != AddressSpace::Tracked) - Base = ConstantPointerNull::get(cast(T_prjlvalue)); - if (Base->getType() != T_prjlvalue) - Base = new BitCastInst(Base, T_prjlvalue, "", Phi->getIncomingBlock(i)->getTerminator()); - lift->addIncoming(Base, Phi->getIncomingBlock(i)); + if (isSpecialPtrVec(Phi->getType())) { + VectorType *VT = cast(Phi->getType()); + std::vector lifted; + for (unsigned i = 0; i < VT->getNumElements(); ++i) { + lifted.push_back(PHINode::Create(T_prjlvalue, Phi->getNumIncomingValues(), "gclift", Phi)); + } + for (unsigned i = 0; i < Phi->getNumIncomingValues(); ++i) { + std::vector Numbers = NumberVector(S, Phi->getIncomingValue(i)); + BasicBlock *IncomingBB = Phi->getIncomingBlock(i); + Instruction *Terminator = IncomingBB->getTerminator(); + for (unsigned i = 0; i < VT->getNumElements(); ++i) { + if (Numbers[i] < 0) + lifted[i]->addIncoming(ConstantPointerNull::get(cast(T_prjlvalue)), IncomingBB); + else + lifted[i]->addIncoming(GetPtrForNumber(S, Numbers[i], Terminator), IncomingBB); + } + } + std::vector Numbers; + for (unsigned i = 0; i < VT->getNumElements(); ++i) { + int Number = ++S.MaxPtrNumber; + PHINumbers.push_back(Number); + Numbers.push_back(Number); + S.PtrNumbering[lifted[i]] = S.AllPtrNumbering[lifted[i]] = Number; + S.ReversePtrNumbering[Number] = lifted[i]; + } + S.AllVectorNumbering[Phi] = Numbers; + } else { + PHINode *lift = PHINode::Create(T_prjlvalue, Phi->getNumIncomingValues(), "gclift", Phi); + for (unsigned i = 0; i < Phi->getNumIncomingValues(); ++i) { + Value *Incoming = Phi->getIncomingValue(i); + Value *Base = MaybeExtractUnion(FindBaseValue(S, Incoming, false), + Phi->getIncomingBlock(i)->getTerminator()); + if (getValueAddrSpace(Base) != AddressSpace::Tracked) + Base = ConstantPointerNull::get(cast(T_prjlvalue)); + if (Base->getType() != T_prjlvalue) + Base = new BitCastInst(Base, T_prjlvalue, "", Phi->getIncomingBlock(i)->getTerminator()); + lift->addIncoming(Base, Phi->getIncomingBlock(i)); + } + int Number = ++S.MaxPtrNumber; + PHINumbers.push_back(Number); + S.PtrNumbering[lift] = S.AllPtrNumbering[lift] = + S.AllPtrNumbering[Phi] = Number; + S.ReversePtrNumbering[Number] = lift; } - int Number = ++S.MaxPtrNumber; - S.PtrNumbering[lift] = S.AllPtrNumbering[lift] = - S.AllPtrNumbering[Phi] = Number; - S.ReversePtrNumbering[Number] = lift; - return Number; } int LateLowerGCFrame::NumberBase(State &S, Value *V, Value *CurrentV) @@ -566,12 +635,14 @@ int LateLowerGCFrame::NumberBase(State &S, Value *V, Value *CurrentV) // input IR) Number = -1; } else if (isa(CurrentV) && !isUnion && getValueAddrSpace(CurrentV) != AddressSpace::Tracked) { - int Number = LiftSelect(S, cast(CurrentV)); - S.AllPtrNumbering[V] = Number; + Number = -1; + if (LiftSelect(S, cast(CurrentV))) + Number = S.AllPtrNumbering[V] = S.AllPtrNumbering.at(CurrentV); return Number; } else if (isa(CurrentV) && !isUnion && getValueAddrSpace(CurrentV) != AddressSpace::Tracked) { - int Number = LiftPhi(S, cast(CurrentV)); - S.AllPtrNumbering[V] = Number; + SmallVector PHINumbers; + LiftPhi(S, cast(CurrentV), PHINumbers); + Number = S.AllPtrNumbering[V] = S.AllPtrNumbering.at(CurrentV); return Number; } else if (isa(CurrentV) && !isUnion) { assert(false && "TODO: Extract"); @@ -630,7 +701,15 @@ std::vector LateLowerGCFrame::NumberVectorBase(State &S, Value *CurrentV) { Numbers = NumberVectorBase(S, IEI->getOperand(0)); int ElNumber = Number(S, IEI->getOperand(1)); Numbers[idx] = ElNumber; - } else if (isa(CurrentV) || isa(CurrentV) || isa(CurrentV)) { + } else if (isa(CurrentV) && getValueAddrSpace(CurrentV) != AddressSpace::Tracked) { + LiftSelect(S, cast(CurrentV)); + Numbers = S.AllVectorNumbering[CurrentV]; + } else if (isa(CurrentV) && getValueAddrSpace(CurrentV) != AddressSpace::Tracked) { + SmallVector PHINumbers; + LiftPhi(S, cast(CurrentV), PHINumbers); + Numbers = S.AllVectorNumbering[CurrentV]; + } else if (isa(CurrentV) || isa(CurrentV) || isa(CurrentV) || + isa(CurrentV)) { // This is simple, we can just number them sequentially for (unsigned i = 0; i < cast(CurrentV->getType())->getNumElements(); ++i) { int Num = ++S.MaxPtrNumber; @@ -638,7 +717,7 @@ std::vector LateLowerGCFrame::NumberVectorBase(State &S, Value *CurrentV) { S.ReversePtrNumbering[Num] = CurrentV; } } else { - assert(false && "Unexpected vector generating operating"); + assert(false && "Unexpected vector generating operation"); } S.AllVectorNumbering[CurrentV] = Numbers; return Numbers; @@ -1148,40 +1227,63 @@ State LateLowerGCFrame::LocalScan(Function &F) { NoteOperandUses(S, BBS, I, BBS.UpExposedUsesUnrooted); } else if (SelectInst *SI = dyn_cast(&I)) { // We need to insert an extra select for the GC root - if (!isSpecialPtr(SI->getType()) && !isUnionRep(SI->getType())) + if (!isSpecialPtr(SI->getType()) && !isSpecialPtrVec(SI->getType()) && + !isUnionRep(SI->getType())) continue; if (!isUnionRep(SI->getType()) && getValueAddrSpace(SI) != AddressSpace::Tracked) { - if (S.AllPtrNumbering.find(SI) != S.AllPtrNumbering.end()) + if (isSpecialPtrVec(SI->getType()) ? + S.AllVectorNumbering.find(SI) != S.AllVectorNumbering.end() : + S.AllPtrNumbering.find(SI) != S.AllPtrNumbering.end()) continue; - auto Num = LiftSelect(S, SI); - if (Num < 0) + if (!LiftSelect(S, SI)) continue; - auto SelectBase = cast(S.ReversePtrNumbering[Num]); - SmallVector RefinedPtr{Number(S, SelectBase->getTrueValue()), - Number(S, SelectBase->getFalseValue())}; - S.Refinements[Num] = std::move(RefinedPtr); + if (!isSpecialPtrVec(SI->getType())) { + // TODO: Refinements for vector select + int Num = S.AllPtrNumbering[SI]; + if (Num < 0) + continue; + auto SelectBase = cast(S.ReversePtrNumbering[Num]); + SmallVector RefinedPtr{Number(S, SelectBase->getTrueValue()), + Number(S, SelectBase->getFalseValue())}; + S.Refinements[Num] = std::move(RefinedPtr); + } } else { - SmallVector RefinedPtr{Number(S, SI->getTrueValue()), - Number(S, SI->getFalseValue())}; + SmallVector RefinedPtr; + if (!isSpecialPtrVec(SI->getType())) { + RefinedPtr = { + Number(S, SI->getTrueValue()), + Number(S, SI->getFalseValue()) + }; + } MaybeNoteDef(S, BBS, SI, BBS.Safepoints, std::move(RefinedPtr)); NoteOperandUses(S, BBS, I, BBS.UpExposedUsesUnrooted); } } else if (PHINode *Phi = dyn_cast(&I)) { - if (!isSpecialPtr(Phi->getType()) && !isUnionRep(Phi->getType())) { + if (!isSpecialPtr(Phi->getType()) && !isSpecialPtrVec(Phi->getType()) && + !isUnionRep(Phi->getType())) { continue; } auto nIncoming = Phi->getNumIncomingValues(); // We need to insert an extra phi for the GC root if (!isUnionRep(Phi->getType()) && getValueAddrSpace(Phi) != AddressSpace::Tracked) { - if (S.AllPtrNumbering.find(Phi) != S.AllPtrNumbering.end()) + if (isSpecialPtrVec(Phi->getType()) ? + S.AllVectorNumbering.find(Phi) != S.AllVectorNumbering.end() : + S.AllPtrNumbering.find(Phi) != S.AllPtrNumbering.end()) continue; - auto Num = LiftPhi(S, Phi); - auto lift = cast(S.ReversePtrNumbering[Num]); - S.Refinements[Num] = GetPHIRefinements(lift, S); - PHINumbers.push_back(Num); + LiftPhi(S, Phi, PHINumbers); } else { - MaybeNoteDef(S, BBS, Phi, BBS.Safepoints, GetPHIRefinements(Phi, S)); - PHINumbers.push_back(Number(S, Phi)); + SmallVector PHIRefinements; + if (!isSpecialPtrVec(Phi->getType())) + PHIRefinements = GetPHIRefinements(Phi, S); + MaybeNoteDef(S, BBS, Phi, BBS.Safepoints, std::move(PHIRefinements)); + if (isSpecialPtrVec(Phi->getType())) { + // TODO: Vector refinements + std::vector Nums = NumberVector(S, Phi); + for (int Num : Nums) + PHINumbers.push_back(Num); + } else { + PHINumbers.push_back(Number(S, Phi)); + } for (unsigned i = 0; i < nIncoming; ++i) { BBState &IncomingBBS = S.BBStates[Phi->getIncomingBlock(i)]; NoteUse(S, IncomingBBS, Phi->getIncomingValue(i), IncomingBBS.PhiOuts); @@ -1776,22 +1878,6 @@ bool LateLowerGCFrame::CleanupIR(Function &F, State *S) { return ChangesMade; } -static Value *GetPtrForNumber(State &S, unsigned Num, Instruction *InsertionPoint) -{ - Value *Val = S.ReversePtrNumbering[Num]; - if (isSpecialPtrVec(Val->getType())) { - const std::vector &AllNums = S.AllVectorNumbering[Val]; - unsigned Idx = 0; - for (; Idx < AllNums.size(); ++Idx) { - if ((unsigned)AllNums[Idx] == Num) - break; - } - Val = ExtractElementInst::Create(Val, ConstantInt::get( - Type::getInt32Ty(Val->getContext()), Idx), "", InsertionPoint); - } - return Val; -} - static void AddInPredLiveOuts(BasicBlock *BB, BitVector &LiveIn, State &S) { bool First = true; diff --git a/test/llvmpasses/gcroots.ll b/test/llvmpasses/gcroots.ll index 958a735b8efca..eb72e2e580d91 100644 --- a/test/llvmpasses/gcroots.ll +++ b/test/llvmpasses/gcroots.ll @@ -414,6 +414,111 @@ top: ret %jl_value_t addrspace(10)* %obj } +define void @vecphi(i1 %cond, <2 x %jl_value_t addrspace(10)*> *%arg) { +; CHECK-LABEL: @vecphi +; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 4 +top: + %ptls = call %jl_value_t*** @julia.ptls_states() + br i1 %cond, label %A, label %B + +A: + br label %common + +B: + %loaded = load <2 x %jl_value_t addrspace(10)*>, <2 x %jl_value_t addrspace(10)*> *%arg + call void @jl_safepoint() + br label %common + +common: + %phi = phi <2 x %jl_value_t addrspace(10)*> [ zeroinitializer, %A ], [ %loaded, %B ] + call void @jl_safepoint() + %el1 = extractelement <2 x %jl_value_t addrspace(10)*> %phi, i32 0 + %el2 = extractelement <2 x %jl_value_t addrspace(10)*> %phi, i32 1 + call void @one_arg_boxed(%jl_value_t addrspace(10)* %el1) + call void @one_arg_boxed(%jl_value_t addrspace(10)* %el2) + unreachable +} + +define i8 @phi_arrayptr(i1 %cond) { +; CHECK-LABEL: @phi_arrayptr +; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 4 +top: + %ptls = call %jl_value_t*** @julia.ptls_states() + br i1 %cond, label %A, label %B + +A: + %obj1 = call %jl_value_t addrspace(10) *@alloc() + %obj2 = call %jl_value_t addrspace(10) *@alloc() + %decayed1 = addrspacecast %jl_value_t addrspace(10) *%obj1 to %jl_value_t addrspace(11) * + %arrayptrptr1 = bitcast %jl_value_t addrspace(11) *%decayed1 to i8 addrspace(13)* addrspace(11)* + %arrayptr1 = load i8 addrspace(13)*, i8 addrspace(13)* addrspace(11)* %arrayptrptr1 + %decayed2 = addrspacecast %jl_value_t addrspace(10) *%obj2 to %jl_value_t addrspace(11) * + %arrayptrptr2 = bitcast %jl_value_t addrspace(11) *%decayed2 to i8 addrspace(13)* addrspace(11)* + %arrayptr2 = load i8 addrspace(13)*, i8 addrspace(13)* addrspace(11)* %arrayptrptr2 + %insert1 = insertelement <2 x i8 addrspace(13)*> undef, i8 addrspace(13)* %arrayptr1, i32 0 + %insert2 = insertelement <2 x i8 addrspace(13)*> %insert1, i8 addrspace(13)* %arrayptr2, i32 1 + call void @jl_safepoint() + br label %common + +B: + br label %common + +common: +; CHECK: %gclift +; CHECK: %gclift1 +; CHECK-NOT: %gclift2 + %phi = phi <2 x i8 addrspace(13)*> [ %insert2, %A ], [ zeroinitializer, %B ] + call void @jl_safepoint() + %el1 = extractelement <2 x i8 addrspace(13)*> %phi, i32 0 + %el2 = extractelement <2 x i8 addrspace(13)*> %phi, i32 1 + %l1 = load i8, i8 addrspace(13)* %el1 + %l2 = load i8, i8 addrspace(13)* %el2 + %add = add i8 %l1, %l2 + ret i8 %add +} + +define void @vecselect(i1 %cond, <2 x %jl_value_t addrspace(10)*> *%arg) { +; CHECK-LABEL: @vecselect +; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 4 +top: + %ptls = call %jl_value_t*** @julia.ptls_states() + %loaded = load <2 x %jl_value_t addrspace(10)*>, <2 x %jl_value_t addrspace(10)*> *%arg + call void @jl_safepoint() + %select = select i1 %cond, <2 x %jl_value_t addrspace(10)*> zeroinitializer, <2 x %jl_value_t addrspace(10)*> %loaded + call void @jl_safepoint() + %el1 = extractelement <2 x %jl_value_t addrspace(10)*> %select, i32 0 + %el2 = extractelement <2 x %jl_value_t addrspace(10)*> %select, i32 1 + call void @one_arg_boxed(%jl_value_t addrspace(10)* %el1) + call void @one_arg_boxed(%jl_value_t addrspace(10)* %el2) + unreachable +} + +define i8 @select_arrayptr(i1 %cond) { +; CHECK-LABEL: @select_arrayptr +; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 4 +top: + %ptls = call %jl_value_t*** @julia.ptls_states() + %obj1 = call %jl_value_t addrspace(10) *@alloc() + %obj2 = call %jl_value_t addrspace(10) *@alloc() + %decayed1 = addrspacecast %jl_value_t addrspace(10) *%obj1 to %jl_value_t addrspace(11) * + %arrayptrptr1 = bitcast %jl_value_t addrspace(11) *%decayed1 to i8 addrspace(13)* addrspace(11)* + %arrayptr1 = load i8 addrspace(13)*, i8 addrspace(13)* addrspace(11)* %arrayptrptr1 + %decayed2 = addrspacecast %jl_value_t addrspace(10) *%obj2 to %jl_value_t addrspace(11) * + %arrayptrptr2 = bitcast %jl_value_t addrspace(11) *%decayed2 to i8 addrspace(13)* addrspace(11)* + %arrayptr2 = load i8 addrspace(13)*, i8 addrspace(13)* addrspace(11)* %arrayptrptr2 + %insert1 = insertelement <2 x i8 addrspace(13)*> undef, i8 addrspace(13)* %arrayptr1, i32 0 + %insert2 = insertelement <2 x i8 addrspace(13)*> %insert1, i8 addrspace(13)* %arrayptr2, i32 1 + call void @jl_safepoint() + %select = select i1 %cond, <2 x i8 addrspace(13)*> %insert2, <2 x i8 addrspace(13)*> zeroinitializer + call void @jl_safepoint() + %el1 = extractelement <2 x i8 addrspace(13)*> %select, i32 0 + %el2 = extractelement <2 x i8 addrspace(13)*> %select, i32 1 + %l1 = load i8, i8 addrspace(13)* %el1 + %l2 = load i8, i8 addrspace(13)* %el2 + %add = add i8 %l1, %l2 + ret i8 %add +} + !0 = !{!"jtbaa"} !1 = !{!"jtbaa_const", !0, i64 0} !2 = !{!1, !1, i64 0, i64 1} From 3f4435ccd5a981ab43d17f8a55c430fb881e4bf5 Mon Sep 17 00:00:00 2001 From: Jim Garrison Date: Wed, 29 Aug 2018 01:09:04 -0400 Subject: [PATCH 081/166] Fix typo in accumulate docstring (#28939) (cherry picked from commit 39e5742557cf56f26e1eccd28ab52d258ae19863) --- base/accumulate.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/accumulate.jl b/base/accumulate.jl index 74c1c3a8c58e0..c5c4e83b3b0e3 100644 --- a/base/accumulate.jl +++ b/base/accumulate.jl @@ -191,7 +191,7 @@ cumprod(x::AbstractVector) = cumprod(x, dims=1) accumulate(op, A; dims::Integer, [init]) Cumulative operation `op` along the dimension `dims` of `A` (providing `dims` is optional -for vectors). An inital value `init` may optionally be provided by a keyword argument. See +for vectors). An initial value `init` may optionally be provided by a keyword argument. See also [`accumulate!`](@ref) to use a preallocated output array, both for performance and to control the precision of the output (e.g. to avoid overflow). For common operations there are specialized variants of `accumulate`, see: [`cumsum`](@ref), [`cumprod`](@ref) From 629164ab060952fa25ce72315c70f5f3c9f049c0 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Mon, 3 Sep 2018 21:19:59 +0200 Subject: [PATCH 082/166] doc: fix accumulate examples not using the init keyword (#28910) * doc: fix accumulate examples not using the init keyword * add links (KristofferC) (cherry picked from commit 49e58ba035ea8a02c29c21cf1f2204f3b20f8dff) --- doc/src/manual/documentation.md | 13 +++++++------ doc/src/manual/parallel-computing.md | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/doc/src/manual/documentation.md b/doc/src/manual/documentation.md index 0eae97de6a4d9..195df3eae514c 100644 --- a/doc/src/manual/documentation.md +++ b/doc/src/manual/documentation.md @@ -621,16 +621,17 @@ the Julia documentation itself. For example: ```julia """ - accumulate!(op, y, x) + tryparse(type, str; base) -Cumulative operation `op` on a vector `x`, storing the result in `y`. See also [`accumulate`](@ref). +Like [`parse`](@ref), but returns either a value of the requested type, +or [`nothing`](@ref) if the string does not contain a valid number. """ ``` -This will create a link in the generated docs to the `accumulate` documentation -(which has more information about what this function actually does). It's good to include -cross references to mutating/non-mutating versions of a function, or to highlight a difference -between two similar-seeming functions. +This will create a link in the generated docs to the [`parse`](@ref) documentation +(which has more information about what this function actually does), and to the +[`nothing`](@ref) documentation. It's good to include cross references to mutating/non-mutating +versions of a function, or to highlight a difference between two similar-seeming functions. !!! note The above cross referencing is *not* a Markdown feature, and relies on diff --git a/doc/src/manual/parallel-computing.md b/doc/src/manual/parallel-computing.md index d8942ebd2567e..d0d291901546d 100644 --- a/doc/src/manual/parallel-computing.md +++ b/doc/src/manual/parallel-computing.md @@ -465,7 +465,7 @@ julia> function g_fix(r) g_fix (generic function with 1 method) julia> r = let m = MersenneTwister(1) - [m; accumulate(Future.randjump, m, fill(big(10)^20, nthreads()-1))] + [m; accumulate(Future.randjump, fill(big(10)^20, nthreads()-1), init=m)] end; julia> g_fix(r) From 71a65f15dae75f051a769f2ee5a8152cde739a5e Mon Sep 17 00:00:00 2001 From: Pablo San-Jose Date: Tue, 4 Sep 2018 12:24:29 +0200 Subject: [PATCH 083/166] CartesianIndices and LinearIndices docstring (#29023) (cherry picked from commit c8450d862f0e2653011f68118daecfe12b398c90) --- base/indices.jl | 2 +- base/multidimensional.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/base/indices.jl b/base/indices.jl index 800280c90f57e..dce053872bd1a 100644 --- a/base/indices.jl +++ b/base/indices.jl @@ -355,7 +355,7 @@ julia> extrema(b) LinearIndices(inds::CartesianIndices) -> R LinearIndices(sz::Dims) -> R - LinearIndices(istart:istop, jstart:jstop, ...) -> R + LinearIndices((istart:istop, jstart:jstop, ...)) -> R Return a `LinearIndices` array with the specified shape or [`axes`](@ref). diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 4677e8649a680..1a78b84c1e6a3 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -156,7 +156,7 @@ module IteratorsMD # Iteration """ CartesianIndices(sz::Dims) -> R - CartesianIndices(istart:istop, jstart:jstop, ...) -> R + CartesianIndices((istart:istop, jstart:jstop, ...)) -> R Define a region `R` spanning a multidimensional rectangular range of integer indices. These are most commonly encountered in the From 139974a540327f598c12f804af559391dd78bf26 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Sun, 2 Sep 2018 20:13:48 -0400 Subject: [PATCH 084/166] Fix out of bounds write in array deserialization The array was allocated based on the serialized `elsize` of the array, however, unions get an extra selector array after the regular storage which was not allocated (because we didn't know it was gonna be a union array at the time when we allocated it). According to a48eeefd6207090898f5b1877684aa10f217800a we cannot look at the element type to allocate the array, so we need to serialize a bit to indicate that we will have a union array. Fixes #28998 (cherry picked from commit e7d7259310ca0dd9c89103bb489a7d6034e39460) --- src/array.c | 15 +++++++++------ src/dump.c | 20 ++++++++++++-------- src/julia_internal.h | 2 +- test/precompile.jl | 8 ++++++++ 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/array.c b/src/array.c index 6a893f96cf43e..fd4de0d24412d 100644 --- a/src/array.c +++ b/src/array.c @@ -53,7 +53,7 @@ size_t jl_arr_xtralloc_limit = 0; #define MAXINTVAL (((size_t)-1)>>1) static jl_array_t *_new_array_(jl_value_t *atype, uint32_t ndims, size_t *dims, - int isunboxed, int elsz) + int isunboxed, int isunion, int elsz) { jl_ptls_t ptls = jl_get_ptls_states(); size_t i, tot, nel=1; @@ -67,7 +67,7 @@ static jl_array_t *_new_array_(jl_value_t *atype, uint32_t ndims, size_t *dims, jl_error("invalid Array dimensions"); nel = prod; } - int isunion = atype != NULL && jl_is_uniontype(jl_tparam0(atype)); + assert(atype == NULL || isunion == jl_is_uniontype(jl_tparam0(atype))); if (isunboxed) { wideint_t prod = (wideint_t)elsz * (wideint_t)nel; if (prod > (wideint_t) MAXINTVAL) @@ -149,18 +149,19 @@ static inline jl_array_t *_new_array(jl_value_t *atype, uint32_t ndims, size_t * jl_value_t *eltype = jl_tparam0(atype); size_t elsz = 0, al = 0; int isunboxed = jl_islayout_inline(eltype, &elsz, &al); + int isunion = jl_is_uniontype(eltype); if (!isunboxed) { elsz = sizeof(void*); al = elsz; } - return _new_array_(atype, ndims, dims, isunboxed, elsz); + return _new_array_(atype, ndims, dims, isunboxed, isunion, elsz); } jl_array_t *jl_new_array_for_deserialization(jl_value_t *atype, uint32_t ndims, size_t *dims, - int isunboxed, int elsz) + int isunboxed, int isunion, int elsz) { - return _new_array_(atype, ndims, dims, isunboxed, elsz); + return _new_array_(atype, ndims, dims, isunboxed, isunion, elsz); } #ifndef JL_NDEBUG @@ -1113,8 +1114,10 @@ JL_DLLEXPORT jl_array_t *jl_array_copy(jl_array_t *ary) { size_t elsz = ary->elsize; size_t len = jl_array_len(ary); + int isunion = jl_is_uniontype(jl_tparam0(jl_typeof(ary))); jl_array_t *new_ary = _new_array_(jl_typeof(ary), jl_array_ndims(ary), - &ary->nrows, !ary->flags.ptrarray, elsz); + &ary->nrows, !ary->flags.ptrarray, + isunion, elsz); memcpy(new_ary->data, ary->data, len * elsz); // ensure isbits union arrays copy their selector bytes correctly if (jl_array_isbitsunion(ary)) diff --git a/src/dump.c b/src/dump.c index c18865125e6c8..e23210b38d762 100644 --- a/src/dump.c +++ b/src/dump.c @@ -638,14 +638,15 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li } else if (jl_is_array(v)) { jl_array_t *ar = (jl_array_t*)v; - if (ar->flags.ndims == 1 && ar->elsize < 128) { + int isunion = jl_is_uniontype(jl_tparam0(jl_typeof(ar))); + if (ar->flags.ndims == 1 && ar->elsize <= 0x3f) { write_uint8(s->s, TAG_ARRAY1D); - write_uint8(s->s, (ar->flags.ptrarray<<7) | (ar->elsize & 0x7f)); + write_uint8(s->s, (ar->flags.ptrarray<<7) | (isunion << 6) | (ar->elsize & 0x3f)); } else { write_uint8(s->s, TAG_ARRAY); write_uint16(s->s, ar->flags.ndims); - write_uint16(s->s, (ar->flags.ptrarray<<15) | (ar->elsize & 0x7fff)); + write_uint16(s->s, (ar->flags.ptrarray << 15) | (isunion << 14) | (ar->elsize & 0x3fff)); } for (i = 0; i < ar->flags.ndims; i++) jl_serialize_value(s, jl_box_long(jl_array_dim(ar,i))); @@ -1210,7 +1211,7 @@ static void write_mod_list(ios_t *s, jl_array_t *a) } // "magic" string and version header of .ji file -static const int JI_FORMAT_VERSION = 6; +static const int JI_FORMAT_VERSION = 7; static const char JI_MAGIC[] = "\373jli\r\n\032\n"; // based on PNG signature static const uint16_t BOM = 0xFEFF; // byte-order marker static void write_header(ios_t *s) @@ -1495,18 +1496,20 @@ static jl_value_t *jl_deserialize_value_array(jl_serializer_state *s, uint8_t ta { int usetable = (s->mode != MODE_IR); int16_t i, ndims; - int isunboxed, elsize; + int isunboxed, isunion, elsize; if (tag == TAG_ARRAY1D) { ndims = 1; elsize = read_uint8(s->s); isunboxed = !(elsize >> 7); - elsize = elsize & 0x7f; + isunion = elsize >> 6; + elsize = elsize & 0x3f; } else { ndims = read_uint16(s->s); elsize = read_uint16(s->s); isunboxed = !(elsize >> 15); - elsize = elsize & 0x7fff; + isunion = elsize >> 14; + elsize = elsize & 0x3fff; } uintptr_t pos = backref_list.len; if (usetable) @@ -1515,7 +1518,8 @@ static jl_value_t *jl_deserialize_value_array(jl_serializer_state *s, uint8_t ta for (i = 0; i < ndims; i++) { dims[i] = jl_unbox_long(jl_deserialize_value(s, NULL)); } - jl_array_t *a = jl_new_array_for_deserialization((jl_value_t*)NULL, ndims, dims, isunboxed, elsize); + jl_array_t *a = jl_new_array_for_deserialization( + (jl_value_t*)NULL, ndims, dims, isunboxed, isunion, elsize); if (usetable) backref_list.items[pos] = a; jl_value_t *aty = jl_deserialize_value(s, &jl_astaggedvalue(a)->type); diff --git a/src/julia_internal.h b/src/julia_internal.h index 186b5d7b2b985..26835e25cc5e1 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -463,7 +463,7 @@ JL_DLLEXPORT jl_value_t *jl_argument_datatype(jl_value_t *argt JL_PROPAGATES_ROO jl_value_t *jl_nth_slot_type(jl_value_t *sig JL_PROPAGATES_ROOT, size_t i) JL_NOTSAFEPOINT; void jl_compute_field_offsets(jl_datatype_t *st); jl_array_t *jl_new_array_for_deserialization(jl_value_t *atype, uint32_t ndims, size_t *dims, - int isunboxed, int elsz); + int isunboxed, int isunion, int elsz); void jl_module_run_initializer(jl_module_t *m); extern jl_array_t *jl_module_init_order JL_GLOBALLY_ROOTED; extern jl_array_t *jl_cfunction_list JL_GLOBALLY_ROOTED; diff --git a/test/precompile.jl b/test/precompile.jl index df0883dfa5fa6..61e5e59512b5e 100644 --- a/test/precompile.jl +++ b/test/precompile.jl @@ -136,6 +136,12 @@ try const x28297 = Result(missing) + # issue #28998 + const x28998 = [missing, 2, missing, 6, missing, + missing, missing, missing, + missing, missing, missing, + missing, missing, 6] + let some_method = which(Base.include, (String,)) # global const some_method // FIXME: support for serializing a direct reference to an external Method not implemented global const some_linfo = @@ -180,6 +186,8 @@ try @test Foo.abigint_x::BigInt + 1 == big"125" @test Foo.x28297.result === missing + + @test Foo.x28998[end] == 6 end cachedir = joinpath(dir, "compiled", "v$(VERSION.major).$(VERSION.minor)") From d6e43e25ff7ca57ff85342243fd072e51ae303d5 Mon Sep 17 00:00:00 2001 From: wfrgra Date: Wed, 5 Sep 2018 04:15:02 +1000 Subject: [PATCH 085/166] Fix download agent search relying on throwing of Sys.which(). Update t #28157 (#28682) * Fix download agent search relying on throwing of Sys.which() (cherry picked from commit 14fb104b5f73e1ff91394f0615c01c2e0a00fc02) --- base/download.jl | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/base/download.jl b/base/download.jl index e5ed437a94a7f..798a9930b7d42 100644 --- a/base/download.jl +++ b/base/download.jl @@ -2,9 +2,7 @@ # file downloading -downloadcmd = nothing if Sys.iswindows() - downloadcmd = "powershell" function download(url::AbstractString, filename::AbstractString) ps = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" tls12 = "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12" @@ -25,28 +23,16 @@ if Sys.iswindows() end else function download(url::AbstractString, filename::AbstractString) - global downloadcmd - if downloadcmd === nothing - for checkcmd in ("curl", "wget", "fetch") - try - # Sys.which() will throw() if it can't find `checkcmd` - Sys.which(checkcmd) - downloadcmd = checkcmd - break - catch - end - end - end - if downloadcmd == "wget" + if Sys.which("curl") !== nothing + run(`curl -g -L -f -o $filename $url`) + elseif Sys.which("wget") !== nothing try run(`wget -O $filename $url`) catch - rm(filename) # wget always creates a file + rm(filename, force=true) # wget always creates a file rethrow() end - elseif downloadcmd == "curl" - run(`curl -g -L -f -o $filename $url`) - elseif downloadcmd == "fetch" + elseif Sys.which("fetch") !== nothing run(`fetch -f $filename $url`) else error("no download agent available; install curl, wget, or fetch") From 8078c1b39ad73173e63d764e1b249468524a9e37 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 4 Sep 2018 11:43:43 -0700 Subject: [PATCH 086/166] fix #28915, identity conversion to union of tuple types (#28951) (cherry picked from commit d4cdde1e35c6c830fb59d7af442ac28ddb72f52d) --- base/essentials.jl | 17 ++++++++++++++--- test/ambiguous.jl | 4 ++++ test/tuple.jl | 3 +++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/base/essentials.jl b/base/essentials.jl index 35a52e592434e..575d3aac0e9d0 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -264,11 +264,22 @@ function typename(a::Union) end typename(union::UnionAll) = typename(union.body) -convert(::Type{T}, x::T) where {T<:Tuple{Any, Vararg{Any}}} = x -convert(::Type{Tuple{}}, x::Tuple{Any, Vararg{Any}}) = throw(MethodError(convert, (Tuple{}, x))) -convert(::Type{T}, x::Tuple{Any, Vararg{Any}}) where {T<:Tuple} = +const AtLeast1 = Tuple{Any, Vararg{Any}} + +# converting to empty tuple type +convert(::Type{Tuple{}}, ::Tuple{}) = () +convert(::Type{Tuple{}}, x::AtLeast1) = throw(MethodError(convert, (Tuple{}, x))) + +# converting to tuple types with at least one element +convert(::Type{T}, x::T) where {T<:AtLeast1} = x +convert(::Type{T}, x::AtLeast1) where {T<:AtLeast1} = (convert(tuple_type_head(T), x[1]), convert(tuple_type_tail(T), tail(x))...) +# converting to Vararg tuple types +convert(::Type{Tuple{Vararg{V}}}, x::Tuple{Vararg{V}}) where {V} = x +convert(T::Type{Tuple{Vararg{V}}}, x::Tuple) where {V} = + (convert(tuple_type_head(T), x[1]), convert(T, tail(x))...) + # TODO: the following definitions are equivalent (behaviorally) to the above method # I think they may be faster / more efficient for inference, # if we could enable them, but are they? diff --git a/test/ambiguous.jl b/test/ambiguous.jl index 6835a2c1977f7..02d076d5eb8ba 100644 --- a/test/ambiguous.jl +++ b/test/ambiguous.jl @@ -273,6 +273,8 @@ end pop!(need_to_handle_undef_sparam, first(methods(Core.Compiler.same_names))) pop!(need_to_handle_undef_sparam, which(Core.Compiler.convert, (Type{Union{Core.Compiler.Some{T}, Nothing}} where T, Core.Compiler.Some))) pop!(need_to_handle_undef_sparam, which(Core.Compiler.convert, (Type{Union{T, Nothing}} where T, Core.Compiler.Some))) + pop!(need_to_handle_undef_sparam, which(Core.Compiler.convert, Tuple{Type{Tuple{Vararg{Int}}}, Tuple{}})) + pop!(need_to_handle_undef_sparam, which(Core.Compiler.convert, Tuple{Type{Tuple{Vararg{Int}}}, Tuple{Int8}})) @test need_to_handle_undef_sparam == Set() end let need_to_handle_undef_sparam = @@ -295,6 +297,8 @@ end pop!(need_to_handle_undef_sparam, which(Base.nonmissingtype, Tuple{Type{Union{Missing, T}} where T})) pop!(need_to_handle_undef_sparam, which(Base.convert, (Type{Union{Some{T}, Nothing}} where T, Some))) pop!(need_to_handle_undef_sparam, which(Base.convert, (Type{Union{T, Nothing}} where T, Some))) + pop!(need_to_handle_undef_sparam, which(Base.convert, Tuple{Type{Tuple{Vararg{Int}}}, Tuple{}})) + pop!(need_to_handle_undef_sparam, which(Base.convert, Tuple{Type{Tuple{Vararg{Int}}}, Tuple{Int8}})) @test need_to_handle_undef_sparam == Set() end end diff --git a/test/tuple.jl b/test/tuple.jl index 11dc498086226..3a22f3b089557 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -86,6 +86,9 @@ end end @test empty((1, 2.0, "c")) === () + + # issue #28915 + @test convert(Union{Tuple{}, Tuple{Int}}, (1,)) === (1,) end @testset "size" begin From def8356a136050cfab315448850c0690257a19bb Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Fri, 17 Aug 2018 15:57:17 -0400 Subject: [PATCH 087/166] Carry LLVM patch to fix incorrect codegen This is rL326967 to fix #28726. (cherry picked from commit e99204b52be23c49b5185d270b6697b097b16513) --- deps/llvm.mk | 1 + deps/patches/llvm-rL326967-aligned-load.patch | 301 ++++++++++++++++++ 2 files changed, 302 insertions(+) create mode 100644 deps/patches/llvm-rL326967-aligned-load.patch diff --git a/deps/llvm.mk b/deps/llvm.mk index 4f350aa443b25..f3ebb3a1f3454 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -507,6 +507,7 @@ $(eval $(call LLVM_PATCH,llvm-rL323946-LSRTy)) # Remove for 7.0 $(eval $(call LLVM_PATCH,llvm-D50010-VNCoercion-ni)) $(eval $(call LLVM_PATCH,llvm-D50167-scev-umin)) $(eval $(call LLVM_PATCH,llvm-windows-race)) +$(eval $(call LLVM_PATCH,llvm-rL326967-aligned-load)) # remove for 7.0 endif # LLVM_VER # Remove hardcoded OS X requirements in compilter-rt cmake build diff --git a/deps/patches/llvm-rL326967-aligned-load.patch b/deps/patches/llvm-rL326967-aligned-load.patch new file mode 100644 index 0000000000000..62c112306a292 --- /dev/null +++ b/deps/patches/llvm-rL326967-aligned-load.patch @@ -0,0 +1,301 @@ +commit b398d8e1fa5a5a914957fa22d0a64db97f6c265e +Author: Craig Topper +Date: Thu Mar 8 00:21:17 2018 +0000 + + [X86] Fix some isel patterns that used aligned vector load instructions with unaligned predicates. + + These patterns weren't checking the alignment of the load, but were using the aligned instructions. This will cause a GP fault if the data isn't aligned. + + I believe these were introduced in r312450. + + git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@326967 91177308-0d34-0410-b5e6-96231b3b80d8 + +diff --git a/lib/Target/X86/X86InstrVecCompiler.td b/lib/Target/X86/X86InstrVecCompiler.td +index db3dfe56531..50c7763a2c3 100644 +--- a/lib/Target/X86/X86InstrVecCompiler.td ++++ b/lib/Target/X86/X86InstrVecCompiler.td +@@ -261,10 +261,10 @@ let Predicates = [HasVLX] in { + // will zero the upper bits. + // TODO: Is there a safe way to detect whether the producing instruction + // already zeroed the upper bits? +-multiclass subvector_zero_lowering { ++multiclass subvector_zero_lowering { + def : Pat<(DstTy (insert_subvector (bitconvert (ZeroTy immAllZerosV)), + (SrcTy RC:$src), (iPTR 0))), + (SUBREG_TO_REG (i64 0), +@@ -274,91 +274,91 @@ multiclass subvector_zero_lowering("VMOV"#MoveStr#"rm") addr:$src), SubIdx)>; ++ (!cast("VMOV"#LoadStr#"rm") addr:$src), SubIdx)>; + } + + let Predicates = [HasAVX, NoVLX] in { +- defm : subvector_zero_lowering<"APD", VR128, v4f64, v2f64, v8i32, loadv2f64, +- sub_xmm>; +- defm : subvector_zero_lowering<"APS", VR128, v8f32, v4f32, v8i32, loadv4f32, +- sub_xmm>; +- defm : subvector_zero_lowering<"DQA", VR128, v4i64, v2i64, v8i32, loadv2i64, +- sub_xmm>; +- defm : subvector_zero_lowering<"DQA", VR128, v8i32, v4i32, v8i32, loadv2i64, +- sub_xmm>; +- defm : subvector_zero_lowering<"DQA", VR128, v16i16, v8i16, v8i32, loadv2i64, +- sub_xmm>; +- defm : subvector_zero_lowering<"DQA", VR128, v32i8, v16i8, v8i32, loadv2i64, +- sub_xmm>; +-} +- +-let Predicates = [HasVLX] in { +- defm : subvector_zero_lowering<"APDZ128", VR128X, v4f64, v2f64, v8i32, ++ defm : subvector_zero_lowering<"APD", "UPD", VR128, v4f64, v2f64, v8i32, + loadv2f64, sub_xmm>; +- defm : subvector_zero_lowering<"APSZ128", VR128X, v8f32, v4f32, v8i32, ++ defm : subvector_zero_lowering<"APS", "UPS", VR128, v8f32, v4f32, v8i32, + loadv4f32, sub_xmm>; +- defm : subvector_zero_lowering<"DQA64Z128", VR128X, v4i64, v2i64, v8i32, ++ defm : subvector_zero_lowering<"DQA", "DQU", VR128, v4i64, v2i64, v8i32, + loadv2i64, sub_xmm>; +- defm : subvector_zero_lowering<"DQA64Z128", VR128X, v8i32, v4i32, v8i32, ++ defm : subvector_zero_lowering<"DQA", "DQU", VR128, v8i32, v4i32, v8i32, + loadv2i64, sub_xmm>; +- defm : subvector_zero_lowering<"DQA64Z128", VR128X, v16i16, v8i16, v8i32, ++ defm : subvector_zero_lowering<"DQA", "DQU", VR128, v16i16, v8i16, v8i32, + loadv2i64, sub_xmm>; +- defm : subvector_zero_lowering<"DQA64Z128", VR128X, v32i8, v16i8, v8i32, +- loadv2i64, sub_xmm>; +- +- defm : subvector_zero_lowering<"APDZ128", VR128X, v8f64, v2f64, v16i32, +- loadv2f64, sub_xmm>; +- defm : subvector_zero_lowering<"APSZ128", VR128X, v16f32, v4f32, v16i32, +- loadv4f32, sub_xmm>; +- defm : subvector_zero_lowering<"DQA64Z128", VR128X, v8i64, v2i64, v16i32, +- loadv2i64, sub_xmm>; +- defm : subvector_zero_lowering<"DQA64Z128", VR128X, v16i32, v4i32, v16i32, +- loadv2i64, sub_xmm>; +- defm : subvector_zero_lowering<"DQA64Z128", VR128X, v32i16, v8i16, v16i32, +- loadv2i64, sub_xmm>; +- defm : subvector_zero_lowering<"DQA64Z128", VR128X, v64i8, v16i8, v16i32, ++ defm : subvector_zero_lowering<"DQA", "DQU", VR128, v32i8, v16i8, v8i32, + loadv2i64, sub_xmm>; ++} + +- defm : subvector_zero_lowering<"APDZ256", VR256X, v8f64, v4f64, v16i32, +- loadv4f64, sub_ymm>; +- defm : subvector_zero_lowering<"APSZ256", VR256X, v16f32, v8f32, v16i32, +- loadv8f32, sub_ymm>; +- defm : subvector_zero_lowering<"DQA64Z256", VR256X, v8i64, v4i64, v16i32, +- loadv4i64, sub_ymm>; +- defm : subvector_zero_lowering<"DQA64Z256", VR256X, v16i32, v8i32, v16i32, +- loadv4i64, sub_ymm>; +- defm : subvector_zero_lowering<"DQA64Z256", VR256X, v32i16, v16i16, v16i32, +- loadv4i64, sub_ymm>; +- defm : subvector_zero_lowering<"DQA64Z256", VR256X, v64i8, v32i8, v16i32, +- loadv4i64, sub_ymm>; ++let Predicates = [HasVLX] in { ++ defm : subvector_zero_lowering<"APDZ128", "UPDZ128", VR128X, v4f64, ++ v2f64, v8i32, loadv2f64, sub_xmm>; ++ defm : subvector_zero_lowering<"APSZ128", "UPSZ128", VR128X, v8f32, ++ v4f32, v8i32, loadv4f32, sub_xmm>; ++ defm : subvector_zero_lowering<"DQA64Z128", "DQU64Z128", VR128X, v4i64, ++ v2i64, v8i32, loadv2i64, sub_xmm>; ++ defm : subvector_zero_lowering<"DQA64Z128", "DQU64Z128", VR128X, v8i32, ++ v4i32, v8i32, loadv2i64, sub_xmm>; ++ defm : subvector_zero_lowering<"DQA64Z128", "DQU64Z128", VR128X, v16i16, ++ v8i16, v8i32, loadv2i64, sub_xmm>; ++ defm : subvector_zero_lowering<"DQA64Z128", "DQU64Z128", VR128X, v32i8, ++ v16i8, v8i32, loadv2i64, sub_xmm>; ++ ++ defm : subvector_zero_lowering<"APDZ128", "UPDZ128", VR128X, v8f64, ++ v2f64, v16i32, loadv2f64, sub_xmm>; ++ defm : subvector_zero_lowering<"APSZ128", "UPSZ128", VR128X, v16f32, ++ v4f32, v16i32, loadv4f32, sub_xmm>; ++ defm : subvector_zero_lowering<"DQA64Z128", "DQU64Z128", VR128X, v8i64, ++ v2i64, v16i32, loadv2i64, sub_xmm>; ++ defm : subvector_zero_lowering<"DQA64Z128", "DQU64Z128", VR128X, v16i32, ++ v4i32, v16i32, loadv2i64, sub_xmm>; ++ defm : subvector_zero_lowering<"DQA64Z128", "DQU64Z128", VR128X, v32i16, ++ v8i16, v16i32, loadv2i64, sub_xmm>; ++ defm : subvector_zero_lowering<"DQA64Z128", "DQU64Z128", VR128X, v64i8, ++ v16i8, v16i32, loadv2i64, sub_xmm>; ++ ++ defm : subvector_zero_lowering<"APDZ256", "UPDZ256", VR256X, v8f64, ++ v4f64, v16i32, loadv4f64, sub_ymm>; ++ defm : subvector_zero_lowering<"APSZ256", "UPDZ256", VR256X, v16f32, ++ v8f32, v16i32, loadv8f32, sub_ymm>; ++ defm : subvector_zero_lowering<"DQA64Z256", "DQU64Z256", VR256X, v8i64, ++ v4i64, v16i32, loadv4i64, sub_ymm>; ++ defm : subvector_zero_lowering<"DQA64Z256", "DQU64Z256", VR256X, v16i32, ++ v8i32, v16i32, loadv4i64, sub_ymm>; ++ defm : subvector_zero_lowering<"DQA64Z256", "DQU64Z256", VR256X, v32i16, ++ v16i16, v16i32, loadv4i64, sub_ymm>; ++ defm : subvector_zero_lowering<"DQA64Z256", "DQU64Z256", VR256X, v64i8, ++ v32i8, v16i32, loadv4i64, sub_ymm>; + } + + let Predicates = [HasAVX512, NoVLX] in { +- defm : subvector_zero_lowering<"APD", VR128, v8f64, v2f64, v16i32, loadv2f64, +- sub_xmm>; +- defm : subvector_zero_lowering<"APS", VR128, v16f32, v4f32, v16i32, loadv4f32, +- sub_xmm>; +- defm : subvector_zero_lowering<"DQA", VR128, v8i64, v2i64, v16i32, loadv2i64, +- sub_xmm>; +- defm : subvector_zero_lowering<"DQA", VR128, v16i32, v4i32, v16i32, loadv2i64, +- sub_xmm>; +- defm : subvector_zero_lowering<"DQA", VR128, v32i16, v8i16, v16i32, loadv2i64, +- sub_xmm>; +- defm : subvector_zero_lowering<"DQA", VR128, v64i8, v16i8, v16i32, loadv2i64, +- sub_xmm>; +- +- defm : subvector_zero_lowering<"APDY", VR256, v8f64, v4f64, v16i32, +- loadv4f64, sub_ymm>; +- defm : subvector_zero_lowering<"APSY", VR256, v16f32, v8f32, v16i32, +- loadv8f32, sub_ymm>; +- defm : subvector_zero_lowering<"DQAY", VR256, v8i64, v4i64, v16i32, +- loadv4i64, sub_ymm>; +- defm : subvector_zero_lowering<"DQAY", VR256, v16i32, v8i32, v16i32, +- loadv4i64, sub_ymm>; +- defm : subvector_zero_lowering<"DQAY", VR256, v32i16, v16i16, v16i32, +- loadv4i64, sub_ymm>; +- defm : subvector_zero_lowering<"DQAY", VR256, v64i8, v32i8, v16i32, +- loadv4i64, sub_ymm>; ++ defm : subvector_zero_lowering<"APD", "UPD", VR128, v8f64, v2f64, ++ v16i32,loadv2f64, sub_xmm>; ++ defm : subvector_zero_lowering<"APS", "UPS", VR128, v16f32, v4f32, ++ v16i32, loadv4f32, sub_xmm>; ++ defm : subvector_zero_lowering<"DQA", "DQU", VR128, v8i64, v2i64, ++ v16i32, loadv2i64, sub_xmm>; ++ defm : subvector_zero_lowering<"DQA", "DQU", VR128, v16i32, v4i32, ++ v16i32, loadv2i64, sub_xmm>; ++ defm : subvector_zero_lowering<"DQA", "DQU", VR128, v32i16, v8i16, ++ v16i32, loadv2i64, sub_xmm>; ++ defm : subvector_zero_lowering<"DQA", "DQU", VR128, v64i8, v16i8, ++ v16i32, loadv2i64, sub_xmm>; ++ ++ defm : subvector_zero_lowering<"APDY", "UPDY", VR256, v8f64, v4f64, ++ v16i32, loadv4f64, sub_ymm>; ++ defm : subvector_zero_lowering<"APSY", "UPSY", VR256, v16f32, v8f32, ++ v16i32, loadv8f32, sub_ymm>; ++ defm : subvector_zero_lowering<"DQAY", "DQUY", VR256, v8i64, v4i64, ++ v16i32, loadv4i64, sub_ymm>; ++ defm : subvector_zero_lowering<"DQAY", "DQUY", VR256, v16i32, v8i32, ++ v16i32, loadv4i64, sub_ymm>; ++ defm : subvector_zero_lowering<"DQAY", "DQUY", VR256, v32i16, v16i16, ++ v16i32, loadv4i64, sub_ymm>; ++ defm : subvector_zero_lowering<"DQAY", "DQUY", VR256, v64i8, v32i8, ++ v16i32, loadv4i64, sub_ymm>; + } + + // List of opcodes that guaranteed to zero the upper elements of vector regs. +diff --git a/test/CodeGen/X86/merge-consecutive-loads-256.ll b/test/CodeGen/X86/merge-consecutive-loads-256.ll +index 6ecd8116443..0f2cf594b1c 100644 +--- a/test/CodeGen/X86/merge-consecutive-loads-256.ll ++++ b/test/CodeGen/X86/merge-consecutive-loads-256.ll +@@ -28,13 +28,13 @@ define <4 x double> @merge_4f64_2f64_23(<2 x double>* %ptr) nounwind uwtable noi + define <4 x double> @merge_4f64_2f64_2z(<2 x double>* %ptr) nounwind uwtable noinline ssp { + ; AVX-LABEL: merge_4f64_2f64_2z: + ; AVX: # %bb.0: +-; AVX-NEXT: vmovaps 32(%rdi), %xmm0 ++; AVX-NEXT: vmovups 32(%rdi), %xmm0 + ; AVX-NEXT: retq + ; + ; X32-AVX-LABEL: merge_4f64_2f64_2z: + ; X32-AVX: # %bb.0: + ; X32-AVX-NEXT: movl {{[0-9]+}}(%esp), %eax +-; X32-AVX-NEXT: vmovaps 32(%eax), %xmm0 ++; X32-AVX-NEXT: vmovups 32(%eax), %xmm0 + ; X32-AVX-NEXT: retl + %ptr0 = getelementptr inbounds <2 x double>, <2 x double>* %ptr, i64 2 + %val0 = load <2 x double>, <2 x double>* %ptr0 +@@ -109,13 +109,13 @@ define <4 x double> @merge_4f64_f64_34uu(double* %ptr) nounwind uwtable noinline + define <4 x double> @merge_4f64_f64_45zz(double* %ptr) nounwind uwtable noinline ssp { + ; AVX-LABEL: merge_4f64_f64_45zz: + ; AVX: # %bb.0: +-; AVX-NEXT: vmovaps 32(%rdi), %xmm0 ++; AVX-NEXT: vmovups 32(%rdi), %xmm0 + ; AVX-NEXT: retq + ; + ; X32-AVX-LABEL: merge_4f64_f64_45zz: + ; X32-AVX: # %bb.0: + ; X32-AVX-NEXT: movl {{[0-9]+}}(%esp), %eax +-; X32-AVX-NEXT: vmovaps 32(%eax), %xmm0 ++; X32-AVX-NEXT: vmovups 32(%eax), %xmm0 + ; X32-AVX-NEXT: retl + %ptr0 = getelementptr inbounds double, double* %ptr, i64 4 + %ptr1 = getelementptr inbounds double, double* %ptr, i64 5 +@@ -155,13 +155,13 @@ define <4 x double> @merge_4f64_f64_34z6(double* %ptr) nounwind uwtable noinline + define <4 x i64> @merge_4i64_2i64_3z(<2 x i64>* %ptr) nounwind uwtable noinline ssp { + ; AVX-LABEL: merge_4i64_2i64_3z: + ; AVX: # %bb.0: +-; AVX-NEXT: vmovaps 48(%rdi), %xmm0 ++; AVX-NEXT: vmovups 48(%rdi), %xmm0 + ; AVX-NEXT: retq + ; + ; X32-AVX-LABEL: merge_4i64_2i64_3z: + ; X32-AVX: # %bb.0: + ; X32-AVX-NEXT: movl {{[0-9]+}}(%esp), %eax +-; X32-AVX-NEXT: vmovaps 48(%eax), %xmm0 ++; X32-AVX-NEXT: vmovups 48(%eax), %xmm0 + ; X32-AVX-NEXT: retl + %ptr0 = getelementptr inbounds <2 x i64>, <2 x i64>* %ptr, i64 3 + %val0 = load <2 x i64>, <2 x i64>* %ptr0 +@@ -217,13 +217,13 @@ define <4 x i64> @merge_4i64_i64_1zzu(i64* %ptr) nounwind uwtable noinline ssp { + define <4 x i64> @merge_4i64_i64_23zz(i64* %ptr) nounwind uwtable noinline ssp { + ; AVX-LABEL: merge_4i64_i64_23zz: + ; AVX: # %bb.0: +-; AVX-NEXT: vmovaps 16(%rdi), %xmm0 ++; AVX-NEXT: vmovups 16(%rdi), %xmm0 + ; AVX-NEXT: retq + ; + ; X32-AVX-LABEL: merge_4i64_i64_23zz: + ; X32-AVX: # %bb.0: + ; X32-AVX-NEXT: movl {{[0-9]+}}(%esp), %eax +-; X32-AVX-NEXT: vmovaps 16(%eax), %xmm0 ++; X32-AVX-NEXT: vmovups 16(%eax), %xmm0 + ; X32-AVX-NEXT: retl + %ptr0 = getelementptr inbounds i64, i64* %ptr, i64 2 + %ptr1 = getelementptr inbounds i64, i64* %ptr, i64 3 +diff --git a/test/CodeGen/X86/merge-consecutive-loads-512.ll b/test/CodeGen/X86/merge-consecutive-loads-512.ll +index 62102eb382c..3c6eaf65292 100644 +--- a/test/CodeGen/X86/merge-consecutive-loads-512.ll ++++ b/test/CodeGen/X86/merge-consecutive-loads-512.ll +@@ -106,13 +106,13 @@ define <8 x double> @merge_8f64_f64_23uuuuu9(double* %ptr) nounwind uwtable noin + define <8 x double> @merge_8f64_f64_12zzuuzz(double* %ptr) nounwind uwtable noinline ssp { + ; ALL-LABEL: merge_8f64_f64_12zzuuzz: + ; ALL: # %bb.0: +-; ALL-NEXT: vmovaps 8(%rdi), %xmm0 ++; ALL-NEXT: vmovups 8(%rdi), %xmm0 + ; ALL-NEXT: retq + ; + ; X32-AVX512F-LABEL: merge_8f64_f64_12zzuuzz: + ; X32-AVX512F: # %bb.0: + ; X32-AVX512F-NEXT: movl {{[0-9]+}}(%esp), %eax +-; X32-AVX512F-NEXT: vmovaps 8(%eax), %xmm0 ++; X32-AVX512F-NEXT: vmovups 8(%eax), %xmm0 + ; X32-AVX512F-NEXT: retl + %ptr0 = getelementptr inbounds double, double* %ptr, i64 1 + %ptr1 = getelementptr inbounds double, double* %ptr, i64 2 +@@ -190,7 +190,7 @@ define <8 x i64> @merge_8i64_4i64_z3(<4 x i64>* %ptr) nounwind uwtable noinline + define <8 x i64> @merge_8i64_i64_56zz9uzz(i64* %ptr) nounwind uwtable noinline ssp { + ; ALL-LABEL: merge_8i64_i64_56zz9uzz: + ; ALL: # %bb.0: +-; ALL-NEXT: vmovaps 40(%rdi), %xmm0 ++; ALL-NEXT: vmovups 40(%rdi), %xmm0 + ; ALL-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero + ; ALL-NEXT: vinsertf64x4 $1, %ymm1, %zmm0, %zmm0 + ; ALL-NEXT: retq +@@ -198,7 +198,7 @@ define <8 x i64> @merge_8i64_i64_56zz9uzz(i64* %ptr) nounwind uwtable noinline s + ; X32-AVX512F-LABEL: merge_8i64_i64_56zz9uzz: + ; X32-AVX512F: # %bb.0: + ; X32-AVX512F-NEXT: movl {{[0-9]+}}(%esp), %eax +-; X32-AVX512F-NEXT: vmovaps 40(%eax), %xmm0 ++; X32-AVX512F-NEXT: vmovups 40(%eax), %xmm0 + ; X32-AVX512F-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero + ; X32-AVX512F-NEXT: vinsertf64x4 $1, %ymm1, %zmm0, %zmm0 + ; X32-AVX512F-NEXT: retl From e35fe835e72da2adb0e5921b869ab96222eeecad Mon Sep 17 00:00:00 2001 From: ExpandingMan Date: Tue, 4 Sep 2018 16:09:39 -0400 Subject: [PATCH 088/166] fixed regression in sparse of adjoint of sparse (#28948) (#28954) * fixed regression in sparse of adjoint (cherry picked from commit c43793c5eb48bb86e6bb40111a81ffe7da34b63f) --- stdlib/SparseArrays/src/sparsematrix.jl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/stdlib/SparseArrays/src/sparsematrix.jl b/stdlib/SparseArrays/src/sparsematrix.jl index f954d33393d61..5b107ff86d258 100644 --- a/stdlib/SparseArrays/src/sparsematrix.jl +++ b/stdlib/SparseArrays/src/sparsematrix.jl @@ -401,6 +401,16 @@ function SparseMatrixCSC{Tv,Ti}(M::StridedMatrix) where {Tv,Ti} end SparseMatrixCSC(M::Adjoint{<:Any,<:SparseMatrixCSC}) = copy(M) SparseMatrixCSC(M::Transpose{<:Any,<:SparseMatrixCSC}) = copy(M) +SparseMatrixCSC{Tv}(M::Adjoint{Tv,SparseMatrixCSC{Tv}}) where {Tv} = copy(M) +SparseMatrixCSC{Tv}(M::Transpose{Tv,SparseMatrixCSC{Tv}}) where {Tv} = copy(M) +SparseMatrixCSC{Tv,Ti}(M::Adjoint{Tv,SparseMatrixCSC{Tv,Ti}}) where {Tv,Ti} = copy(M) +SparseMatrixCSC{Tv,Ti}(M::Transpose{Tv,SparseMatrixCSC{Tv,Ti}}) where {Tv,Ti} = copy(M) + +# converting from adjoint or transpose sparse matrices to sparse matrices with different eltype +SparseMatrixCSC{Tv}(M::Adjoint{<:Any,SparseMatrixCSC}) where {Tv} = SparseMatrixCSC{Tv}(copy(M)) +SparseMatrixCSC{Tv}(M::Transpose{<:Any,SparseMatrixCSC}) where {Tv} = SparseMatrixCSC{Tv}(copy(M)) +SparseMatrixCSC{Tv,Ti}(M::Adjoint{<:Any,SparseMatrixCSC}) where {Tv,Ti} = SparseMatrixCSC{Tv,Ti}(copy(M)) +SparseMatrixCSC{Tv,Ti}(M::Transpose{<:Any,SparseMatrixCSC}) where {Tv,Ti} = SparseMatrixCSC{Tv,Ti}(copy(M)) # converting from SparseMatrixCSC to other matrix types function Matrix(S::SparseMatrixCSC{Tv}) where Tv From e99894f23202c5f735b133007a1cf05cc45197fe Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Mon, 13 Aug 2018 16:38:02 +0200 Subject: [PATCH 089/166] no longer update on add (cherry picked from commit eaee5cceb1d690822e1faa1e422d8bce6718fe18) (cherry picked from commit ff1f09c545e0fe51e78463296a9672865d4641cc) (cherry picked from commit 2909e7c403674cafb482a30983f64f37b73156d8) --- stdlib/Pkg/src/Operations.jl | 17 +++++++++-------- stdlib/Pkg/test/pkg.jl | 3 +++ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/stdlib/Pkg/src/Operations.jl b/stdlib/Pkg/src/Operations.jl index f03de979c85dc..a778b83be9de8 100644 --- a/stdlib/Pkg/src/Operations.jl +++ b/stdlib/Pkg/src/Operations.jl @@ -310,16 +310,17 @@ function resolve_versions!(ctx::Context, pkgs::Vector{PackageSpec})::Dict{UUID,V uuid_to_name[uuid] = name uuid_idx = findfirst(isequal(uuid), uuids) - ver = VersionSpec() + info = manifest_info(ctx.env, uuid) + if info !== nothing && haskey(info, "version") # stdlibs might not have a version + ver = VersionSpec(VersionNumber(info["version"])) + else + ver = VersionSpec() + end if uuid_idx != nothing pkg = pkgs[uuid_idx] - info = manifest_info(ctx.env, uuid) - if info !== nothing && haskey(info, "version") # stdlibs might not have a version - ver = VersionNumber(info["version"]) - if pkg.special_action != PKGSPEC_FREED && get(info, "pinned", false) - # This is a pinned package, fix its version - pkg.version = ver - end + if info !== nothing && pkg.special_action != PKGSPEC_FREED && get(info, "pinned", false) + # This is a pinned package, fix its version + pkg.version = ver end else pkg = PackageSpec(name, uuid, ver) diff --git a/stdlib/Pkg/test/pkg.jl b/stdlib/Pkg/test/pkg.jl index 32e1f8d18bb5c..a918dc5d66cd4 100644 --- a/stdlib/Pkg/test/pkg.jl +++ b/stdlib/Pkg/test/pkg.jl @@ -144,6 +144,9 @@ temp_pkg_dir() do project_path # VersionRange Pkg.add(PackageSpec(TEST_PKG.name, VersionSpec(VersionRange("0.3.0-0.3.2")))) @test Pkg.API.__installed()[TEST_PKG.name] == v"0.3.2" + # Check that adding another packages doesn't upgrade other packages + Pkg.add("Test") + @test Pkg.API.__installed()[TEST_PKG.name] == v"0.3.2" Pkg.update(; level = UPLEVEL_PATCH) @test Pkg.API.__installed()[TEST_PKG.name] == v"0.3.3" Pkg.update(; level = UPLEVEL_MINOR) From 8398ea68c0c358d65d32367e8795d486fcf020dc Mon Sep 17 00:00:00 2001 From: David Varela <00.varela.david@gmail.com> Date: Wed, 8 Aug 2018 07:47:37 -0700 Subject: [PATCH 090/166] Remove `--env` meta option (cherry picked from commit 4efb50e7788199ef26bc6288416d34a5f6db8975) (cherry picked from commit e80a83ebadc57dbea826cd69a580ca898571c119) (cherry picked from commit 5165018febc6b9698e6edcd8f07914a02b6e1b93) --- stdlib/Pkg/src/REPLMode.jl | 16 +++------------- stdlib/Pkg/test/repl.jl | 1 - 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index a9c9822863938..3e3d29a0188b6 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -81,9 +81,8 @@ function parse_option(word::AbstractString)::Option return Option(option_name, option_arg) end -meta_option_declarations = OptionDeclaration[ - ("env", OPT_ARG, :env => arg->EnvCache(Base.parse_env(arg))) -] +# declare meta options here +meta_option_declarations = OptionDeclaration[] meta_option_specs = OptionSpecs(meta_option_declarations) ################ @@ -1235,19 +1234,10 @@ backspace when the input line is empty or press Ctrl+C. **Synopsis** - pkg> [--env=...] cmd [opts] [args] + pkg> cmd [opts] [args] Multiple commands can be given on the same line by interleaving a `;` between the commands. -**Environment** - -The `--env` meta option determines which project environment to manipulate. By -default, this looks for a git repo in the parents directories of the current -working directory, and if it finds one, it uses that as an environment. Otherwise, -it uses a named environment (typically found in `~/.julia/environments`) looking -for environments named `v$(VERSION.major).$(VERSION.minor).$(VERSION.patch)`, -`v$(VERSION.major).$(VERSION.minor)`, `v$(VERSION.major)` or `default` in order. - **Commands** What action you want the package manager to take: diff --git a/stdlib/Pkg/test/repl.jl b/stdlib/Pkg/test/repl.jl index 3c80a9b7d904a..b3c88e57c7948 100644 --- a/stdlib/Pkg/test/repl.jl +++ b/stdlib/Pkg/test/repl.jl @@ -820,7 +820,6 @@ end @test_throws PkgError Pkg.REPLMode.pkgstr("--foo=foo add Example") @test_throws PkgError Pkg.REPLMode.pkgstr("--bar add Example") @test_throws PkgError Pkg.REPLMode.pkgstr("-x add Example") - # malformed, but registered meta option @test_throws PkgError Pkg.REPLMode.pkgstr("--env Example") end end end end From 3d29983b04e6400fe931ef2bed281657b6df86d2 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Mon, 13 Aug 2018 11:36:48 +0200 Subject: [PATCH 091/166] Better info messages for activating new environment. (cherry picked from commit be4d03db83e777d04f06b22de6622a70e0f85e0f) (cherry picked from commit a8d0d2babe6e07e1533df9755dc245c16618e670) (cherry picked from commit 65964b140dabecd929d89f1a39db8758803d07a1) --- stdlib/Pkg/src/API.jl | 4 ++-- stdlib/Pkg/test/repl.jl | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/stdlib/Pkg/src/API.jl b/stdlib/Pkg/src/API.jl index a4cc2a363f682..f9a23ab651f68 100644 --- a/stdlib/Pkg/src/API.jl +++ b/stdlib/Pkg/src/API.jl @@ -572,7 +572,7 @@ function activate(path::String; shared::Bool=false) fullpath = abspath(devpath) else fullpath = abspath(path) - isdir(fullpath) || @info("new environment will be placed at $fullpath") + isdir(fullpath) || @info("activating new environment at $(Base.contractuser(fullpath)).") end else # initialize `fullpath` in case of empty `Pkg.depots()` @@ -589,7 +589,7 @@ function activate(path::String; shared::Bool=false) # unless the shared environment already exists, place it in the first depots if !isdir(fullpath) fullpath = joinpath(Pkg.envdir(Pkg.depots1()), path) - @info("new shared environment \"$path\" will be placed at $fullpath") + @info("activating new environment at $(Base.contractuser(fullpath)).") end end Base.ACTIVE_PROJECT[] = Base.load_path_expand(fullpath) diff --git a/stdlib/Pkg/test/repl.jl b/stdlib/Pkg/test/repl.jl index b3c88e57c7948..67211ece0e27b 100644 --- a/stdlib/Pkg/test/repl.jl +++ b/stdlib/Pkg/test/repl.jl @@ -264,21 +264,21 @@ temp_pkg_dir() do project_path pkg"activate Foo" # activate path Foo over deps Foo @test Base.active_project() == joinpath(path, "Foo", "Project.toml") pkg"activate ." - @test_logs (:info, r"new shared environment") pkg"activate --shared Foo" # activate shared Foo + @test_logs (:info, r"activating new environment at ") pkg"activate --shared Foo" # activate shared Foo @test Base.active_project() == joinpath(Pkg.envdir(), "Foo", "Project.toml") pkg"activate ." rm("Foo"; force=true, recursive=true) pkg"activate Foo" # activate path from developed Foo @test Base.active_project() == joinpath(path, "modules", "Foo", "Project.toml") pkg"activate ." - @test_logs (:info, r"new environment") pkg"activate ./Foo" # activate empty directory Foo (sidestep the developed Foo) + @test_logs (:info, r"activating new environment at ") pkg"activate ./Foo" # activate empty directory Foo (sidestep the developed Foo) @test Base.active_project() == joinpath(path, "Foo", "Project.toml") pkg"activate ." - @test_logs (:info, r"new environment") pkg"activate Bar" # activate empty directory Bar + @test_logs (:info, r"activating new environment at ") pkg"activate Bar" # activate empty directory Bar @test Base.active_project() == joinpath(path, "Bar", "Project.toml") pkg"activate ." pkg"add Example" # non-deved deps should not be activated - @test_logs (:info, r"new environment") pkg"activate Example" + @test_logs (:info, r"activating new environment at ") pkg"activate Example" @test Base.active_project() == joinpath(path, "Example", "Project.toml") pkg"activate ." cd(mkdir("tests")) From 6cd963b6688c11ebe7a655c13886ab3a9aa3817b Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Tue, 14 Aug 2018 01:29:50 +0200 Subject: [PATCH 092/166] remove unnecessary version handling when dealing with repos, this is handled in the resolver (cherry picked from commit 6f3e865edc016eb0e2507d55d70aa755e68d9e7c) (cherry picked from commit c31f924eb7df7126de59ce901a7310c0a56e8e93) (cherry picked from commit 87d666991ed58b114ba7d983854814c846499ca2) --- stdlib/Pkg/src/Operations.jl | 31 ++++++++++++++++++++----------- stdlib/Pkg/src/Types.jl | 15 ++------------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/stdlib/Pkg/src/Operations.jl b/stdlib/Pkg/src/Operations.jl index a778b83be9de8..2328e29b2bffa 100644 --- a/stdlib/Pkg/src/Operations.jl +++ b/stdlib/Pkg/src/Operations.jl @@ -98,7 +98,6 @@ function collect_fixed!(ctx::Context, pkgs::Vector{PackageSpec}, uuid_to_name::D path = pkg.path elseif info !== nothing && haskey(info, "repo-url") path = find_installed(pkg.name, pkg.uuid, SHA1(info["git-tree-sha1"])) - pkg.version = VersionNumber(info["version"]) pkg.repo = Types.GitRepo(info["repo-url"], info["repo-rev"], SHA1(info["git-tree-sha1"])) else continue @@ -326,23 +325,33 @@ function resolve_versions!(ctx::Context, pkgs::Vector{PackageSpec})::Dict{UUID,V pkg = PackageSpec(name, uuid, ver) push!(pkgs, pkg) end - proj_compat = Types.project_compatibility(ctx, name) - v = intersect(pkg.version, proj_compat) - if isempty(v) - pkgerror(string("for package $(pkg.name) intersection between project compatibility $(proj_compat) ", - "and package version $(pkg.version) is empty")) - end - pkg.version = v end + + # construct data structures for resolver and call it + # this also sets pkg.version for fixed packages + fixed = collect_fixed!(ctx, pkgs, uuid_to_name) + + # compatibility proj_compat = Types.project_compatibility(ctx, "julia") v = intersect(VERSION, proj_compat) if isempty(v) - @warn("julia version requirement for project not satisfied") + @warn "julia version requirement for project not satisfied" _module=nothing _file=nothing + end + + for pkg in pkgs + proj_compat = Types.project_compatibility(ctx, pkg.name) + v = intersect(pkg.version, proj_compat) + if isempty(v) + pkgerror(string("empty intersection between $(pkg.name)@$(pkg.version) and project ", + "compatibility $(proj_compat)")) + end + # Work around not clobbering 0.x.y+ for checked out old type of packages + if !(pkg.version isa VersionNumber) + pkg.version = v + end end - # construct data structures for resolver and call it reqs = Requires(pkg.uuid => VersionSpec(pkg.version) for pkg in pkgs if pkg.uuid ≠ uuid_julia) - fixed = collect_fixed!(ctx, pkgs, uuid_to_name) fixed[uuid_julia] = Fixed(VERSION) graph = deps_graph(ctx, uuid_to_name, reqs, fixed) diff --git a/stdlib/Pkg/src/Types.jl b/stdlib/Pkg/src/Types.jl index 1cd15177f05f6..9b97e99b243ae 100644 --- a/stdlib/Pkg/src/Types.jl +++ b/stdlib/Pkg/src/Types.jl @@ -582,6 +582,7 @@ function handle_repos_develop!(ctx::Context, pkgs::AbstractVector{PackageSpec}, pkg.path = Pkg.Operations.relative_project_path_if_in_project(ctx, dev_pkg_path) end @assert pkg.path != nothing + @assert has_uuid(pkg) end return new_uuids end @@ -679,7 +680,7 @@ function handle_repos_add!(ctx::Context, pkgs::AbstractVector{PackageSpec}; mv(project_path, version_path; force=true) push!(new_uuids, pkg.uuid) end - @assert pkg.version isa VersionNumber + @assert has_uuid(pkg) end return new_uuids finally @@ -694,14 +695,7 @@ function parse_package!(ctx, pkg, project_path) project_data = read_package(project_file) pkg.uuid = UUID(project_data["uuid"]) pkg.name = project_data["name"] - if haskey(project_data, "version") - pkg.version = VersionNumber(project_data["version"]) - else - @warn "project file for $(pkg.name) at $(project_path) is missing a `version` entry" - Pkg.Operations.set_maximum_version_registry!(env, pkg) - end else - # @warn "package $(pkg.name) at $(project_path) will need to have a [Julia]Project.toml file in the future" if !isempty(ctx.old_pkg2_clone_name) # remove when legacy CI script support is removed pkg.name = ctx.old_pkg2_clone_name else @@ -723,14 +717,9 @@ function parse_package!(ctx, pkg, project_path) pkg.uuid = uuid5(uuid_unreg_pkg, pkg.name) @info "Assigning UUID $(pkg.uuid) to $(pkg.name)" end - pkg.version = v"0.0" else - # TODO: Fix @assert length(reg_uuids) == 1 pkg.uuid = reg_uuids[1] - # Old style registered package - # What version does this package have? We have no idea... let's give it the latest one with a `+`... - Pkg.Operations.set_maximum_version_registry!(env, pkg) end end end From 713fcef6acc18db5c42a6fe706abd4e2d6b1b2bc Mon Sep 17 00:00:00 2001 From: Sebastian Pfitzner Date: Wed, 8 Aug 2018 00:58:53 +0200 Subject: [PATCH 093/166] add path completions to add/dev in repl (cherry picked from commit 9cbe4a262ebeabd415ec46b80ee760aee0f009bd) (cherry picked from commit da9baa2e5fe82904c1fb269e8d5ad93b7189d504) (cherry picked from commit 4e660116ab2b6dfc0807513fbfdb88bf970fd20e) --- stdlib/Pkg/src/REPLMode.jl | 13 +++- stdlib/Pkg/test/repl.jl | 126 ++++++++++++++++++++----------------- 2 files changed, 80 insertions(+), 59 deletions(-) diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index 3e3d29a0188b6..632c34f75e0e0 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -697,11 +697,22 @@ function complete_package(s, i1, i2, lastcommand, project_opt) if lastcommand in [CMD_STATUS, CMD_RM, CMD_UP, CMD_TEST, CMD_BUILD, CMD_FREE, CMD_PIN] return complete_installed_package(s, i1, i2, project_opt) elseif lastcommand in [CMD_ADD, CMD_DEVELOP] - return complete_remote_package(s, i1, i2) + if occursin(Base.Filesystem.path_separator_re, s) + return complete_local_path(s, i1, i2) + else + rps = complete_remote_package(s, i1, i2) + lps = complete_local_path(s, i1, i2) + return vcat(rps[1], lps[1]), isempty(rps[1]) ? lps[2] : i1:i2, length(rps[1]) + length(lps[1]) > 0 + end end return String[], 0:-1, false end +function complete_local_path(s, i1, i2) + cmp = REPL.REPLCompletions.complete_path(s, i2) + [REPL.REPLCompletions.completion_text(p) for p in cmp[1]], cmp[2], !isempty(cmp[1]) +end + function complete_installed_package(s, i1, i2, project_opt) pkgs = project_opt ? API.__installed(PKGMODE_PROJECT) : API.__installed() pkgs = sort!(collect(keys(filter((p) -> p[2] != nothing, pkgs)))) diff --git a/stdlib/Pkg/test/repl.jl b/stdlib/Pkg/test/repl.jl index 67211ece0e27b..877f5ec756f0d 100644 --- a/stdlib/Pkg/test/repl.jl +++ b/stdlib/Pkg/test/repl.jl @@ -327,69 +327,79 @@ end test_complete(s) = Pkg.REPLMode.completions(s,lastindex(s)) apply_completion(str) = begin c, r, s = test_complete(str) - @test s == true str[1:prevind(str, first(r))]*first(c) end # Autocompletions temp_pkg_dir() do project_path; cd(project_path) do - Pkg.Types.registries() - pkg"activate ." - c, r = test_complete("add Exam") - @test "Example" in c - c, r = test_complete("rm Exam") - @test isempty(c) - Pkg.REPLMode.pkgstr("develop $(joinpath(@__DIR__, "test_packages", "RequireDependency"))") - - c, r = test_complete("rm RequireDep") - @test "RequireDependency" in c - c, r = test_complete("rm -p RequireDep") - @test "RequireDependency" in c - c, r = test_complete("rm --project RequireDep") - @test "RequireDependency" in c - c, r = test_complete("rm Exam") - @test isempty(c) - c, r = test_complete("rm -p Exam") - @test isempty(c) - c, r = test_complete("rm --project Exam") - @test isempty(c) - - c, r = test_complete("rm -m RequireDep") - @test "RequireDependency" in c - c, r = test_complete("rm --manifest RequireDep") - @test "RequireDependency" in c - c, r = test_complete("rm -m Exam") - @test "Example" in c - c, r = test_complete("rm --manifest Exam") - @test "Example" in c - - c, r = test_complete("rm RequireDep") - @test "RequireDependency" in c - c, r = test_complete("rm Exam") - @test isempty(c) - c, r = test_complete("rm -m Exam") - c, r = test_complete("rm -m Exam") - @test "Example" in c - - pkg"add Example" - c, r = test_complete("rm Exam") - @test "Example" in c - c, r = test_complete("add --man") - @test "--manifest" in c - c, r = test_complete("rem") - @test "remove" in c - @test apply_completion("rm E") == "rm Example" - @test apply_completion("add Exampl") == "add Example" - - c, r = test_complete("preview r") - @test "remove" in c - c, r = test_complete("help r") - @test "remove" in c - @test !("rm" in c) - - c, r = test_complete("add REPL") - # Filtered by version - @test !("REPL" in c) + @testset "tab completion" begin + Pkg.Types.registries() + pkg"activate ." + c, r = test_complete("add Exam") + @test "Example" in c + c, r = test_complete("rm Exam") + @test isempty(c) + Pkg.REPLMode.pkgstr("develop $(joinpath(@__DIR__, "test_packages", "RequireDependency"))") + + c, r = test_complete("rm RequireDep") + @test "RequireDependency" in c + c, r = test_complete("rm -p RequireDep") + @test "RequireDependency" in c + c, r = test_complete("rm --project RequireDep") + @test "RequireDependency" in c + c, r = test_complete("rm Exam") + @test isempty(c) + c, r = test_complete("rm -p Exam") + @test isempty(c) + c, r = test_complete("rm --project Exam") + @test isempty(c) + + c, r = test_complete("rm -m RequireDep") + @test "RequireDependency" in c + c, r = test_complete("rm --manifest RequireDep") + @test "RequireDependency" in c + c, r = test_complete("rm -m Exam") + @test "Example" in c + c, r = test_complete("rm --manifest Exam") + @test "Example" in c + + c, r = test_complete("rm RequireDep") + @test "RequireDependency" in c + c, r = test_complete("rm Exam") + @test isempty(c) + c, r = test_complete("rm -m Exam") + c, r = test_complete("rm -m Exam") + @test "Example" in c + + pkg"add Example" + c, r = test_complete("rm Exam") + @test "Example" in c + c, r = test_complete("add --man") + @test "--manifest" in c + c, r = test_complete("rem") + @test "remove" in c + @test apply_completion("rm E") == "rm Example" + @test apply_completion("add Exampl") == "add Example" + + c, r = test_complete("preview r") + @test "remove" in c + c, r = test_complete("help r") + @test "remove" in c + @test !("rm" in c) + + c, r = test_complete("add REPL") + # Filtered by version + @test !("REPL" in c) + + mkdir("testdir") + c, r = test_complete("add ") + @test Sys.iswindows() ? ("testdir\\\\" in c) : ("testdir/" in c) + @test "Example" in c + @test apply_completion("add tes") == (Sys.iswindows() ? "add testdir\\\\" : "add testdir/") + @test apply_completion("add ./tes") == (Sys.iswindows() ? "add ./testdir\\\\" : "add ./testdir/") + c, r = test_complete("dev ./") + @test (Sys.iswindows() ? ("testdir\\\\" in c) : ("testdir/" in c)) + end end end temp_pkg_dir() do project_path; cd(project_path) do From 80227fd2474384f87211e43dd65c25ed47e32c94 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Tue, 14 Aug 2018 14:46:25 +0200 Subject: [PATCH 094/166] update the repo when the gitobject is not available (cherry picked from commit 58b57acc3e56ca269d30d6cc9eba9174e5c2423c) (cherry picked from commit 5ca249afd1a374546395b0c98a7021ae70596f39) (cherry picked from commit 286e43b2ca0cb552dc18d72eaa24c73568bd59c1) --- stdlib/Pkg/src/Types.jl | 44 ++++++++++++++++++++------------------ stdlib/Pkg/test/pkg.jl | 46 +++++++++++++++++++++++++++++++++++++++- stdlib/Pkg/test/repl.jl | 3 --- stdlib/Pkg/test/utils.jl | 5 +++++ 4 files changed, 73 insertions(+), 25 deletions(-) diff --git a/stdlib/Pkg/src/Types.jl b/stdlib/Pkg/src/Types.jl index 9b97e99b243ae..4f93d4e10b7cc 100644 --- a/stdlib/Pkg/src/Types.jl +++ b/stdlib/Pkg/src/Types.jl @@ -550,7 +550,7 @@ function handle_repos_develop!(ctx::Context, pkgs::AbstractVector{PackageSpec}, else rev = string(LibGit2.GitHash(LibGit2.head(repo))) end - gitobject, isbranch = get_object_branch(repo, rev) + gitobject, isbranch = get_object_branch(repo, rev, creds) try LibGit2.transact(repo) do r if isbranch @@ -608,35 +608,32 @@ function handle_repos_add!(ctx::Context, pkgs::AbstractVector{PackageSpec}; project_path = nothing folder_already_downloaded = false try - repo, just_cloned = ispath(repo_path) ? (LibGit2.GitRepo(repo_path), false) : begin - r = GitTools.clone(pkg.repo.url, repo_path, isbare=true, credentials=creds) - GitTools.fetch(r, pkg.repo.url; refspecs=refspecs, credentials=creds) - r, true + repo = if ispath(repo_path) + LibGit2.GitRepo(repo_path) + else + GitTools.clone(pkg.repo.url, repo_path, isbare=true, credentials=creds) end info = manifest_info(env, pkg.uuid) pinned = (info != nothing && get(info, "pinned", false)) - if upgrade_or_add && !pinned && !just_cloned - rev = pkg.repo.rev - GitTools.fetch(repo, pkg.repo.url; refspecs=refspecs, credentials=creds) - end upgrading = upgrade_or_add && !pinned if upgrading + GitTools.fetch(repo; refspecs=refspecs, credentials=creds) rev = pkg.repo.rev + # see if we can get rev as a branch + if isempty(rev) + if LibGit2.isattached(repo) + rev = LibGit2.branch(repo) + else + rev = string(LibGit2.GitHash(LibGit2.head(repo))) + end + end else # Not upgrading so the rev should be the current git-tree-sha rev = info["git-tree-sha1"] pkg.version = VersionNumber(info["version"]) end - # see if we can get rev as a branch - if isempty(rev) - if LibGit2.isattached(repo) - rev = LibGit2.branch(repo) - else - rev = string(LibGit2.GitHash(LibGit2.head(repo))) - end - end - gitobject, isbranch = get_object_branch(repo, rev) + gitobject, isbranch = get_object_branch(repo, rev, creds) # If the user gave a shortened commit SHA, might as well update it to the full one try if upgrading @@ -653,7 +650,6 @@ function handle_repos_add!(ctx::Context, pkgs::AbstractVector{PackageSpec}; info = manifest_info(env, pkg.uuid) if info != nothing && get(info, "git-tree-sha1", "") == string(pkg.repo.git_tree_sha1) && folder_already_downloaded # Same tree sha and this version already downloaded, nothing left to do - pkg.version = VersionNumber(info["version"]) do_nothing_more = true end end @@ -733,7 +729,7 @@ function set_repo_for_pkg!(env, pkg) _, pkg.repo.url = Types.registered_info(env, pkg.uuid, "repo")[1] end -function get_object_branch(repo, rev) +function get_object_branch(repo, rev, creds) gitobject = nothing isbranch = false try @@ -747,7 +743,13 @@ function get_object_branch(repo, rev) gitobject = LibGit2.GitObject(repo, rev) catch err err isa LibGit2.GitError && err.code == LibGit2.Error.ENOTFOUND || rethrow(err) - pkgerror("git object $(rev) could not be found") + GitTools.fetch(repo; refspecs=refspecs, credentials=creds) + try + gitobject = LibGit2.GitObject(repo, rev) + catch err + err isa LibGit2.GitError && err.code == LibGit2.Error.ENOTFOUND || rethrow(err) + pkgerror("git object $(rev) could not be found") + end end end return gitobject, isbranch diff --git a/stdlib/Pkg/test/pkg.jl b/stdlib/Pkg/test/pkg.jl index a918dc5d66cd4..5ecc3a9c985bf 100644 --- a/stdlib/Pkg/test/pkg.jl +++ b/stdlib/Pkg/test/pkg.jl @@ -156,7 +156,6 @@ temp_pkg_dir() do project_path @testset "testing" begin # TODO: Check that preview = true doesn't actually execute the test - # TODO: Test-only dependencies Pkg.add(TEST_PKG.name) Pkg.test(TEST_PKG.name; coverage=true) pkgdir = Base.locate_package(Base.PkgId(TEST_PKG.uuid, TEST_PKG.name)) @@ -417,6 +416,51 @@ temp_pkg_dir() do project_path end end +temp_pkg_dir() do project_path; cd(project_path) do + @testset "instantiating updated repo" begin + tmp = mktempdir() + cd(tmp) + depo1 = mktempdir() + depo2 = mktempdir() + + empty!(DEPOT_PATH) + pushfirst!(DEPOT_PATH, depo1) + LibGit2.close(LibGit2.clone("https://github.com/JuliaLang/Example.jl", "Example.jl")) + mkdir("machine1") + cd("machine1") + Pkg.activate(".") + Pkg.add(PackageSpec(path="../Example.jl")) + cd("..") + cp("machine1", "machine2") + empty!(DEPOT_PATH) + pushfirst!(DEPOT_PATH, depo2) + cd("machine2") + Pkg.activate(".") + Pkg.instantiate() + cd("..") + cd("Example.jl") + open("README.md", "a") do io + print(io, "Hello") + end + LibGit2.with(LibGit2.GitRepo(".")) do repo + LibGit2.add!(repo, "*") + LibGit2.commit(repo, "changes"; author=TEST_SIG, committer=TEST_SIG) + end + cd("../machine1") + empty!(DEPOT_PATH) + pushfirst!(DEPOT_PATH, depo1) + Pkg.activate(".") + Pkg.update() + cd("..") + cp("machine1/Manifest.toml", "machine2/Manifest.toml"; force=true) + cd("machine2") + empty!(DEPOT_PATH) + pushfirst!(DEPOT_PATH, depo2) + Pkg.activate(".") + Pkg.instantiate() + end +end end + temp_pkg_dir() do project_path cd(project_path) do project = """ diff --git a/stdlib/Pkg/test/repl.jl b/stdlib/Pkg/test/repl.jl index 877f5ec756f0d..57ed232d002a1 100644 --- a/stdlib/Pkg/test/repl.jl +++ b/stdlib/Pkg/test/repl.jl @@ -10,9 +10,6 @@ import LibGit2 include("utils.jl") -const TEST_SIG = LibGit2.Signature("TEST", "TEST@TEST.COM", round(time()), 0) -const TEST_PKG = (name = "Example", uuid = UUID("7876af07-990d-54b4-ab0e-23690620f79a")) - function git_init_package(tmp, path) base = basename(path) pkgpath = joinpath(tmp, base) diff --git a/stdlib/Pkg/test/utils.jl b/stdlib/Pkg/test/utils.jl index a93ca4c92872a..f8f3a75a55b29 100644 --- a/stdlib/Pkg/test/utils.jl +++ b/stdlib/Pkg/test/utils.jl @@ -80,3 +80,8 @@ function with_pkg_env(fn::Function, path::AbstractString="."; change_dir=false) Pkg.activate() end end + +import LibGit2 +using UUIDs +const TEST_SIG = LibGit2.Signature("TEST", "TEST@TEST.COM", round(time()), 0) +const TEST_PKG = (name = "Example", uuid = UUID("7876af07-990d-54b4-ab0e-23690620f79a")) From 1cc648a729a90ddc3150a69f8a7e4a454448cbbf Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Wed, 15 Aug 2018 11:50:33 +0200 Subject: [PATCH 095/166] Fix a bug where the path was stored as relative because devdir() happened to be in the project. The path should only be relative if the user used --local. (cherry picked from commit 1d3c5aabb2b45ed89bac53fc739d0ae7c6379b32) (cherry picked from commit 7f46aca7b470aa3d0c694862b784e994e5806f4f) (cherry picked from commit 3c569ac6c502e79076b3e2c99c792a5cfb694bd1) --- stdlib/Pkg/src/API.jl | 3 +-- stdlib/Pkg/src/Operations.jl | 13 ++----------- stdlib/Pkg/src/Types.jl | 25 +++++++++++++++++++------ stdlib/Pkg/test/repl.jl | 34 +++++++++++++++++++++++++++++++++- 4 files changed, 55 insertions(+), 20 deletions(-) diff --git a/stdlib/Pkg/src/API.jl b/stdlib/Pkg/src/API.jl index f9a23ab651f68..f015d7693dc8a 100644 --- a/stdlib/Pkg/src/API.jl +++ b/stdlib/Pkg/src/API.jl @@ -48,8 +48,7 @@ function add_or_develop(ctx::Context, pkgs::Vector{PackageSpec}; mode::Symbol, s ctx.preview && preview_info() if mode == :develop - devdir = shared ? Pkg.devdir() : joinpath(dirname(ctx.env.project_file), "dev") - new_git = handle_repos_develop!(ctx, pkgs, devdir) + new_git = handle_repos_develop!(ctx, pkgs, shared = shared) else new_git = handle_repos_add!(ctx, pkgs; upgrade_or_add=true) end diff --git a/stdlib/Pkg/src/Operations.jl b/stdlib/Pkg/src/Operations.jl index 2328e29b2bffa..1e5a6cced6bb3 100644 --- a/stdlib/Pkg/src/Operations.jl +++ b/stdlib/Pkg/src/Operations.jl @@ -657,17 +657,8 @@ function find_stdlib_deps(ctx::Context, path::String) return stdlib_deps end -function relative_project_path_if_in_project(ctx::Context, path::String) - # Check if path is in project => relative - project_path = dirname(ctx.env.project_file) - if startswith(normpath(path), project_path) - return relpath(path, project_path) - else - return abspath(path) - end -end - -project_rel_path(ctx::Context, path::String) = joinpath(dirname(ctx.env.project_file), path) +project_rel_path(ctx::Context, path::String) = + normpath(joinpath(dirname(ctx.env.project_file), path)) function update_manifest(ctx::Context, pkg::PackageSpec, hash::Union{SHA1, Nothing}) env = ctx.env diff --git a/stdlib/Pkg/src/Types.jl b/stdlib/Pkg/src/Types.jl index 4f93d4e10b7cc..83403d60b1d0b 100644 --- a/stdlib/Pkg/src/Types.jl +++ b/stdlib/Pkg/src/Types.jl @@ -492,9 +492,22 @@ function isdir_windows_workaround(path::String) end end +# try to call realpath on as much as possible +function safe_realpath(path) + ispath(path) && return realpath(path) + a, b = splitdir(path) + return joinpath(safe_realpath(a), b) +end +function relative_project_path(ctx::Context, path::String) + # compute path relative the project + # realpath needed to expand symlinks before taking the relative path + return relpath(safe_realpath(abspath(path)), + safe_realpath(dirname(ctx.env.project_file))) +end + casesensitive_isdir(dir::String) = isdir_windows_workaround(dir) && dir in readdir(joinpath(dir, "..")) -function handle_repos_develop!(ctx::Context, pkgs::AbstractVector{PackageSpec}, devdir::String) +function handle_repos_develop!(ctx::Context, pkgs::AbstractVector{PackageSpec}; shared::Bool) Base.shred!(LibGit2.CachedCredentials()) do creds env = ctx.env new_uuids = UUID[] @@ -512,8 +525,7 @@ function handle_repos_develop!(ctx::Context, pkgs::AbstractVector{PackageSpec}, else # Relative paths are given relative pwd() so we # translate that to be relative the project instead. - # `realpath` is needed to expand symlinks before taking the relative path. - pkg.path = relpath(realpath(abspath(pkg.repo.url)), realpath(dirname(ctx.env.project_file))) + pkg.path = relative_project_path(ctx, pkg.repo.url) end folder_already_downloaded = true project_path = pkg.repo.url @@ -565,6 +577,7 @@ function handle_repos_develop!(ctx::Context, pkgs::AbstractVector{PackageSpec}, end parse_package!(ctx, pkg, project_path) + devdir = shared ? Pkg.devdir() : joinpath(dirname(ctx.env.project_file), "dev") dev_pkg_path = joinpath(devdir, pkg.name) if isdir(dev_pkg_path) if !isfile(joinpath(dev_pkg_path, "src", pkg.name * ".jl")) @@ -577,9 +590,9 @@ function handle_repos_develop!(ctx::Context, pkgs::AbstractVector{PackageSpec}, mv(project_path, dev_pkg_path; force=true) push!(new_uuids, pkg.uuid) end - # Save the path as relative if the location is inside the project - # (e.g. from `dev --local`), otherwise put in the absolute path. - pkg.path = Pkg.Operations.relative_project_path_if_in_project(ctx, dev_pkg_path) + # Save the path as relative if it is a --local dev, + # otherwise put in the absolute path. + pkg.path = shared ? dev_pkg_path : relative_project_path(ctx, dev_pkg_path) end @assert pkg.path != nothing @assert has_uuid(pkg) diff --git a/stdlib/Pkg/test/repl.jl b/stdlib/Pkg/test/repl.jl index 57ed232d002a1..bd3147ca32365 100644 --- a/stdlib/Pkg/test/repl.jl +++ b/stdlib/Pkg/test/repl.jl @@ -3,6 +3,7 @@ module REPLTests using Pkg +using Pkg.Types: manifest_info, EnvCache import Pkg.Types.PkgError using UUIDs using Test @@ -308,8 +309,39 @@ cd(mktempdir()) do @test manifest["SubModule"][1]["path"] == joinpath("..", "SubModule") end +# path should not be relative when devdir() happens to be in project +# unless user used dev --local. +temp_pkg_dir() do depot + cd(mktempdir()) do + uuid = UUID("7876af07-990d-54b4-ab0e-23690620f79a") # Example + pkg"activate ." + withenv("JULIA_PKG_DEVDIR" => joinpath(pwd(), "dev")) do + pkg"dev Example" + @test manifest_info(EnvCache(), uuid)["path"] == joinpath(pwd(), "dev", "Example") + pkg"dev --shared Example" + @test manifest_info(EnvCache(), uuid)["path"] == joinpath(pwd(), "dev", "Example") + pkg"dev --local Example" + @test manifest_info(EnvCache(), uuid)["path"] == joinpath("dev", "Example") + end + end +end + +# test relative dev paths (#490) without existing Project.toml +temp_pkg_dir() do depot + cd(mktempdir()) do + pkg"activate NonExistent" + withenv("USER" => "Test User") do + pkg"generate Foo" + end + # this dev should not error even if NonExistent/Project.toml file is non-existent + @test !isdir("NonExistent") + pkg"dev Foo" + manifest = Pkg.Types.Context().env.manifest + @test manifest["Foo"][1]["path"] == joinpath("..", "Foo") + end +end + # develop with --shared and --local -using Pkg.Types: manifest_info, EnvCache cd(mktempdir()) do uuid = UUID("7876af07-990d-54b4-ab0e-23690620f79a") # Example pkg"activate ." From 97bbabd94789f006c2b9b4bfbc8cf33127a0abbc Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Mon, 13 Aug 2018 15:43:18 +0200 Subject: [PATCH 096/166] update docs for develop (cherry picked from commit b38d3b707b781b3ac71330aff7a0b719e0b63527) (cherry picked from commit 491d72db4b3bd08a3f213cdf56e784eb9a9d4f14) (cherry picked from commit fc931e5435e9b602330e2c6465bd61e0ecf6af4b) --- stdlib/Pkg/src/Pkg.jl | 6 +++--- stdlib/Pkg/src/REPLMode.jl | 4 +--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/stdlib/Pkg/src/Pkg.jl b/stdlib/Pkg/src/Pkg.jl index 940375c94af54..818e45e9aacb4 100644 --- a/stdlib/Pkg/src/Pkg.jl +++ b/stdlib/Pkg/src/Pkg.jl @@ -219,10 +219,10 @@ If `pkg` is given as a local path, the package at that path will be tracked. Pkg.develop("Example") # By url -Pkg.develop(PackageSpec(url="https://github.com/JuliaLang/Compat.jl", rev="master")) +Pkg.develop(PackageSpec(url="https://github.com/JuliaLang/Compat.jl")) -# By path (also uses url keyword to PackageSpec) -Pkg.develop(PackageSpec(url="MyJuliaPackages/Package.jl") +# By path +Pkg.develop(PackageSpec(path="MyJuliaPackages/Package.jl") ``` See also [`PackageSpec`](@ref) diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index 632c34f75e0e0..39bb380182f83 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -1052,9 +1052,7 @@ This operation is undone by `free`. *Example* ```jl pkg> develop Example -pkg> develop Example#master -pkg> develop Example#c37b675 -pkg> develop https://github.com/JuliaLang/Example.jl#master +pkg> develop https://github.com/JuliaLang/Example.jl pkg> develop --local Example ``` """, From e818a3fd23fc71d2499892d8d218ce031d1957cc Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Tue, 10 Jul 2018 15:48:56 +0200 Subject: [PATCH 097/166] fixup testing to be more isolated from env variables (cherry picked from commit 84b7e726357d2f212599eb9cc66a37112696da72) (cherry picked from commit b0c9df9aaea2f03e4469001a6c12dd16492178a7) (cherry picked from commit 830bbcec2b1acba952b9da53b0d46d87cecd9d20) --- stdlib/Pkg/test/utils.jl | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/stdlib/Pkg/test/utils.jl b/stdlib/Pkg/test/utils.jl index f8f3a75a55b29..54f1a3982a877 100644 --- a/stdlib/Pkg/test/utils.jl +++ b/stdlib/Pkg/test/utils.jl @@ -15,11 +15,13 @@ function temp_pkg_dir(fn::Function) empty!(DEPOT_PATH) Base.HOME_PROJECT[] = nothing Base.ACTIVE_PROJECT[] = nothing - mktempdir() do env_dir - mktempdir() do depot_dir - push!(LOAD_PATH, "@", "@v#.#", "@stdlib") - push!(DEPOT_PATH, depot_dir) - fn(env_dir) + withenv("JULIA_PROJECT" => nothing, "JULIA_LOAD_PATH" => nothing) do + mktempdir() do env_dir + mktempdir() do depot_dir + push!(LOAD_PATH, "@", "@v#.#", "@stdlib") + push!(DEPOT_PATH, depot_dir) + fn(env_dir) + end end end finally From 200b8137929ecdcbc36124cf9015d27d3926d7f9 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Fri, 17 Aug 2018 19:08:04 +0200 Subject: [PATCH 098/166] better path print (cherry picked from commit f5e729d1cea4b13c5560d7b47b3b40ea819d6b82) (cherry picked from commit ab4906e771bce85accca46fa51039116997d00d5) (cherry picked from commit 06b9df99a753cc4c58dc0afb3234aeef06048516) --- stdlib/Pkg/src/API.jl | 2 +- stdlib/Pkg/src/Display.jl | 8 ++++---- stdlib/Pkg/src/Operations.jl | 2 +- stdlib/Pkg/src/Types.jl | 20 ++++---------------- 4 files changed, 10 insertions(+), 22 deletions(-) diff --git a/stdlib/Pkg/src/API.jl b/stdlib/Pkg/src/API.jl index f015d7693dc8a..ee308919facf1 100644 --- a/stdlib/Pkg/src/API.jl +++ b/stdlib/Pkg/src/API.jl @@ -96,7 +96,7 @@ function update_registry(ctx) else for reg in registries() if isdir(joinpath(reg, ".git")) - regpath = pathrepr(ctx, reg) + regpath = pathrepr(reg) printpkgstyle(ctx, :Updating, "registry at " * regpath) LibGit2.with(LibGit2.GitRepo, reg) do repo if LibGit2.isdirty(repo) diff --git a/stdlib/Pkg/src/Display.jl b/stdlib/Pkg/src/Display.jl index 415e0ba5d57c9..030d206db1069 100644 --- a/stdlib/Pkg/src/Display.jl +++ b/stdlib/Pkg/src/Display.jl @@ -56,14 +56,14 @@ function status(ctx::Context, mode::PackageMode, use_as_api=false) m₁ = filter_manifest(in_project(project₁["deps"]), manifest₁) diff = manifest_diff(ctx, m₀, m₁) if !use_as_api - printpkgstyle(ctx, :Status, pathrepr(ctx, env.project_file), #=ignore_indent=# true) + printpkgstyle(ctx, :Status, pathrepr(env.project_file), #=ignore_indent=# true) print_diff(ctx, diff, #=status=# true) end end if mode == PKGMODE_MANIFEST diff = manifest_diff(ctx, manifest₀, manifest₁) if !use_as_api - printpkgstyle(ctx, :Status, pathrepr(ctx, env.manifest_file), #=ignore_indent=# true) + printpkgstyle(ctx, :Status, pathrepr(env.manifest_file), #=ignore_indent=# true) print_diff(ctx, diff, #=status=# true) end elseif mode == PKGMODE_COMBINED @@ -73,7 +73,7 @@ function status(ctx::Context, mode::PackageMode, use_as_api=false) c_diff = filter!(x->x.old != x.new, manifest_diff(ctx, m₀, m₁)) if !isempty(c_diff) if !use_as_api - printpkgstyle(ctx, :Status, pathrepr(ctx, env.manifest_file), #=ignore_indent=# true) + printpkgstyle(ctx, :Status, pathrepr(env.manifest_file), #=ignore_indent=# true) print_diff(ctx, c_diff, #=status=# true) end diff = Base.vcat(c_diff, diff) @@ -116,7 +116,7 @@ revstring(str::String) = occursin(r"\b([a-f0-9]{40})\b", str) ? str[1:7] : str vstring(ctx::Context, a::VerInfo) = string((a.ver == nothing && a.hash != nothing) ? "[$(string(a.hash)[1:16])]" : "", a.ver != nothing ? "v$(a.ver)" : "", - a.path != nothing ? " [$(pathrepr(ctx, a.path))]" : "", + a.path != nothing ? " [$(pathrepr(a.path))]" : "", a.repo != nothing ? " #$(revstring(a.repo.rev)) ($(a.repo.url))" : "", a.pinned == true ? " ⚲" : "", ) diff --git a/stdlib/Pkg/src/Operations.jl b/stdlib/Pkg/src/Operations.jl index 1e5a6cced6bb3..610171372a0f9 100644 --- a/stdlib/Pkg/src/Operations.jl +++ b/stdlib/Pkg/src/Operations.jl @@ -1038,7 +1038,7 @@ function build_versions(ctx::Context, uuids::Vector{UUID}; might_need_to_resolve for (uuid, name, hash_or_path, build_file, version) in builds log_file = splitext(build_file)[1] * ".log" printpkgstyle(ctx, :Building, - rpad(name * " ", max_name + 1, "─") * "→ " * Types.pathrepr(ctx, log_file)) + rpad(name * " ", max_name + 1, "─") * "→ " * Types.pathrepr(log_file)) code = """ $(Base.load_path_setup_code(false)) cd($(repr(dirname(build_file)))) diff --git a/stdlib/Pkg/src/Types.jl b/stdlib/Pkg/src/Types.jl index 83403d60b1d0b..9e1e80e3dbf48 100644 --- a/stdlib/Pkg/src/Types.jl +++ b/stdlib/Pkg/src/Types.jl @@ -1113,20 +1113,8 @@ function printpkgstyle(ctx::Context, cmd::Symbol, text::String, ignore_indent::B end -function pathrepr(ctx::Union{Nothing, Context}, path::String, base::String=pwd()) - project_path = dirname(ctx.env.project_file) - path = joinpath(project_path, path) - if startswith(path, project_path) && startswith(base, project_path) - # We are in project and path is in project - path = relpath(path, base) - end - if !Sys.iswindows() && isabspath(path) - home = joinpath(homedir(), "") - if startswith(path, home) - path = joinpath("~", path[nextind(path, lastindex(home)):end]) - end - end - return "`" * path * "`" +function pathrepr(path::String) + return "`" * Base.contractuser(path) * "`" end function project_key_order(key::String) @@ -1149,7 +1137,7 @@ function write_env(ctx::Context; display_diff=true) isempty(project["deps"]) && delete!(project, "deps") if !isempty(project) || ispath(env.project_file) if display_diff && !(ctx.currently_running_target) - printpkgstyle(ctx, :Updating, pathrepr(ctx, env.project_file)) + printpkgstyle(ctx, :Updating, pathrepr(env.project_file)) Pkg.Display.print_project_diff(ctx, old_env, env) end if !ctx.preview @@ -1162,7 +1150,7 @@ function write_env(ctx::Context; display_diff=true) # update the manifest file if !isempty(env.manifest) || ispath(env.manifest_file) if display_diff && !(ctx.currently_running_target) - printpkgstyle(ctx, :Updating, pathrepr(ctx, env.manifest_file)) + printpkgstyle(ctx, :Updating, pathrepr(env.manifest_file)) Pkg.Display.print_manifest_diff(ctx, old_env, env) end manifest = deepcopy(env.manifest) From bb395493044bd8803452d19155b8279f7025fb74 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Fri, 17 Aug 2018 19:09:04 +0200 Subject: [PATCH 099/166] Print stdlib paths more compactly, fix #605. (cherry picked from commit aef9aeddaf050a6b16c3229037de353748e84698) (cherry picked from commit a1330c849022106ddd43352e096cd01d93810449) (cherry picked from commit 7b8e4685f942d6dff76ae10ad6e62ae0feb1b934) --- stdlib/Pkg/src/Types.jl | 6 +++++- stdlib/Pkg/test/pkg.jl | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/stdlib/Pkg/src/Types.jl b/stdlib/Pkg/src/Types.jl index 9e1e80e3dbf48..0b989386b0458 100644 --- a/stdlib/Pkg/src/Types.jl +++ b/stdlib/Pkg/src/Types.jl @@ -333,7 +333,7 @@ is_project_uuid(env::EnvCache, uuid::UUID) = ########### # Context # ########### -stdlib_dir() = joinpath(Sys.BINDIR, "..", "share", "julia", "stdlib", "v$(VERSION.major).$(VERSION.minor)") +stdlib_dir() = normpath(joinpath(Sys.BINDIR, "..", "share", "julia", "stdlib", "v$(VERSION.major).$(VERSION.minor)")) stdlib_path(stdlib::String) = joinpath(stdlib_dir(), stdlib) function gather_stdlib_uuids() stdlibs = Dict{UUID,String}() @@ -1114,6 +1114,10 @@ end function pathrepr(path::String) + # print stdlib paths as @stdlib/Name + if startswith(path, stdlib_dir()) + path = "@stdlib/" * basename(path) + end return "`" * Base.contractuser(path) * "`" end diff --git a/stdlib/Pkg/test/pkg.jl b/stdlib/Pkg/test/pkg.jl index 5ecc3a9c985bf..63f5834e3b8bb 100644 --- a/stdlib/Pkg/test/pkg.jl +++ b/stdlib/Pkg/test/pkg.jl @@ -495,6 +495,11 @@ end end end +@testset "printing of stdlib paths, issue #605" begin + path = Pkg.Types.stdlib_path("Test") + @test Pkg.Types.pathrepr(path) == "`@stdlib/Test`" +end + include("repl.jl") include("api.jl") From 394d05656f4bcd255c61f8d316e0a8a1457dd2e1 Mon Sep 17 00:00:00 2001 From: Patrick Kofod Mogensen Date: Mon, 20 Aug 2018 14:00:57 +0200 Subject: [PATCH 100/166] Update Pkg docs to reflect version change to v1.0 (cherry picked from commit c87cbd03c7e93741043d8d719972bcd948ea89ef) (cherry picked from commit b449507037e1046d5cd3d97d7734f7bb477af5de) (cherry picked from commit 2e718cac08593a247b0460aed6c0c008b6ec42fe) --- stdlib/Pkg/docs/src/index.md | 84 ++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/stdlib/Pkg/docs/src/index.md b/stdlib/Pkg/docs/src/index.md index 7e01e44a08584..53eada6779862 100644 --- a/stdlib/Pkg/docs/src/index.md +++ b/stdlib/Pkg/docs/src/index.md @@ -146,7 +146,7 @@ format using ranges of package versions. **Depot:** a directory on a system where various package-related resources live, including: -- `environments`: shared named environments (e.g. `v0.7`, `devtools`) +- `environments`: shared named environments (e.g. `v1.0`, `devtools`) - `clones`: bare clones of package repositories - `compiled`: cached compiled package images (`.ji` files) - `config`: global configuration files (e.g. `startup.jl`) @@ -181,11 +181,11 @@ managed by system administrators. The Pkg REPL-mode is entered from the Julia REPL using the key `]`. ``` -(v0.7) pkg> +(v1.0) pkg> ``` The part inside the parenthesis of the prompt shows the name of the current project. -Since we haven't created our own project yet, we are in the default project, located at `~/.julia/environments/v0.7` +Since we haven't created our own project yet, we are in the default project, located at `~/.julia/environments/v1.0` (or whatever version of Julia you happen to run). To return to the `julia>` prompt, either press backspace when the input line is empty or press Ctrl+C. @@ -207,15 +207,15 @@ The most frequently used one is `add` and its usage is described first. In the Pkg REPL packages can be added with the `add` command followed by the name of the package, for example: ``` -(v0.7) pkg> add Example +(v1.0) pkg> add Example Cloning default registries into /Users/kristoffer/.julia/registries Cloning registry General from "https://github.com/JuliaRegistries/General.git" Updating registry at `~/.julia/registries/General` Updating git-repo `https://github.com/JuliaRegistries/General.git` Resolving package versions... - Updating `~/.julia/environments/v0.7/Project.toml` + Updating `~/.julia/environments/v1.0/Project.toml` [7876af07] + Example v0.5.1 - Updating `~/.julia/environments/v0.7/Manifest.toml` + Updating `~/.julia/environments/v1.0/Manifest.toml` [7876af07] + Example v0.5.1 [8dfed614] + Test ``` @@ -228,7 +228,7 @@ Since standard libraries (e.g. `Test`) are shipped with Julia, they do not have you have added yourself, in this case, `Example`: ``` -(v0.7) pkg> st +(v1.0) pkg> st Status `Project.toml` [7876af07] Example v0.5.1 ``` @@ -236,7 +236,7 @@ you have added yourself, in this case, `Example`: The manifest status, in addition, includes the dependencies of explicitly added packages. ``` -(v0.7) pkg> st --manifest +(v1.0) pkg> st --manifest Status `Manifest.toml` [7876af07] Example v0.5.1 [8dfed614] Test @@ -256,11 +256,11 @@ julia> Example.hello("User") A specific version can be installed by appending a version after a `@` symbol, e.g. `@v0.4`, to the package name: ``` -(v0.7) pkg> add Example@0.4 +(v1.0) pkg> add Example@0.4 Resolving package versions... - Updating `~/.julia/environments/v0.7/Project.toml` + Updating `~/.julia/environments/v1.0/Project.toml` [7876af07] + Example v0.4.1 - Updating `~/.julia/environments/v0.7/Manifest.toml` + Updating `~/.julia/environments/v1.0/Manifest.toml` [7876af07] + Example v0.4.1 ``` @@ -268,12 +268,12 @@ If the master branch (or a certain commit SHA) of `Example` has a hotfix that ha we can explicitly track a branch (or commit) by appending `#branch` (or `#commit`) to the package name: ``` -(v0.7) pkg> add Example#master +(v1.0) pkg> add Example#master Updating git-repo `https://github.com/JuliaLang/Example.jl.git` Resolving package versions... - Updating `~/.julia/environments/v0.7/Project.toml` + Updating `~/.julia/environments/v1.0/Project.toml` [7876af07] ~ Example v0.5.1 ⇒ v0.5.1+ #master (https://github.com/JuliaLang/Example.jl.git) - Updating `~/.julia/environments/v0.7/Manifest.toml` + Updating `~/.julia/environments/v1.0/Manifest.toml` [7876af07] ~ Example v0.5.1 ⇒ v0.5.1+ #master (https://github.com/JuliaLang/Example.jl.git) ``` @@ -283,11 +283,11 @@ When updating packages, we will pull updates from that branch. To go back to tracking the registry version of `Example`, the command `free` is used: ``` -(v0.7) pkg> free Example +(v1.0) pkg> free Example Resolving package versions... - Updating `~/.julia/environments/v0.7/Project.toml` + Updating `~/.julia/environments/v1.0/Project.toml` [7876af07] ~ Example v0.5.1+ #master (https://github.com/JuliaLang/Example.jl.git) ⇒ v0.5.1 - Updating `~/.julia/environments/v0.7/Manifest.toml` + Updating `~/.julia/environments/v1.0/Manifest.toml` [7876af07] ~ Example v0.5.1+ #master )https://github.com/JuliaLang/Example.jl.git) ⇒ v0.5.1 ``` @@ -297,13 +297,13 @@ To go back to tracking the registry version of `Example`, the command `free` is If a package is not in a registry, it can still be added by instead of the package name giving the URL to the repository to `add`. ``` -(v0.7) pkg> add https://github.com/fredrikekre/ImportMacros.jl +(v1.0) pkg> add https://github.com/fredrikekre/ImportMacros.jl Updating git-repo `https://github.com/fredrikekre/ImportMacros.jl` Resolving package versions... Downloaded MacroTools ─ v0.4.1 - Updating `~/.julia/environments/v0.7/Project.toml` + Updating `~/.julia/environments/v1.0/Project.toml` [e6797606] + ImportMacros v0.0.0 # (https://github.com/fredrikekre/ImportMacros.jl) - Updating `~/.julia/environments/v0.7/Manifest.toml` + Updating `~/.julia/environments/v1.0/Manifest.toml` [e6797606] + ImportMacros v0.0.0 # (https://github.com/fredrikekre/ImportMacros.jl) [1914dd2f] + MacroTools v0.4.1 ``` @@ -330,12 +330,12 @@ However, when you are developing a package, it is more convenient to load packag Let's try to `dev` a registered package: ``` -(v0.7) pkg> dev Example +(v1.0) pkg> dev Example Updating git-repo `https://github.com/JuliaLang/Example.jl.git` Resolving package versions... - Updating `~/.julia/environments/v0.7/Project.toml` + Updating `~/.julia/environments/v1.0/Project.toml` [7876af07] + Example v0.5.1+ [`~/.julia/dev/Example`] - Updating `~/.julia/environments/v0.7/Manifest.toml` + Updating `~/.julia/environments/v1.0/Manifest.toml` [7876af07] + Example v0.5.1+ [`~/.julia/dev/Example`] ``` @@ -347,7 +347,7 @@ If we try to `dev` a package at some branch that already exists at `~/.julia/dev For example: ``` -(v0.7) pkg> dev Example +(v1.0) pkg> dev Example Updating git-repo `https://github.com/JuliaLang/Example.jl.git` [ Info: Path `/Users/kristoffer/.julia/dev/Example` exists and looks like the correct package, using existing path instead of cloning ``` @@ -361,11 +361,11 @@ The path will be recorded relative to the project file, unless it is given as an To stop tracking a path and use the registered version again, use `free` ``` -(v0.7) pkg> free Example +(v1.0) pkg> free Example Resolving package versions... - Updating `~/.julia/environments/v0.7/Project.toml` + Updating `~/.julia/environments/v1.0/Project.toml` [7876af07] ↓ Example v0.5.1+ [`~/.julia/dev/Example`] ⇒ v0.5.1 - Updating `~/.julia/environments/v0.7/Manifest.toml` + Updating `~/.julia/environments/v1.0/Manifest.toml` [7876af07] ↓ Example v0.5.1+ [`~/.julia/dev/Example`] ⇒ v0.5.1 ``` @@ -390,13 +390,13 @@ When new versions of packages the project is using are released, it is a good id to the latest compatible version. Sometimes this is not what you want. You can specify a subset of the dependencies to upgrade by giving them as arguments to `up`, e.g: ``` -(v0.7) pkg> up Example +(v1.0) pkg> up Example ``` The version of all other packages direct dependencies will stay the same. If you only want to update the minor version of packages, to reduce the risk that your project breaks, you can give the `--minor` flag, e.g: ``` -(v0.7) pkg> up --minor Example +(v1.0) pkg> up --minor Example ``` Packages that track a repository are not updated when a minor upgrade is done. @@ -407,21 +407,21 @@ Packages that track a path are never touched by the package manager. A pinned package will never be updated. A package can be pinned using `pin` as for example ``` -(v0.7) pkg> pin Example +(v1.0) pkg> pin Example Resolving package versions... - Updating `~/.julia/environments/v0.7/Project.toml` + Updating `~/.julia/environments/v1.0/Project.toml` [7876af07] ~ Example v0.5.1 ⇒ v0.5.1 ⚲ - Updating `~/.julia/environments/v0.7/Manifest.toml` + Updating `~/.julia/environments/v1.0/Manifest.toml` [7876af07] ~ Example v0.5.1 ⇒ v0.5.1 ⚲ ``` Note the pin symbol `⚲` showing that the package is pinned. Removing the pin is done using `free` ``` -(v0.7) pkg> free Example - Updating `~/.julia/environments/v0.7/Project.toml` +(v1.0) pkg> free Example + Updating `~/.julia/environments/v1.0/Project.toml` [7876af07] ~ Example v0.5.1 ⚲ ⇒ v0.5.1 - Updating `~/.julia/environments/v0.7/Manifest.toml` + Updating `~/.julia/environments/v1.0/Manifest.toml` [7876af07] ~ Example v0.5.1 ⚲ ⇒ v0.5.1 ``` @@ -430,7 +430,7 @@ Note the pin symbol `⚲` showing that the package is pinned. Removing the pin i The tests for a package can be run using `test`command: ``` -(v0.7) pkg> test Example +(v1.0) pkg> test Example Testing Example Testing Example tests passed ``` @@ -442,7 +442,7 @@ The output of the build process is directed to a file. To explicitly run the build step for a package the `build` command is used: ``` -(v0.7) pkg> build MbedTLS +(v1.0) pkg> build MbedTLS Building MbedTLS → `~/.julia/packages/MbedTLS/h1Vu/deps/build.log` shell> cat ~/.julia/packages/MbedTLS/h1Vu/deps/build.log @@ -455,7 +455,7 @@ shell> cat ~/.julia/packages/MbedTLS/h1Vu/deps/build.log ## Creating your own projects -So far we have added packages to the default project at `~/.julia/environments/v0.7`, it is, however, easy to create other, independent, projects. +So far we have added packages to the default project at `~/.julia/environments/v1.0`, it is, however, easy to create other, independent, projects. It should be pointed out if two projects uses the same package at the same version, the content of this package is not duplicated. In order to create a new project, create a directory for it and then activate that directory to make it the "active project" which package operations manipulate: @@ -465,7 +465,7 @@ shell> mkdir MyProject shell> cd MyProject /Users/kristoffer/MyProject -(v0.7) pkg> activate . +(v1.0) pkg> activate . (MyProject) pkg> st Status `Project.toml` @@ -518,7 +518,7 @@ and what packages those projects used. The rest can be deleted. This is done with the `gc` command: ``` -(v0.7) pkg> gc +(v1.0) pkg> gc Active manifests at: `/Users/kristoffer/BinaryProvider/Manifest.toml` ... @@ -542,7 +542,7 @@ This file is executed when the package is loaded. To generate files for a new package, use `pkg> generate`. ``` -(v0.7) pkg> generate HelloWorld +(v1.0) pkg> generate HelloWorld ``` This creates a new project `HelloWorld` with the following files (visualized with the external [`tree` command](https://linux.die.net/man/1/tree)): @@ -825,7 +825,7 @@ However, nothing would be installed and your `Project.toml` and `Manifest.toml` Simply clone their project using e.g. `git clone`, `cd` to the project directory and call ``` -(v0.7) pkg> activate . +(v1.0) pkg> activate . (SomeProject) pkg> instantiate ``` From 90b1bdb00653c84ab8d8aed8276c6f9e945936a9 Mon Sep 17 00:00:00 2001 From: David Varela <00.varela.david@gmail.com> Date: Wed, 8 Aug 2018 16:02:08 -0700 Subject: [PATCH 101/166] Fix `preview` Make preview a meta option Update tests for `preview` Allow `preview` meta option to use command syntax Add support for context sensitive completions Fix completion parsing tests Fix tests: `add` does not have a `manifest` option Cache data needed for completions Refactor completions Fix completions Update tests for completions parse Fix `_statement` Only complete canonical names for `help` (cherry picked from commit 7aaf3ea5526a6e9aee6689b62100b18d57ac423c) (cherry picked from commit b8c3b8525480ccda580a34738b750d5841c36201) (cherry picked from commit 18ab938c4560a9c24d096232646190fa17f14715) --- stdlib/Pkg/src/REPLMode.jl | 291 +++++++++++++++++++++++-------------- stdlib/Pkg/test/repl.jl | 67 ++++++++- 2 files changed, 246 insertions(+), 112 deletions(-) diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index 39bb380182f83..293fe4a24e70e 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -81,8 +81,9 @@ function parse_option(word::AbstractString)::Option return Option(option_name, option_arg) end -# declare meta options here -meta_option_declarations = OptionDeclaration[] +meta_option_declarations = OptionDeclaration[ + ("preview", OPT_SWITCH, :preview => true) +] meta_option_specs = OptionSpecs(meta_option_declarations) ################ @@ -108,7 +109,8 @@ const CommandDeclaration = Tuple{CommandKind, } struct CommandSpec kind::CommandKind - names::Vector{String} + canonical_name::String + short_name::Union{Nothing,String} handler::Union{Nothing,Function} argument_spec::ArgSpec # note: just use range operator for max/min option_specs::Dict{String, OptionSpec} @@ -134,7 +136,8 @@ function CommandSpecs(declarations::Vector{CommandDeclaration})::Dict{String,Com for dec in declarations names = dec[2] spec = CommandSpec(dec[1], - names, + names[1], + length(names) == 2 ? names[2] : nothing, dec[3], ArgSpec(dec[4]...), OptionSpecs(dec[5]), @@ -195,7 +198,72 @@ struct QuotedWord isquoted::Bool end -function parse(cmd::String)::Vector{Statement} +function unwrap_option(option::String) + if startswith(option, "--") + return length(option) == 2 ? "" : option[3:end] + elseif length(option) == 2 + return option[end] + end +end + +wrap_option(option::String) = + length(option) == 1 ? "-$option" : "--$option" + +function _statement(words) + is_option(word) = first(word) == '-' + + word = popfirst!(words) + # meta options + while is_option(word) + if isempty(words) + if unwrap_option(word) in keys(meta_option_specs) + return :cmd, "", nothing, true + else + return :meta, word, nothing, true + end + end + word = popfirst!(words) + end + # command + if word == "preview" + if isempty(words) + return :cmd, "", nothing, true + end + word = popfirst!(words) + end + if word in keys(super_specs) # have a super command + super_name = word + super = super_specs[word] + if isempty(words) + return :sub, "", super_name, true + end + word = popfirst!(words) + command = get(super, word, nothing) + if command === nothing + if isempty(words) + return :sub, word, super_name, true + else + return nothing + end + end + elseif get(super_specs["package"], word, nothing) !== nothing # given a "package" command + command = get(super_specs["package"], word, nothing) + elseif isempty(words) # try to complete the super command + return :cmd, word, nothing, true + else + return nothing + end + if isempty(words) + return :arg, "", command, true + end + word = words[end] + manifest = any(x->x in ["--manifest", "-m"], filter(is_option, words)) + return is_option(word) ? + (:opt, word, command, true) : + (:arg, word, command, !manifest) +end + +function parse(cmd::String; for_completions=false) # replace new lines with ; to support multiline commands cmd = replace(replace(cmd, "\r\n" => "; "), "\n" => "; ") # tokenize accoring to whitespace / quotes @@ -205,8 +273,10 @@ function parse(cmd::String)::Vector{Statement} # break up words according to ";"(doing this early makes subsequent processing easier) word_groups = group_words(words) # create statements - statements = map(Statement, word_groups) - return statements + if for_completions + return _statement(word_groups[end]) + end + return map(Statement, word_groups) end # vector of words -> structured statement @@ -223,8 +293,17 @@ function Statement(words)::Statement word = popfirst!(words) end # command + # special handling for `preview`, just convert it to a meta option under the hood + if word == "preview" + if !("--preview" in statement.meta_options) + push!(statement.meta_options, "--preview") + end + isempty(words) && pkgerror("preview requires a command") + word = popfirst!(words) + end if word in keys(super_specs) super = super_specs[word] + isempty(words) && pkgerror("no subcommand specified") word = popfirst!(words) else super = super_specs["package"] @@ -519,29 +598,34 @@ end function do_cmd!(command::PkgCommand, repl) context = APIOptions(command.meta_options, meta_option_specs) - spec = command.spec # REPL specific commands - if spec.kind == CMD_HELP + if command.spec.kind == CMD_HELP return Base.invokelatest(do_help!, command, repl) - elseif spec.kind == CMD_PREVIEW - context[:preview] = true - cmd = command.arguments[1] - cmd_spec = get(command_specs, cmd, nothing) - cmd_spec === nothing && - pkgerror("'$cmd' is not a valid command") - spec = cmd_spec - command = PkgCommand([], cmd, [], PackageSpec[]) end # API commands # TODO is invokelatest still needed? api_opts = APIOptions(command) - if applicable(spec.handler, context, command.arguments, api_opts) - Base.invokelatest(spec.handler, context, command.arguments, api_opts) + if applicable(command.spec.handler, context, command.arguments, api_opts) + Base.invokelatest(command.spec.handler, context, command.arguments, api_opts) else - Base.invokelatest(spec.handler, command.arguments, api_opts) + Base.invokelatest(command.spec.handler, command.arguments, api_opts) + end +end + +function CommandSpec(command_name::String)::Union{Nothing,CommandSpec} + # maybe a "package" command + spec = get(super_specs["package"], command_name, nothing) + if spec !== nothing + return spec end + # maybe a "compound command" + m = match(r"(\w+)-(\w+)", command_name) + m !== nothing || (return nothing) + super = get(super_specs, m.captures[1], nothing) + super !== nothing || (return nothing) + return get(super, m.captures[2], nothing) end function do_help!(command::PkgCommand, repl::REPL.AbstractREPL) @@ -552,9 +636,10 @@ function do_help!(command::PkgCommand, repl::REPL.AbstractREPL) end help_md = md"" for arg in command.arguments - spec = get(command_specs, arg, nothing) - spec === nothing && + spec = CommandSpec(arg) + if spec === nothing pkgerror("'$arg' does not name a command") + end spec.help === nothing && pkgerror("Sorry, I don't have any help for the `$arg` command.") isempty(help_md.content) || @@ -665,10 +750,16 @@ end pkgstr(str::String) = do_cmd(minirepl[], str; do_rethrow=true) # handle completions -all_commands_sorted = [] -long_commands = [] -all_options_sorted = [] -long_options = [] +mutable struct CompletionCache + commands::Vector{String} + canonical_names::Vector{String} + meta_options::Vector{String} + options::Dict{CommandKind, Vector{String}} + subcommands::Dict{String, Vector{String}} + CompletionCache() = new([],[],[],Dict(),Dict()) +end + +completion_cache = CompletionCache() struct PkgCompletionProvider <: LineEdit.CompletionProvider end @@ -679,35 +770,6 @@ function LineEdit.complete_line(c::PkgCompletionProvider, s) return ret, partial[range], should_complete end -function complete_command(s, i1, i2) - # only show short form commands when no input is given at all - cmp = filter(cmd -> startswith(cmd, s), isempty(s) ? all_commands_sorted : long_commands) - return cmp, i1:i2, !isempty(cmp) -end - -function complete_option(s, i1, i2) - # only show short form options if only a dash is given - cmp = filter(cmd -> startswith(cmd, s), length(s) == 1 && first(s) == '-' ? - all_options_sorted : - long_options) - return cmp, i1:i2, !isempty(cmp) -end - -function complete_package(s, i1, i2, lastcommand, project_opt) - if lastcommand in [CMD_STATUS, CMD_RM, CMD_UP, CMD_TEST, CMD_BUILD, CMD_FREE, CMD_PIN] - return complete_installed_package(s, i1, i2, project_opt) - elseif lastcommand in [CMD_ADD, CMD_DEVELOP] - if occursin(Base.Filesystem.path_separator_re, s) - return complete_local_path(s, i1, i2) - else - rps = complete_remote_package(s, i1, i2) - lps = complete_local_path(s, i1, i2) - return vcat(rps[1], lps[1]), isempty(rps[1]) ? lps[2] : i1:i2, length(rps[1]) + length(lps[1]) > 0 - end - end - return String[], 0:-1, false -end - function complete_local_path(s, i1, i2) cmp = REPL.REPLCompletions.complete_path(s, i2) [REPL.REPLCompletions.completion_text(p) for p in cmp[1]], cmp[2], !isempty(cmp[1]) @@ -747,46 +809,51 @@ function complete_remote_package(s, i1, i2) return cmp, i1:i2, !isempty(cmp) end -function completions(full, index) - pre = full[1:index] - - pre_words = split(pre, ' ', keepempty=true) - - # first word should always be a command - if isempty(pre_words) - return complete_command("", 1:1) - else - to_complete = pre_words[end] - offset = isempty(to_complete) ? index+1 : to_complete.offset+1 - - if length(pre_words) == 1 - return complete_command(to_complete, offset, index) - end - - # tokenize input, don't offer any completions for invalid commands - statement = try - parse(join(pre_words[1:end-1], ' '))[end] - catch - return String[], 0:-1, false - end - - lastcommand = statement.command.kind - project_opt = true - for opt in statement.options - if opt in ["--manifest", "--project", "-m", "-p"] - project_opt = opt in ["--project", "-p"] - break - end - end - - if lastcommand in [CMD_HELP, CMD_PREVIEW] - return complete_command(to_complete, offset, index) - elseif !isempty(to_complete) && first(to_complete) == '-' - return complete_option(to_complete, offset, index) +function complete_argument(to_complete, i1, i2, lastcommand, project_opt + )::Tuple{Vector{String},UnitRange{Int},Bool} + if lastcommand == CMD_HELP + completions = filter(x->startswith(x,to_complete), completion_cache.canonical_names) + return completions, i1:i2, !isempty(completions) + elseif lastcommand in [CMD_STATUS, CMD_RM, CMD_UP, CMD_TEST, CMD_BUILD, CMD_FREE, CMD_PIN] + return complete_installed_package(to_complete, i1, i2, project_opt) + elseif lastcommand in [CMD_ADD, CMD_DEVELOP] + if occursin(Base.Filesystem.path_separator_re, to_complete) + return complete_local_path(to_complete, i1, i2) else - return complete_package(to_complete, offset, index, lastcommand, project_opt) + rps = complete_remote_package(to_complete, i1, i2) + lps = complete_local_path(to_complete, i1, i2) + return vcat(rps[1], lps[1]), isempty(rps[1]) ? lps[2] : i1:i2, length(rps[1]) + length(lps[1]) > 0 end end + return String[], 0:-1, false +end + +function completions(full, index)::Tuple{Vector{String},UnitRange{Int},Bool} + pre = full[1:index] + if isempty(pre) + return completion_cache.commands, 0:-1, false + end + x = parse(pre; for_completions=true) + if x === nothing # failed parse (invalid command name) + return String[], 0:-1, false + end + (key::Symbol, to_complete::String, spec, proj::Bool) = x + last = split(pre, ' ', keepempty=true)[end] + offset = isempty(last) ? index+1 : last.offset+1 + if last != to_complete # require a space before completing next field + return String[], 0:-1, false + end + if key == :arg + return complete_argument(to_complete, offset, index, spec.kind, proj) + end + possible::Vector{String} = + key == :meta ? completion_cache.meta_options : + key == :cmd ? completion_cache.commands : + key == :sub ? completion_cache.subcommands[spec] : + key == :opt ? completion_cache.options[spec.kind] : + String[] + completions = filter(x->startswith(x,to_complete), possible) + return completions, offset:index, !isempty(completions) end prev_project_file = nothing @@ -1200,7 +1267,9 @@ includes the dependencies of explicitly added packages. Deletes packages that cannot be reached from any existing environment. """, -),( CMD_PREVIEW, +),( # preview is not a regular command. + # this is here so that preview appears as a registered command to users + CMD_PREVIEW, ["preview"], nothing, (ARG_RAW, [1]), @@ -1218,22 +1287,32 @@ is modified. ] #command_declarations super_specs = SuperSpecs(command_declarations) -command_specs = super_specs["package"] -all_commands_sorted = sort(collect(String,keys(command_specs))) -long_commands = filter(c -> length(c) > 2, all_commands_sorted) -function all_options() - all_opts = [] - for command in values(command_specs) - for opt_spec in values(command.option_specs) - push!(all_opts, opt_spec.name) - opt_spec.short_name !== nothing && push!(all_opts, opt_spec.short_name) +# cache things you need for completions +completion_cache.meta_options = sort(map(wrap_option, collect(keys(meta_option_specs)))) +completion_cache.commands = sort(append!(collect(keys(super_specs)), + collect(keys(super_specs["package"])))) +let names = String[] + for (super, specs) in pairs(super_specs) + super == "package" && continue # skip "package" + for spec in unique(values(specs)) + push!(names, join([super, spec.canonical_name], "-")) end end - unique!(all_opts) - return all_opts + for spec in unique(values(super_specs["package"])) + push!(names, spec.canonical_name) + end + completion_cache.canonical_names = names + sort!(completion_cache.canonical_names) end -all_options_sorted = [length(opt) > 1 ? "--$opt" : "-$opt" for opt in sort!(all_options())] -long_options = filter(c -> length(c) > 2, all_options_sorted) +for (k, v) in pairs(super_specs) + completion_cache.subcommands[k] = sort(collect(keys(v))) + for spec in values(v) + completion_cache.options[spec.kind] = + sort(map(wrap_option, collect(keys(spec.option_specs)))) + end +end +# TODO remove this +command_specs = super_specs["package"] const help = md""" diff --git a/stdlib/Pkg/test/repl.jl b/stdlib/Pkg/test/repl.jl index bd3147ca32365..aa4d36ae880e9 100644 --- a/stdlib/Pkg/test/repl.jl +++ b/stdlib/Pkg/test/repl.jl @@ -66,15 +66,15 @@ end @test length(statement.arguments) == 1 @test statement.arguments[1] == "dev" statement = Pkg.REPLMode.parse("add git@github.com:JuliaLang/Example.jl.git")[1] - @test "add" in statement.command.names + @test "add" == statement.command.canonical_name @test statement.arguments[1] == "git@github.com:JuliaLang/Example.jl.git" statement = Pkg.REPLMode.parse("add git@github.com:JuliaLang/Example.jl.git#master")[1] - @test "add" in statement.command.names + @test "add" == statement.command.canonical_name @test length(statement.arguments) == 2 @test statement.arguments[1] == "git@github.com:JuliaLang/Example.jl.git" @test statement.arguments[2] == "#master" statement = Pkg.REPLMode.parse("add git@github.com:JuliaLang/Example.jl.git#c37b675")[1] - @test "add" in statement.command.names + @test "add" == statement.command.canonical_name @test length(statement.arguments) == 2 @test statement.arguments[1] == "git@github.com:JuliaLang/Example.jl.git" @test statement.arguments[2] == "#c37b675" @@ -82,7 +82,7 @@ end @test statement.arguments[1] == "git@github.com:JuliaLang/Example.jl.git" @test statement.arguments[2] == "@v0.5.0" statement = Pkg.REPLMode.parse("add git@gitlab-fsl.jsc.näsan.guvv:drats/URGA2010.jl.git@0.5.0")[1] - @test "add" in statement.command.names + @test "add" == statement.command.canonical_name @test length(statement.arguments) == 2 @test statement.arguments[1] == "git@gitlab-fsl.jsc.näsan.guvv:drats/URGA2010.jl.git" @test statement.arguments[2] == "@0.5.0" @@ -353,6 +353,40 @@ cd(mktempdir()) do @test manifest_info(EnvCache(), uuid)["path"] == joinpath("dev", "Example") end +@testset "parse completions" begin + # meta options + @test Pkg.REPLMode.parse("--pre"; for_completions=true) == (:meta, "--pre", nothing, true) + @test Pkg.REPLMode.parse("--meta --pre"; for_completions=true) == (:meta, "--pre", nothing, true) + @test Pkg.REPLMode.parse("--meta -"; for_completions=true) == (:meta, "-", nothing, true) + @test Pkg.REPLMode.parse("--meta --"; for_completions=true) == (:meta, "--", nothing, true) + # commands + @test Pkg.REPLMode.parse("--preview"; for_completions=true) == (:cmd, "", nothing, true) + @test Pkg.REPLMode.parse("--preview ad"; for_completions=true) == (:cmd, "ad", nothing, true) + @test Pkg.REPLMode.parse("--meta --preview r"; for_completions=true) == (:cmd, "r", nothing, true) + @test Pkg.REPLMode.parse("--preview reg"; for_completions=true) == (:cmd, "reg", nothing, true) + # sub commands + @test Pkg.REPLMode.parse("--preview registry"; for_completions=true) == + (:sub, "", "registry", true) + @test Pkg.REPLMode.parse("--preview registry a"; for_completions=true) == + (:sub, "a", "registry", true) + # options + @test Pkg.REPLMode.parse("add -"; for_completions=true) == + (:opt, "-", Pkg.REPLMode.super_specs["package"]["add"], true) + @test Pkg.REPLMode.parse("up --m"; for_completions=true) == + (:opt, "--m", Pkg.REPLMode.super_specs["package"]["up"], true) + @test Pkg.REPLMode.parse("up --major --pro"; for_completions=true) == + (:opt, "--pro", Pkg.REPLMode.super_specs["package"]["up"], true) + @test Pkg.REPLMode.parse("foo --maj"; for_completions=true) === + nothing + # arguments + @test Pkg.REPLMode.parse("up --major Ex"; for_completions=true) == + (:arg, "Ex", Pkg.REPLMode.super_specs["package"]["up"], true) + @test Pkg.REPLMode.parse("--preview up --major foo Ex"; for_completions=true) == + (:arg, "Ex", Pkg.REPLMode.super_specs["package"]["up"], true) + @test Pkg.REPLMode.parse("remove --manifest Ex"; for_completions=true) == + (:arg, "Ex", Pkg.REPLMode.super_specs["package"]["remove"], false) +end + test_complete(s) = Pkg.REPLMode.completions(s,lastindex(s)) apply_completion(str) = begin c, r, s = test_complete(str) @@ -403,7 +437,7 @@ temp_pkg_dir() do project_path; cd(project_path) do pkg"add Example" c, r = test_complete("rm Exam") @test "Example" in c - c, r = test_complete("add --man") + c, r = test_complete("up --man") @test "--manifest" in c c, r = test_complete("rem") @test "remove" in c @@ -428,7 +462,7 @@ temp_pkg_dir() do project_path; cd(project_path) do @test apply_completion("add ./tes") == (Sys.iswindows() ? "add ./testdir\\\\" : "add ./testdir/") c, r = test_complete("dev ./") @test (Sys.iswindows() ? ("testdir\\\\" in c) : ("testdir/" in c)) - end + end # testset end end temp_pkg_dir() do project_path; cd(project_path) do @@ -884,6 +918,27 @@ end end end end end +@testset "preview" begin + temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; + pkg"add Example" + pkg"preview rm Example" + @test isinstalled(TEST_PKG) + pkg"rm Example" + pkg"preview add Example" + @test !isinstalled(TEST_PKG) + # as a meta option + pkg"add Example" + pkg"--preview rm Example" + @test isinstalled(TEST_PKG) + pkg"rm Example" + pkg"--preview add Example" + @test !isinstalled(TEST_PKG) + # both + pkg"--preview preview add Example" + @test !isinstalled(TEST_PKG) + end end end +end + @testset "`parse_quotes` unit tests" begin qwords = Pkg.REPLMode.parse_quotes("\"Don't\" forget to '\"test\"'") @test qwords[1].isquoted From 7f4ed908ac97e07c326a55a1f8ba9787d046372f Mon Sep 17 00:00:00 2001 From: David Varela <00.varela.david@gmail.com> Date: Tue, 7 Aug 2018 16:22:23 -0700 Subject: [PATCH 102/166] Declare an argument parser for each command (cherry picked from commit ccb45335230baa919650f3704381572cd073186d) (cherry picked from commit f42f77d17836b6bd4ea075bbb69bee7d1f06c004) (cherry picked from commit 8b70a4f56518e56d7ba98ea0923e8679c0f739a2) --- stdlib/Pkg/src/REPLMode.jl | 162 +++++++++++++++++-------------------- 1 file changed, 76 insertions(+), 86 deletions(-) diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index 293fe4a24e70e..ef6186aca4833 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -97,13 +97,17 @@ meta_option_specs = OptionSpecs(meta_option_declarations) ) @enum(ArgClass, ARG_RAW, ARG_PKG, ARG_VERSION, ARG_REV, ARG_ALL) struct ArgSpec - class::ArgClass - count::Vector{Int} + count::Vector{Int} # note: just use range operator for max/min + parser::Function + parser_keys::Vector{Pair{Symbol, Any}} end const CommandDeclaration = Tuple{CommandKind, Vector{String}, # names Union{Nothing,Function}, # handler - Tuple{ArgClass, Vector{Int}}, # argument count + Tuple{Vector{Int}, # count + Function, # parser + Vector{Pair{Symbol, Any}}, # parser keys + }, # arguments Vector{OptionDeclaration}, # options Union{Nothing, Markdown.MD}, #help } @@ -112,7 +116,7 @@ struct CommandSpec canonical_name::String short_name::Union{Nothing,String} handler::Union{Nothing,Function} - argument_spec::ArgSpec # note: just use range operator for max/min + argument_spec::ArgSpec option_specs::Dict{String, OptionSpec} help::Union{Nothing, Markdown.MD} end @@ -393,6 +397,8 @@ end # PkgCommand # ############## const Token = Union{String, VersionRange, Rev} +const ArgToken = Union{VersionRange, Rev} +const PkgToken = Union{String, VersionRange, Rev} const PkgArguments = Union{Vector{String}, Vector{PackageSpec}} struct PkgCommand meta_options::Vector{Option} @@ -422,22 +428,36 @@ function APIOptions(options::Vector{Option}, return Dict(keyword_vec) end -function enforce_argument_order(args::Vector{Token}) - prev_arg = nothing - function check_prev_arg(valid_type::DataType, error_message::AbstractString) - prev_arg isa valid_type || pkgerror(error_message) - end +# TODO vector of what? +function enforce_argument_count(count::Vector{Int}, args::PkgArguments) + isempty(count) && return + length(args) in count || + pkgerror("Wrong number of arguments") +end +# Only for PkgSpec +function package_args(args::Vector{Token}; add_or_dev=false)::Vector{PackageSpec} + pkgs = PackageSpec[] for arg in args - if arg isa VersionRange - check_prev_arg(String, "package name/uuid must precede version spec `@$arg`") + if arg isa String + push!(pkgs, parse_package(arg; add_or_develop=add_or_dev)) + elseif arg isa VersionRange + pkgs[end].version = VersionSpec(arg) elseif arg isa Rev - check_prev_arg(String, "package name/uuid must precede rev spec `#$(arg.rev)`") + pkg = pkgs[end] + if pkg.repo == nothing + pkg.repo = Types.GitRepo("", arg.rev) + else + pkgs[end].repo.rev = arg.rev + end + else + assert(false) end - prev_arg = arg end + return pkgs end +# Only for PkgSpec function word2token(word::AbstractString)::Token if first(word) == '@' return VersionRange(word[2:end]) @@ -448,68 +468,39 @@ function word2token(word::AbstractString)::Token end end -function enforce_arg_spec(raw_args::Vector{String}, class::ArgClass) - # TODO is there a more idiomatic way to do this? - function has_types(arguments::Vector{Token}, types::Vector{DataType}) - return !isempty(filter(x->typeof(x) in types, arguments)) - end - - class == ARG_RAW && return raw_args - args::Vector{Token} = map(word2token, raw_args) - class == ARG_ALL && return args - - if class == ARG_PKG && has_types(args, [VersionRange, Rev]) - pkgerror("no versioned packages allowed") - elseif class == ARG_REV && has_types(args, [VersionRange]) - pkgerror("no versioned packages allowed") - elseif class == ARG_VERSION && has_types(args, [Rev]) - pkgerror("no reved packages allowed") +# Only for PkgSpec +function enforce_argument_order(args::Vector{Token}) + prev_arg = nothing + function check_prev_arg(valid_type::DataType, error_message::AbstractString) + prev_arg isa valid_type || pkgerror(error_message) end - return args -end -function package_args(args::Vector{Token}, spec::CommandSpec)::Vector{PackageSpec} - pkgs = PackageSpec[] for arg in args - if arg isa String - is_add_or_develop = spec.kind in (CMD_ADD, CMD_DEVELOP) - push!(pkgs, parse_package(arg; add_or_develop=is_add_or_develop)) - elseif arg isa VersionRange - pkgs[end].version = VersionSpec(arg) + if arg isa VersionRange + check_prev_arg(String, "package name/uuid must precede version spec `@$arg`") elseif arg isa Rev - if spec.kind == CMD_DEVELOP - pkgerror("a git revision cannot be given to `develop`") - end - pkg = pkgs[end] - if pkg.repo == nothing - pkg.repo = Types.GitRepo("", arg.rev) - else - pkgs[end].repo.rev = arg.rev - end - else - assert(false) + check_prev_arg(String, "package name/uuid must precede rev spec `#$(arg.rev)`") end + prev_arg = arg end - return pkgs end -function enforce_arg_count(count::Vector{Int}, args::PkgArguments) - isempty(count) && return - length(args) in count || - pkgerror("Wrong number of arguments") -end - -function enforce_args(raw_args::Vector{String}, spec::ArgSpec, cmd_spec::CommandSpec)::PkgArguments - if spec.class == ARG_RAW - enforce_arg_count(spec.count, raw_args) - return raw_args +function parse_pkg(raw_args::Vector{String}; valid=[], add_or_dev=false) + args::Vector{PkgToken} = map(word2token, raw_args) + enforce_argument_order(args) + # enforce spec + push!(valid, String) # always want at least PkgSpec identifiers + if !all(x->typeof(x) in valid, args) + pkgerror("invalid token") end + # convert to final arguments + return package_args(args; add_or_dev=add_or_dev) +end - args = enforce_arg_spec(raw_args, spec.class) - enforce_argument_order(args) - pkgs = package_args(args, cmd_spec) - enforce_arg_count(spec.count, pkgs) - return pkgs +function enforce_argument(raw_args::Vector{String}, spec::ArgSpec)::PkgArguments + args = spec.parser(raw_args; spec.parser_keys...) + enforce_argument_count(spec.count, args) + return args end function enforce_option(option::String, specs::Dict{String,OptionSpec})::Option @@ -565,9 +556,8 @@ end function PkgCommand(statement::Statement)::PkgCommand meta_opts = enforce_meta_options(statement.meta_options, meta_option_specs) - args = enforce_args(statement.arguments, - statement.command.argument_spec, - statement.command) + args = enforce_argument(statement.arguments, + statement.command.argument_spec) opts = enforce_opts(statement.options, statement.command.option_specs) return PkgCommand(meta_opts, statement.command, opts, args) end @@ -982,7 +972,7 @@ command_declarations = [ CMD_REGISTRY_ADD, ["add"], do_registry_add!, - (ARG_PKG, []), + ([], identity, []), [], nothing, ), @@ -992,7 +982,7 @@ command_declarations = [ ( CMD_TEST, ["test"], do_test!, - (ARG_PKG, []), + ([], parse_pkg, []), [ ("coverage", OPT_SWITCH, :coverage => true), ], @@ -1010,7 +1000,7 @@ julia is started with `--startup-file=yes`. ),( CMD_HELP, ["help", "?"], nothing, - (ARG_RAW, []), + ([], identity, []), [], md""" @@ -1027,7 +1017,7 @@ Available commands: `help`, `status`, `add`, `rm`, `up`, `preview`, `gc`, `test` ),( CMD_INSTANTIATE, ["instantiate"], do_instantiate!, - (ARG_RAW, [0]), + ([0], identity, []), [ (["project", "p"], OPT_SWITCH, :manifest => false), (["manifest", "m"], OPT_SWITCH, :manifest => true), @@ -1043,7 +1033,7 @@ If no manifest exists or the `--project` option is given, resolve and download t ),( CMD_RM, ["remove", "rm"], do_rm!, - (ARG_PKG, []), + ([], parse_pkg, []), [ (["project", "p"], OPT_SWITCH, :mode => PKGMODE_PROJECT), (["manifest", "m"], OPT_SWITCH, :mode => PKGMODE_MANIFEST), @@ -1071,7 +1061,7 @@ as any no-longer-necessary manifest packages due to project package removals. ),( CMD_ADD, ["add"], do_add!, - (ARG_ALL, []), + ([], parse_pkg, [:add_or_dev => true, :valid => [VersionRange, Rev]]), [], md""" @@ -1101,7 +1091,7 @@ pkg> add Example=7876af07-990d-54b4-ab0e-23690620f79a ),( CMD_DEVELOP, ["develop", "dev"], do_develop!, - (ARG_ALL, []), + ([], parse_pkg, [:add_or_dev => true, :valid => [VersionRange]]), [ ("local", OPT_SWITCH, :shared => false), ("shared", OPT_SWITCH, :shared => true), @@ -1126,7 +1116,7 @@ pkg> develop --local Example ),( CMD_FREE, ["free"], do_free!, - (ARG_PKG, []), + ([], parse_pkg, []), [], md""" free pkg[=uuid] ... @@ -1137,7 +1127,7 @@ makes the package no longer being checked out. ),( CMD_PIN, ["pin"], do_pin!, - (ARG_VERSION, []), + ([], parse_pkg, [:valid => [VersionRange]]), [], md""" @@ -1149,7 +1139,7 @@ A pinned package has the symbol `⚲` next to its version in the status list. ),( CMD_BUILD, ["build"], do_build!, - (ARG_PKG, []), + ([], parse_pkg, []), [], md""" @@ -1162,7 +1152,7 @@ The `startup.jl` file is disabled during building unless julia is started with ` ),( CMD_RESOLVE, ["resolve"], do_resolve!, - (ARG_RAW, [0]), + ([0], identity, []), [], md""" resolve @@ -1173,7 +1163,7 @@ packages have changed causing the current Manifest to_indices be out of sync. ),( CMD_ACTIVATE, ["activate"], do_activate!, - (ARG_RAW, [0,1]), + ([0,1], identity, []), [ ("shared", OPT_SWITCH, :shared => true), ], @@ -1190,7 +1180,7 @@ it will be placed in the first depot of the stack. ),( CMD_UP, ["update", "up"], do_up!, - (ARG_VERSION, []), + ([], parse_pkg, [:valid => [VersionRange]]), [ (["project", "p"], OPT_SWITCH, :mode => PKGMODE_PROJECT), (["manifest", "m"], OPT_SWITCH, :mode => PKGMODE_MANIFEST), @@ -1218,7 +1208,7 @@ packages will not be upgraded at all. ),( CMD_GENERATE, ["generate"], do_generate!, - (ARG_RAW, [1]), + ([1], identity, []), [], md""" @@ -1229,7 +1219,7 @@ Create a project called `pkgname` in the current folder. ),( CMD_PRECOMPILE, ["precompile"], do_precompile!, - (ARG_RAW, [0]), + ([0], identity, []), [], md""" precompile @@ -1240,7 +1230,7 @@ The `startup.jl` file is disabled during precompilation unless julia is started ),( CMD_STATUS, ["status", "st"], do_status!, - (ARG_RAW, [0]), + ([0], identity, []), [ (["project", "p"], OPT_SWITCH, :mode => PKGMODE_PROJECT), (["manifest", "m"], OPT_SWITCH, :mode => PKGMODE_MANIFEST), @@ -1261,7 +1251,7 @@ includes the dependencies of explicitly added packages. ),( CMD_GC, ["gc"], do_gc!, - (ARG_RAW, [0]), + ([0], identity, []), [], md""" @@ -1272,7 +1262,7 @@ Deletes packages that cannot be reached from any existing environment. CMD_PREVIEW, ["preview"], nothing, - (ARG_RAW, [1]), + ([1], identity, []), [], md""" From bcae2f2c15aff1b47b05e8f636fb846c07de1895 Mon Sep 17 00:00:00 2001 From: David Varela <00.varela.david@gmail.com> Date: Fri, 17 Aug 2018 22:32:06 -0700 Subject: [PATCH 103/166] Add a `description` field to `CommandSpec` Fix help doc. Disable `registry` (cherry picked from commit 9d1ef197621e20b5f9e97b1c92929a73b2e467c7) (cherry picked from commit 73296794fe728bef015b8c57220b5e3aa30eba3b) (cherry picked from commit 3b19b42ff4486f9f7f20cdbabaf36267195b1e08) --- stdlib/Pkg/src/REPLMode.jl | 65 ++++++++++++++++---------------------- stdlib/Pkg/test/repl.jl | 8 ++--- 2 files changed, 32 insertions(+), 41 deletions(-) diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index ef6186aca4833..0e3b1c35a3f7a 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -109,6 +109,7 @@ const CommandDeclaration = Tuple{CommandKind, Vector{Pair{Symbol, Any}}, # parser keys }, # arguments Vector{OptionDeclaration}, # options + String, #description Union{Nothing, Markdown.MD}, #help } struct CommandSpec @@ -118,6 +119,7 @@ struct CommandSpec handler::Union{Nothing,Function} argument_spec::ArgSpec option_specs::Dict{String, OptionSpec} + description::String help::Union{Nothing, Markdown.MD} end command_specs = Dict{String,CommandSpec}() # TODO remove this ? @@ -145,6 +147,7 @@ function CommandSpecs(declarations::Vector{CommandDeclaration})::Dict{String,Com dec[3], ArgSpec(dec[4]...), OptionSpecs(dec[5]), + dec[6], dec[end]) for name in names # TODO regex check name @@ -967,6 +970,7 @@ end # SPEC # ######## command_declarations = [ +#= ["registry"] => CommandDeclaration[ ( CMD_REGISTRY_ADD, @@ -974,9 +978,11 @@ command_declarations = [ do_registry_add!, ([], identity, []), [], + "Currently just a placeholder for a future command", nothing, ), ], #registry +=# ["package"] => CommandDeclaration[ ( CMD_TEST, @@ -986,6 +992,7 @@ command_declarations = [ [ ("coverage", OPT_SWITCH, :coverage => true), ], + "run tests for packages", md""" test [opts] pkg[=uuid] ... @@ -1002,6 +1009,7 @@ julia is started with `--startup-file=yes`. nothing, ([], identity, []), [], + "show this message", md""" help @@ -1022,6 +1030,7 @@ Available commands: `help`, `status`, `add`, `rm`, `up`, `preview`, `gc`, `test` (["project", "p"], OPT_SWITCH, :manifest => false), (["manifest", "m"], OPT_SWITCH, :manifest => true), ], + "downloads all the dependencies for the project", md""" instantiate instantiate [-m|--manifest] @@ -1038,6 +1047,7 @@ If no manifest exists or the `--project` option is given, resolve and download t (["project", "p"], OPT_SWITCH, :mode => PKGMODE_PROJECT), (["manifest", "m"], OPT_SWITCH, :mode => PKGMODE_MANIFEST), ], + "remove packages from project or manifest", md""" rm [-p|--project] pkg[=uuid] ... @@ -1063,6 +1073,7 @@ as any no-longer-necessary manifest packages due to project package removals. do_add!, ([], parse_pkg, [:add_or_dev => true, :valid => [VersionRange, Rev]]), [], + "add packages to project", md""" add pkg[=uuid] [@version] [#rev] ... @@ -1096,6 +1107,7 @@ pkg> add Example=7876af07-990d-54b4-ab0e-23690620f79a ("local", OPT_SWITCH, :shared => false), ("shared", OPT_SWITCH, :shared => true), ], + "clone the full package repo locally for development", md""" develop [--shared|--local] pkg[=uuid] ... @@ -1118,6 +1130,7 @@ pkg> develop --local Example do_free!, ([], parse_pkg, []), [], + "undoes a `pin`, `develop`, or stops tracking a repo", md""" free pkg[=uuid] ... @@ -1129,6 +1142,7 @@ makes the package no longer being checked out. do_pin!, ([], parse_pkg, [:valid => [VersionRange]]), [], + "pins the version of packages", md""" pin pkg[=uuid] ... @@ -1141,6 +1155,7 @@ A pinned package has the symbol `⚲` next to its version in the status list. do_build!, ([], parse_pkg, []), [], + "run the build script for packages", md""" build pkg[=uuid] ... @@ -1154,6 +1169,7 @@ The `startup.jl` file is disabled during building unless julia is started with ` do_resolve!, ([0], identity, []), [], + "resolves to update the manifest from changes in dependencies of developed packages", md""" resolve @@ -1167,6 +1183,7 @@ packages have changed causing the current Manifest to_indices be out of sync. [ ("shared", OPT_SWITCH, :shared => true), ], + "set the primary environment the package manager manipulates", md""" activate activate [--shared] path @@ -1189,6 +1206,7 @@ it will be placed in the first depot of the stack. ("patch", OPT_SWITCH, :level => UPLEVEL_PATCH), ("fixed", OPT_SWITCH, :level => UPLEVEL_FIXED), ], + "update packages in manifest", md""" up [-p|project] [opts] pkg[=uuid] [@version] ... @@ -1210,6 +1228,7 @@ packages will not be upgraded at all. do_generate!, ([1], identity, []), [], + "generate files for a new project", md""" generate pkgname @@ -1221,6 +1240,7 @@ Create a project called `pkgname` in the current folder. do_precompile!, ([0], identity, []), [], + "precompile all the project dependencies", md""" precompile @@ -1235,6 +1255,7 @@ The `startup.jl` file is disabled during precompilation unless julia is started (["project", "p"], OPT_SWITCH, :mode => PKGMODE_PROJECT), (["manifest", "m"], OPT_SWITCH, :mode => PKGMODE_MANIFEST), ], + "summarize contents of and changes to environment", md""" status @@ -1253,6 +1274,7 @@ includes the dependencies of explicitly added packages. do_gc!, ([0], identity, []), [], + "garbage collect packages not used for a significant time", md""" Deletes packages that cannot be reached from any existing environment. @@ -1264,6 +1286,7 @@ Deletes packages that cannot be reached from any existing environment. nothing, ([1], identity, []), [], + "previews a subsequent command without affecting the current state", md""" preview cmd @@ -1317,43 +1340,11 @@ backspace when the input line is empty or press Ctrl+C. Multiple commands can be given on the same line by interleaving a `;` between the commands. **Commands** - -What action you want the package manager to take: - -`help`: show this message - -`status`: summarize contents of and changes to environment - -`add`: add packages to project - -`develop`: clone the full package repo locally for development - -`rm`: remove packages from project or manifest - -`up`: update packages in manifest - -`test`: run tests for packages - -`build`: run the build script for packages - -`pin`: pins the version of packages - -`free`: undoes a `pin`, `develop`, or stops tracking a repo. - -`instantiate`: downloads all the dependencies for the project - -`resolve`: resolves to update the manifest from changes in dependencies of -developed packages - -`generate`: generate files for a new project - -`preview`: previews a subsequent command without affecting the current state - -`precompile`: precompile all the project dependencies - -`gc`: garbage collect packages not used for a significant time - -`activate`: set the primary environment the package manager manipulates """ +for command in completion_cache.canonical_names + spec = CommandSpec(command) + push!(help.content, Markdown.parse("`$command`: $(spec.description)")) +end + end #module diff --git a/stdlib/Pkg/test/repl.jl b/stdlib/Pkg/test/repl.jl index aa4d36ae880e9..3b7cf7e5fa74f 100644 --- a/stdlib/Pkg/test/repl.jl +++ b/stdlib/Pkg/test/repl.jl @@ -365,10 +365,10 @@ end @test Pkg.REPLMode.parse("--meta --preview r"; for_completions=true) == (:cmd, "r", nothing, true) @test Pkg.REPLMode.parse("--preview reg"; for_completions=true) == (:cmd, "reg", nothing, true) # sub commands - @test Pkg.REPLMode.parse("--preview registry"; for_completions=true) == - (:sub, "", "registry", true) - @test Pkg.REPLMode.parse("--preview registry a"; for_completions=true) == - (:sub, "a", "registry", true) + @test Pkg.REPLMode.parse("--preview package"; for_completions=true) == + (:sub, "", "package", true) + @test Pkg.REPLMode.parse("--preview package a"; for_completions=true) == + (:sub, "a", "package", true) # options @test Pkg.REPLMode.parse("add -"; for_completions=true) == (:opt, "-", Pkg.REPLMode.super_specs["package"]["add"], true) From fec46bc868446fabccaeeaccfbaad8fc44f5ee6b Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Mon, 13 Aug 2018 16:48:20 +0200 Subject: [PATCH 104/166] add develop for path (cherry picked from commit 9f2e6d973ef6801819e0414184facc05b2eece04) (cherry picked from commit cf02a682e3b4bfc8e02e2d660507ec89864763ee) --- stdlib/Pkg/src/REPLMode.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index 0e3b1c35a3f7a..e862140d26ec7 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -1122,6 +1122,7 @@ This operation is undone by `free`. ```jl pkg> develop Example pkg> develop https://github.com/JuliaLang/Example.jl +pkg> develop ~/mypackages/Example pkg> develop --local Example ``` """, From 7f88b2c359cbae618ee922df4951ec6ac8ccb0c0 Mon Sep 17 00:00:00 2001 From: David Varela <00.varela.david@gmail.com> Date: Fri, 17 Aug 2018 13:39:46 -0700 Subject: [PATCH 105/166] Use max/min to declare expected argument count (cherry picked from commit 13bf2f009bd36f616b438f527ec13593c5ea261d) (cherry picked from commit 6f02645d832731b05f4eebdc79ec1fc041fb781c) (cherry picked from commit 9bc0cf955ee89f4f31a7977fba109d9170c32816) --- stdlib/Pkg/src/REPLMode.jl | 47 +++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index e862140d26ec7..744df6d24b13b 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -97,14 +97,14 @@ meta_option_specs = OptionSpecs(meta_option_declarations) ) @enum(ArgClass, ARG_RAW, ARG_PKG, ARG_VERSION, ARG_REV, ARG_ALL) struct ArgSpec - count::Vector{Int} # note: just use range operator for max/min + count::Pair parser::Function parser_keys::Vector{Pair{Symbol, Any}} end const CommandDeclaration = Tuple{CommandKind, Vector{String}, # names Union{Nothing,Function}, # handler - Tuple{Vector{Int}, # count + Tuple{Pair, # count Function, # parser Vector{Pair{Symbol, Any}}, # parser keys }, # arguments @@ -431,10 +431,9 @@ function APIOptions(options::Vector{Option}, return Dict(keyword_vec) end -# TODO vector of what? -function enforce_argument_count(count::Vector{Int}, args::PkgArguments) - isempty(count) && return - length(args) in count || +function enforce_argument_count(spec::Pair, args::PkgArguments) + count = length(args) + spec.first <= count <= spec.second || pkgerror("Wrong number of arguments") end @@ -976,7 +975,7 @@ command_declarations = [ CMD_REGISTRY_ADD, ["add"], do_registry_add!, - ([], identity, []), + (1=>Inf, identity, []), [], "Currently just a placeholder for a future command", nothing, @@ -988,7 +987,7 @@ command_declarations = [ ( CMD_TEST, ["test"], do_test!, - ([], parse_pkg, []), + (0=>Inf, parse_pkg, []), [ ("coverage", OPT_SWITCH, :coverage => true), ], @@ -1007,7 +1006,7 @@ julia is started with `--startup-file=yes`. ),( CMD_HELP, ["help", "?"], nothing, - ([], identity, []), + (0=>Inf, identity, []), [], "show this message", md""" @@ -1025,7 +1024,7 @@ Available commands: `help`, `status`, `add`, `rm`, `up`, `preview`, `gc`, `test` ),( CMD_INSTANTIATE, ["instantiate"], do_instantiate!, - ([0], identity, []), + (0=>0, identity, []), [ (["project", "p"], OPT_SWITCH, :manifest => false), (["manifest", "m"], OPT_SWITCH, :manifest => true), @@ -1042,7 +1041,7 @@ If no manifest exists or the `--project` option is given, resolve and download t ),( CMD_RM, ["remove", "rm"], do_rm!, - ([], parse_pkg, []), + (1=>Inf, parse_pkg, []), [ (["project", "p"], OPT_SWITCH, :mode => PKGMODE_PROJECT), (["manifest", "m"], OPT_SWITCH, :mode => PKGMODE_MANIFEST), @@ -1071,7 +1070,7 @@ as any no-longer-necessary manifest packages due to project package removals. ),( CMD_ADD, ["add"], do_add!, - ([], parse_pkg, [:add_or_dev => true, :valid => [VersionRange, Rev]]), + (1=>Inf, parse_pkg, [:add_or_dev => true, :valid => [VersionRange, Rev]]), [], "add packages to project", md""" @@ -1102,7 +1101,7 @@ pkg> add Example=7876af07-990d-54b4-ab0e-23690620f79a ),( CMD_DEVELOP, ["develop", "dev"], do_develop!, - ([], parse_pkg, [:add_or_dev => true, :valid => [VersionRange]]), + (1=>Inf, parse_pkg, [:add_or_dev => true, :valid => [VersionRange]]), [ ("local", OPT_SWITCH, :shared => false), ("shared", OPT_SWITCH, :shared => true), @@ -1129,7 +1128,7 @@ pkg> develop --local Example ),( CMD_FREE, ["free"], do_free!, - ([], parse_pkg, []), + (1=>Inf, parse_pkg, []), [], "undoes a `pin`, `develop`, or stops tracking a repo", md""" @@ -1141,7 +1140,7 @@ makes the package no longer being checked out. ),( CMD_PIN, ["pin"], do_pin!, - ([], parse_pkg, [:valid => [VersionRange]]), + (1=>Inf, parse_pkg, [:valid => [VersionRange]]), [], "pins the version of packages", md""" @@ -1154,7 +1153,7 @@ A pinned package has the symbol `⚲` next to its version in the status list. ),( CMD_BUILD, ["build"], do_build!, - ([], parse_pkg, []), + (0=>Inf, parse_pkg, []), [], "run the build script for packages", md""" @@ -1168,7 +1167,7 @@ The `startup.jl` file is disabled during building unless julia is started with ` ),( CMD_RESOLVE, ["resolve"], do_resolve!, - ([0], identity, []), + (0=>0, identity, []), [], "resolves to update the manifest from changes in dependencies of developed packages", md""" @@ -1180,7 +1179,7 @@ packages have changed causing the current Manifest to_indices be out of sync. ),( CMD_ACTIVATE, ["activate"], do_activate!, - ([0,1], identity, []), + (0=>1, identity, []), [ ("shared", OPT_SWITCH, :shared => true), ], @@ -1198,7 +1197,7 @@ it will be placed in the first depot of the stack. ),( CMD_UP, ["update", "up"], do_up!, - ([], parse_pkg, [:valid => [VersionRange]]), + (0=>Inf, parse_pkg, [:valid => [VersionRange]]), [ (["project", "p"], OPT_SWITCH, :mode => PKGMODE_PROJECT), (["manifest", "m"], OPT_SWITCH, :mode => PKGMODE_MANIFEST), @@ -1227,7 +1226,7 @@ packages will not be upgraded at all. ),( CMD_GENERATE, ["generate"], do_generate!, - ([1], identity, []), + (1=>1, identity, []), [], "generate files for a new project", md""" @@ -1239,7 +1238,7 @@ Create a project called `pkgname` in the current folder. ),( CMD_PRECOMPILE, ["precompile"], do_precompile!, - ([0], identity, []), + (0=>0, identity, []), [], "precompile all the project dependencies", md""" @@ -1251,7 +1250,7 @@ The `startup.jl` file is disabled during precompilation unless julia is started ),( CMD_STATUS, ["status", "st"], do_status!, - ([0], identity, []), + (0=>0, identity, []), [ (["project", "p"], OPT_SWITCH, :mode => PKGMODE_PROJECT), (["manifest", "m"], OPT_SWITCH, :mode => PKGMODE_MANIFEST), @@ -1273,7 +1272,7 @@ includes the dependencies of explicitly added packages. ),( CMD_GC, ["gc"], do_gc!, - ([0], identity, []), + (0=>0, identity, []), [], "garbage collect packages not used for a significant time", md""" @@ -1285,7 +1284,7 @@ Deletes packages that cannot be reached from any existing environment. CMD_PREVIEW, ["preview"], nothing, - ([1], identity, []), + (1=>Inf, identity, []), [], "previews a subsequent command without affecting the current state", md""" From 8f816dbd496756300b7b5328652edf08cb0a631c Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Wed, 22 Aug 2018 18:26:57 +0200 Subject: [PATCH 106/166] work around strange "Unreachable reached" when the close function for the repo fires (cherry picked from commit 90ca61baa7b29cef2e1e089481afaeffa63544fa) --- stdlib/Pkg/src/API.jl | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/stdlib/Pkg/src/API.jl b/stdlib/Pkg/src/API.jl index ee308919facf1..28937ddc859b0 100644 --- a/stdlib/Pkg/src/API.jl +++ b/stdlib/Pkg/src/API.jl @@ -74,7 +74,7 @@ rm(pkgs::Vector{PackageSpec}; kwargs...) = rm(Context(), pkgs; kwargs...) function rm(ctx::Context, pkgs::Vector{PackageSpec}; mode=PKGMODE_PROJECT, kwargs...) for pkg in pkgs - #TODO only overwrite pkg.mode is default value ? + # TODO only overwrite pkg.mode if default value ? pkg.mode = mode end @@ -98,14 +98,23 @@ function update_registry(ctx) if isdir(joinpath(reg, ".git")) regpath = pathrepr(reg) printpkgstyle(ctx, :Updating, "registry at " * regpath) - LibGit2.with(LibGit2.GitRepo, reg) do repo + # Using LibGit2.with here crashes julia when running the + # tests for PkgDev wiht "Unreachable reached". + # This seems to work around it. + local repo + try + repo = LibGit2.GitRepo(reg) if LibGit2.isdirty(repo) push!(errors, (regpath, "registry dirty")) - return + @goto done end if !LibGit2.isattached(repo) push!(errors, (regpath, "registry detached")) - return + @goto done + end + if !("origin" in LibGit2.remotes(repo)) + push!(errors, (regpath, "origin not in the list of remotes")) + @goto done end branch = LibGit2.headname(repo) try @@ -113,14 +122,14 @@ function update_registry(ctx) catch e e isa PkgError || rethrow(e) push!(errors, (reg, "failed to fetch from repo")) - return + @goto done end ff_succeeded = try LibGit2.merge!(repo; branch="refs/remotes/origin/$branch", fastforward=true) catch e e isa LibGit2.GitError && e.code == LibGit2.Error.ENOTFOUND || rethrow(e) push!(errors, (reg, "branch origin/$branch not found")) - return + @goto done end if !ff_succeeded @@ -128,9 +137,12 @@ function update_registry(ctx) catch e e isa LibGit2.GitError || rethrow(e) push!(errors, (reg, "registry failed to rebase on origin/$branch")) - return + @goto done end end + @label done + finally + close(repo) end end end From 4137472f4a955485a19038ef9f793fe042b738e7 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Tue, 4 Sep 2018 09:20:34 -0400 Subject: [PATCH 107/166] use default proxy credentials when downloading via powershell (cherry picked from commit d495fed46606ff29685135bc63bffb5f7cc6d463) (cherry picked from commit 714b2c33df575f29395cabceeaaf26076aa39f3f) --- stdlib/Pkg/src/PlatformEngines.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stdlib/Pkg/src/PlatformEngines.jl b/stdlib/Pkg/src/PlatformEngines.jl index 8fb430d146be8..736ccccb0ea67 100644 --- a/stdlib/Pkg/src/PlatformEngines.jl +++ b/stdlib/Pkg/src/PlatformEngines.jl @@ -199,6 +199,8 @@ function probe_platform_engines!(;verbose::Bool = false) [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; \$webclient = (New-Object System.Net.Webclient); + \$webclient.UseDefaultCredentials = \$true; + \$webclient.Proxy.Credentials = \$webclient.Credentials; \$webclient.Headers.Add("user-agent", \"Pkg.jl (https://github.com/JuliaLang/Pkg.jl)\"); \$webclient.DownloadFile(\"$url\", \"$path\") """ From 8729c6380407dc8ae6a09bbc6525c74c39e62b87 Mon Sep 17 00:00:00 2001 From: Patrick Belliveau Date: Wed, 5 Sep 2018 03:09:00 -0700 Subject: [PATCH 108/166] Fix dispatch of SparseMatrixCSC*Diagonal multiplication (#29045) * Fix type signature of mul! methods for multiplying SparseMatrixCSCs with Diagonal matrices. Type signature for diagonal matrices was wrong, causing fallback to generic Matmul. * Add SparseMatrixCSC*Diagonal dispatch test * Fix trailing whitespace * Don't copy with deepcopy (cherry picked from commit 8d993569b86608f9588458930a203fa4bc29ad50) --- stdlib/SparseArrays/src/linalg.jl | 4 ++-- stdlib/SparseArrays/test/sparse.jl | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/stdlib/SparseArrays/src/linalg.jl b/stdlib/SparseArrays/src/linalg.jl index 6e9a751dd4306..ad8ffb2b14f63 100644 --- a/stdlib/SparseArrays/src/linalg.jl +++ b/stdlib/SparseArrays/src/linalg.jl @@ -968,7 +968,7 @@ function copyinds!(C::SparseMatrixCSC, A::SparseMatrixCSC) end # multiply by diagonal matrix as vector -function mul!(C::SparseMatrixCSC, A::SparseMatrixCSC, D::Diagonal{<:Vector}) +function mul!(C::SparseMatrixCSC, A::SparseMatrixCSC, D::Diagonal{T, <:Vector}) where T m, n = size(A) b = D.diag (n==length(b) && size(A)==size(C)) || throw(DimensionMismatch()) @@ -982,7 +982,7 @@ function mul!(C::SparseMatrixCSC, A::SparseMatrixCSC, D::Diagonal{<:Vector}) C end -function mul!(C::SparseMatrixCSC, D::Diagonal{<:Vector}, A::SparseMatrixCSC) +function mul!(C::SparseMatrixCSC, D::Diagonal{T, <:Vector}, A::SparseMatrixCSC) where T m, n = size(A) b = D.diag (m==length(b) && size(A)==size(C)) || throw(DimensionMismatch()) diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index 0c17946d7a5d8..416cbffac27cf 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -8,6 +8,7 @@ using LinearAlgebra using Base.Printf: @printf using Random using Test: guardseed +using InteractiveUtils: @which @testset "issparse" begin @test issparse(sparse(fill(1,5,5))) @@ -2295,4 +2296,15 @@ end @test typeof(a) === typeof(na) end +#PR #29045 +@testset "Issue #28934" begin + A = sprand(5,5,0.5) + D = Diagonal(rand(5)) + C = copy(A) + m1 = @which mul!(C,A,D) + m2 = @which mul!(C,D,A) + @test m1.module == SparseArrays + @test m2.module == SparseArrays +end + end # module From 5279e48afb2a174b42e75a1e700b6c62c7884926 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 5 Sep 2018 17:49:57 -0400 Subject: [PATCH 109/166] fix #28900, macro hygiene bug inside keyword arg values (#29043) (cherry picked from commit 1fb86d2dae91dbd96ac43011468236380f1ac021) --- src/macroexpand.scm | 4 ++-- test/syntax.jl | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/macroexpand.scm b/src/macroexpand.scm index abad3407656fd..d95e8132ff21e 100644 --- a/src/macroexpand.scm +++ b/src/macroexpand.scm @@ -379,12 +379,12 @@ ;; in keyword arg A=B, don't transform "A" (unescape (cadr (cadr e)))) ,(resolve-expansion-vars- (caddr (cadr e)) env m parent-scope inarg)) - ,(resolve-expansion-vars- (caddr e) env m parent-scope inarg))) + ,(resolve-expansion-vars-with-new-env (caddr e) env m parent-scope inarg))) (else `(kw ,(if inarg (resolve-expansion-vars- (cadr e) env m parent-scope inarg) (unescape (cadr e))) - ,(resolve-expansion-vars- (caddr e) env m parent-scope inarg))))) + ,(resolve-expansion-vars-with-new-env (caddr e) env m parent-scope inarg))))) ((let) (let* ((newenv (new-expansion-env-for e env)) diff --git a/test/syntax.jl b/test/syntax.jl index 9e12206ad8325..250c73503a711 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -1673,3 +1673,14 @@ end @test A28593.var.name === :S @test B28593.var.name === :S @test C28593.var.name === :S + +# issue #28900 +macro foo28900(x) + quote + $x + end +end +f28900(; kwarg) = kwarg +let g = @foo28900 f28900(kwarg = x->2x) + @test g(10) == 20 +end From f5bf3317f04b907343f48412dc8a9a8bc43358a9 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 5 Sep 2018 17:50:34 -0400 Subject: [PATCH 110/166] fix #28991, error when adding default defs to constructed module Exprs (#29044) The code for this expected the first element of a block to be a line number; check to make sure it is before using it. (cherry picked from commit 11e32a44f259d46aafcc7f9feac10aaa241743e0) --- src/jlfrontend.scm | 11 +++++++---- test/syntax.jl | 8 ++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/jlfrontend.scm b/src/jlfrontend.scm index 8233a47feb3aa..77557c14ab682 100644 --- a/src/jlfrontend.scm +++ b/src/jlfrontend.scm @@ -133,16 +133,19 @@ (jl-expand-to-thunk (let* ((name (caddr e)) (body (cadddr e)) - (loc (cadr body)) - (x (if (eq? name 'x) 'y 'x))) + (loc (cadr body)) + (loc (if (and (pair? loc) (eq? (car loc) 'line)) + (list loc) + '())) + (x (if (eq? name 'x) 'y 'x))) `(block (= (call eval ,x) (block - ,loc + ,@loc (call (core eval) ,name ,x))) (= (call include ,x) (block - ,loc + ,@loc (call (top include) ,name ,x))))))) ;; parse only, returning end position, no expansion. diff --git a/test/syntax.jl b/test/syntax.jl index 250c73503a711..2090a1a5cfef0 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -1647,6 +1647,14 @@ end @test Meta.isexpr(Meta.parse("1 == 2 ?"), :incomplete) @test Meta.isexpr(Meta.parse("1 == 2 ? 3 :"), :incomplete) +# issue #28991 +eval(Expr(:toplevel, + Expr(:module, true, :Mod28991, + Expr(:block, + Expr(:export, :Inner), + Expr(:abstract, :Inner))))) +@test names(Mod28991) == Symbol[:Inner, :Mod28991] + # issue #28593 macro a28593() quote From f928df4c2d16a1e4f90707047d88eb9ad822ac0f Mon Sep 17 00:00:00 2001 From: zy Date: Thu, 6 Sep 2018 22:23:18 +0800 Subject: [PATCH 111/166] Fix typo on file.jl (#29063) cp() doc : dest->dst (cherry picked from commit 53f8e186790f5e544fa0674e6169845cdbc439d8) --- base/file.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/file.jl b/base/file.jl index 1fab5238bc745..da966d37f0e49 100644 --- a/base/file.jl +++ b/base/file.jl @@ -317,7 +317,7 @@ end """ cp(src::AbstractString, dst::AbstractString; force::Bool=false, follow_symlinks::Bool=false) -Copy the file, link, or directory from `src` to `dest`. +Copy the file, link, or directory from `src` to `dst`. `force=true` will first remove an existing `dst`. If `follow_symlinks=false`, and `src` is a symbolic link, `dst` will be created as a From f160e4e5c314d1a71e38ec29c944e63a184663b2 Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 6 Sep 2018 15:39:53 +0100 Subject: [PATCH 112/166] Fix typo in mapreduce docstring (#29049) (cherry picked from commit be14985ef8e65af79c4bcd6e8a9ce6a59b88f513) --- base/reduce.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/reduce.jl b/base/reduce.jl index caeadc55b4017..a1732a87f860f 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -180,7 +180,7 @@ mapreduce_impl(f, op, A::AbstractArray, ifirst::Integer, ilast::Integer) = mapreduce(f, op, itr; [init]) Apply function `f` to each element in `itr`, and then reduce the result using the binary -function `op`. If provided, `init` must be a neutral element for `op` that will be returne +function `op`. If provided, `init` must be a neutral element for `op` that will be returned for empty collections. It is unspecified whether `init` is used for non-empty collections. In general, it will be necessary to provide `init` to work with empty collections. From f7bbec5491e46de01e33320efbdb3e0e06fe9c9f Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 6 Sep 2018 12:04:54 -0400 Subject: [PATCH 113/166] fix #28833, crash in macros returning certain top-level forms (#28882) (cherry picked from commit e5cc7506d335089469f7be026ef954e684274e7f) --- src/toplevel.c | 98 +++++++++++++++++++++++++++++++------------------- test/syntax.jl | 6 ++++ 2 files changed, 68 insertions(+), 36 deletions(-) diff --git a/src/toplevel.c b/src/toplevel.c index 6da0ab47b98f5..a57ad3b16ddfb 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -523,6 +523,29 @@ int jl_is_toplevel_only_expr(jl_value_t *e) ((jl_expr_t*)e)->head == jl_incomplete_sym); } +int jl_needs_lowering(jl_value_t *e) JL_NOTSAFEPOINT +{ + if (!jl_is_expr(e)) + return 0; + jl_expr_t *ex = (jl_expr_t*)e; + jl_sym_t *head = ex->head; + if (head == module_sym || head == import_sym || head == using_sym || + head == export_sym || head == thunk_sym || head == toplevel_sym || + head == error_sym || head == jl_incomplete_sym || head == method_sym) { + return 0; + } + if (head == global_sym) { + size_t i, l = jl_array_len(ex->args); + for (i = 0; i < l; i++) { + jl_value_t *a = jl_exprarg(ex, i); + if (!jl_is_symbol(a) && !jl_is_globalref(a)) + return 1; + } + return 0; + } + return 1; +} + void jl_resolve_globals_in_ir(jl_array_t *stmts, jl_module_t *m, jl_svec_t *sparam_vals, int binding_effects); @@ -600,22 +623,36 @@ jl_value_t *jl_toplevel_eval_flex(jl_module_t *m, jl_value_t *e, int fast, int e } jl_expr_t *ex = (jl_expr_t*)e; + if (ex->head == dot_sym) { if (jl_expr_nargs(ex) != 2) jl_error("syntax: malformed \".\" expression"); jl_value_t *lhs = jl_exprarg(ex, 0); jl_value_t *rhs = jl_exprarg(ex, 1); - // only handle `a.b` syntax here + // only handle `a.b` syntax here, so qualified names can be eval'd in pure contexts if (jl_is_quotenode(rhs) && jl_is_symbol(jl_fieldref(rhs,0))) return jl_eval_dot_expr(m, lhs, rhs, fast); } + if (ptls->in_pure_callback) { jl_error("eval cannot be used in a generated function"); } - else if (ex->head == module_sym) { - return jl_eval_module_expr(m, ex); + + jl_method_instance_t *li = NULL; + jl_code_info_t *thk = NULL; + JL_GC_PUSH3(&li, &thk, &ex); + + if (!expanded && jl_needs_lowering(e)) { + ex = (jl_expr_t*)jl_expand(e, m); + } + jl_sym_t *head = jl_is_expr(ex) ? ex->head : NULL; + + if (head == module_sym) { + jl_value_t *val = jl_eval_module_expr(m, ex); + JL_GC_POP(); + return val; } - else if (ex->head == using_sym) { + else if (head == using_sym) { size_t last_age = ptls->world_age; ptls->world_age = jl_world_counter; jl_sym_t *name = NULL; @@ -652,9 +689,10 @@ jl_value_t *jl_toplevel_eval_flex(jl_module_t *m, jl_value_t *e, int fast, int e } } ptls->world_age = last_age; + JL_GC_POP(); return jl_nothing; } - else if (ex->head == import_sym) { + else if (head == import_sym) { size_t last_age = ptls->world_age; ptls->world_age = jl_world_counter; jl_sym_t *name = NULL; @@ -679,53 +717,41 @@ jl_value_t *jl_toplevel_eval_flex(jl_module_t *m, jl_value_t *e, int fast, int e } } ptls->world_age = last_age; + JL_GC_POP(); return jl_nothing; } - else if (ex->head == export_sym) { + else if (head == export_sym) { for (size_t i = 0; i < jl_array_len(ex->args); i++) { jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(ex->args, i); if (!jl_is_symbol(name)) jl_error("syntax: malformed \"export\" statement"); jl_module_export(m, name); } + JL_GC_POP(); return jl_nothing; } - else if (ex->head == global_sym) { + else if (head == global_sym) { // create uninitialized mutable binding for "global x" decl size_t i, l = jl_array_len(ex->args); for (i = 0; i < l; i++) { - jl_value_t *a = jl_exprarg(ex, i); - if (!jl_is_symbol(a) && !jl_is_globalref(a)) - break; - } - if (i == l) { - for (i = 0; i < l; i++) { - jl_sym_t *gs = (jl_sym_t*)jl_exprarg(ex, i); - jl_module_t *gm = m; - if (jl_is_globalref(gs)) { - gm = jl_globalref_mod(gs); - gs = jl_globalref_name(gs); - } - assert(jl_is_symbol(gs)); - jl_get_binding_wr(gm, gs, 0); + jl_value_t *arg = jl_exprarg(ex, i); + jl_module_t *gm; + jl_sym_t *gs; + if (jl_is_globalref(arg)) { + gm = jl_globalref_mod(arg); + gs = jl_globalref_name(arg); } - return jl_nothing; + else { + assert(jl_is_symbol(arg)); + gm = m; + gs = (jl_sym_t*)arg; + } + jl_get_binding_wr(gm, gs, 0); } - // fall-through to expand to normalize the syntax - } - - jl_method_instance_t *li = NULL; - jl_code_info_t *thk = NULL; - JL_GC_PUSH3(&li, &thk, &ex); - - if (!expanded && ex->head != thunk_sym && ex->head != method_sym && ex->head != toplevel_sym && - ex->head != error_sym && ex->head != jl_incomplete_sym) { - // not yet expanded - ex = (jl_expr_t*)jl_expand(e, m); + JL_GC_POP(); + return jl_nothing; } - jl_sym_t *head = jl_is_expr(ex) ? ex->head : NULL; - - if (head == toplevel_sym) { + else if (head == toplevel_sym) { size_t last_age = ptls->world_age; jl_value_t *res = jl_nothing; int i; diff --git a/test/syntax.jl b/test/syntax.jl index 2090a1a5cfef0..7702fb8686767 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -1682,6 +1682,12 @@ end @test B28593.var.name === :S @test C28593.var.name === :S +# issue #28833 +macro m28833(expr) + esc(:(global a28833)) +end +@m28833 1+1 + # issue #28900 macro foo28900(x) quote From 059e36dd430b934d446aafaa455e1c8b56dcc072 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Thu, 6 Sep 2018 14:03:05 -0400 Subject: [PATCH 114/166] work around a splatting penalty in twiceprecision (#29060) * work around a splatting penalty in twiceprecision * add allocation test (cherry picked from commit 88d536a1ea8903dfdfd78f86a5be75eedcfddf5a) --- base/twiceprecision.jl | 7 +++++-- test/ranges.jl | 7 +++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/base/twiceprecision.jl b/base/twiceprecision.jl index cf61823ecc0f6..e80c87c2eb8e5 100644 --- a/base/twiceprecision.jl +++ b/base/twiceprecision.jl @@ -332,11 +332,14 @@ const F_or_FF = Union{AbstractFloat, Tuple{AbstractFloat,AbstractFloat}} asF64(x::AbstractFloat) = Float64(x) asF64(x::Tuple{AbstractFloat,AbstractFloat}) = Float64(x[1]) + Float64(x[2]) +# Defined to prevent splatting in the function below which here has a performance impact +_TP(x) = TwicePrecision{Float64}(x) +_TP(x::Tuple{Any, Any}) = TwicePrecision{Float64}(x[1], x[2]) function steprangelen_hp(::Type{Float64}, ref::F_or_FF, step::F_or_FF, nb::Integer, len::Integer, offset::Integer) - StepRangeLen(TwicePrecision{Float64}(ref...), - twiceprecision(TwicePrecision{Float64}(step...), nb), Int(len), offset) + StepRangeLen(_TP(ref), + twiceprecision(_TP(step), nb), Int(len), offset) end function steprangelen_hp(::Type{T}, ref::F_or_FF, diff --git a/test/ranges.jl b/test/ranges.jl index 5817871b04050..ad720f7a2553f 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -1371,3 +1371,10 @@ end # module NonStandardIntegerRangeTest end end end + +@testset "allocation of TwicePrecision call" begin + 0:286.493442:360 + 0:286:360 + @test @allocated(0:286.493442:360) == 0 + @test @allocated(0:286:360) == 0 +end From 780e74a29e7de2b8f758b941dac51089c465c611 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Thu, 6 Sep 2018 21:26:41 +0200 Subject: [PATCH 115/166] add local to outer description (#29010) (cherry picked from commit bda5dd869f6600335a6e4de57b34b3c0501e49dd) --- doc/src/manual/variables-and-scoping.md | 2 +- src/julia-syntax.scm | 2 +- test/core.jl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/src/manual/variables-and-scoping.md b/doc/src/manual/variables-and-scoping.md index ab6f1962be0c6..47098fe0f9899 100644 --- a/doc/src/manual/variables-and-scoping.md +++ b/doc/src/manual/variables-and-scoping.md @@ -449,7 +449,7 @@ julia> f() 0 ``` -However, it is occasionally useful to reuse an existing variable as the iteration variable. +However, it is occasionally useful to reuse an existing local variable as the iteration variable. This can be done conveniently by adding the keyword `outer`: ```jldoctest diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 4a3d43613cff1..bed7108b176fc 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -2430,7 +2430,7 @@ '(null)) ((eq? (car e) 'require-existing-local) (if (not (memq (cadr e) env)) - (error "no outer variable declaration exists for \"for outer\"")) + (error "no outer local variable declaration exists for \"for outer\"")) '(null)) ((eq? (car e) 'lambda) (let* ((lv (lam:vars e)) diff --git a/test/core.jl b/test/core.jl index 822fa6fca76c7..ff9282a243b40 100644 --- a/test/core.jl +++ b/test/core.jl @@ -3256,7 +3256,7 @@ let @test forouter() == 3 end -@test_throws ErrorException("syntax: no outer variable declaration exists for \"for outer\"") @eval function f() +@test_throws ErrorException("syntax: no outer local variable declaration exists for \"for outer\"") @eval function f() for outer i = 1:2 end end From 8c5384316241248b32a5f5eef73811c9ab23dd19 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 7 Sep 2018 13:39:14 -0400 Subject: [PATCH 116/166] stronger warnings about changing constants in help and docs (#28711) [ci skip] (cherry picked from commit 4b103ef33da6f3e66fc5708ee78f6fe37b0c6f36) --- base/docs/basedocs.jl | 18 ++++++++++-------- doc/src/manual/variables-and-scoping.md | 7 +++++-- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 062a9e554aa9a..4c12bf68d80b5 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -260,7 +260,7 @@ kw"'" """ const -`const` is used to declare global variables which are also constant. In almost all code +`const` is used to declare global variables whose values will not change. In almost all code (and particularly performance sensitive code) global variables should be declared constant in this way. @@ -275,15 +275,17 @@ const y, z = 7, 11 Note that `const` only applies to one `=` operation, therefore `const x = y = 1` declares `x` to be constant but not `y`. On the other hand, `const x = const y = 1` -declares both `x` and `y` as constants. +declares both `x` and `y` constant. -Note that "constant-ness" is not enforced inside containers, so if `x` is an array or -dictionary (for example) you can still add and remove elements. +Note that "constant-ness" does not extend into mutable containers; only the +association between a variable and its value is constant. +If `x` is an array or dictionary (for example) you can still modify, add, or remove elements. -Technically, you can even redefine `const` variables, although this will generate a -warning from the compiler. The only strict requirement is that the *type* of the -variable does not change, which is why `const` variables are much faster than regular -globals. +In some cases changing the value of a `const` variable gives a warning instead of +an error. +However, this can produce unpredictable behavior or corrupt the state of your program, +and so should be avoided. +This feature is intended only for convenience during interactive use. """ kw"const" diff --git a/doc/src/manual/variables-and-scoping.md b/doc/src/manual/variables-and-scoping.md index 47098fe0f9899..82d84f289ad4d 100644 --- a/doc/src/manual/variables-and-scoping.md +++ b/doc/src/manual/variables-and-scoping.md @@ -555,8 +555,11 @@ WARNING: redefining constant a 1 ``` -Note that although possible, changing the value of a variable that is declared as constant -is strongly discouraged. For instance, if a method references a constant and is already +Note that although sometimes possible, changing the value of a `const` variable +is strongly discouraged, and is intended only for convenience during +interactive use. +Changing constants can cause various problems or unexpected behaviors. +For instance, if a method references a constant and is already compiled before the constant is changed then it might keep using the old value: ```jldoctest julia> const x = 1 From f8895099c80d74b73aa0f456b33f203b079e71a1 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 7 Sep 2018 14:25:26 -0400 Subject: [PATCH 117/166] fix #29064, bug in field name same as struct type name (#29070) (cherry picked from commit cfca8334dd6f99a3d7f621e338869c0a58a3ae99) --- src/julia-syntax.scm | 2 +- test/syntax.jl | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index bed7108b176fc..8d6a08daae273 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -692,7 +692,7 @@ ,@(map make-decl field-names field-types)) (block ,@locs - (new ,name ,@field-names)))) + (new (outerref ,name) ,@field-names)))) any-ctor) (list any-ctor)))) diff --git a/test/syntax.jl b/test/syntax.jl index 7702fb8686767..021d591d4e55a 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -1502,6 +1502,12 @@ function test27710() end @test test27710() === Int64 +# issue #29064 +struct X29064 + X29064::Int +end +@test X29064(1) isa X29064 + # issue #27268 function f27268() g(col::AbstractArray{<:Real}) = col From 718cb82c3468ad4fd70b1c79fb48bfe78863d19e Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 7 Sep 2018 17:18:46 -0400 Subject: [PATCH 118/166] fix #25955, hygiene of arg name of function defined by type (`(f::T)(...)`) (#29072) (cherry picked from commit bb7d0434d79c0ef8217706faec846862e3b2b805) --- src/macroexpand.scm | 10 ++++++++-- test/syntax.jl | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/macroexpand.scm b/src/macroexpand.scm index d95e8132ff21e..4349e3a5b67d6 100644 --- a/src/macroexpand.scm +++ b/src/macroexpand.scm @@ -60,7 +60,7 @@ ;; function definition (pattern-lambda (function (-$ (call name . argl) (|::| (call name . argl) _t)) body) - (cons 'varlist (safe-llist-positional-args (fix-arglist argl)))) + (cons 'varlist (safe-llist-positional-args (fix-arglist (append (self-argname name) argl))))) (pattern-lambda (function (where callspec . wheres) body) (let ((others (pattern-expand1 vars-introduced-by-patterns `(function ,callspec ,body)))) (cons 'varlist (append (if (and (pair? others) (eq? (car others) 'varlist)) @@ -75,7 +75,7 @@ (pattern-lambda (= (call (curly name . sparams) . argl) body) `(function (call (curly ,name . ,sparams) . ,argl) ,body)) (pattern-lambda (= (-$ (call name . argl) (|::| (call name . argl) _t)) body) - `(function (call ,name ,@argl) ,body)) + `(function ,(cadr __) ,body)) (pattern-lambda (= (where callspec . wheres) body) (cons 'function (cdr __))) @@ -257,6 +257,12 @@ ;; count escaped argument names as "keywords" to prevent renaming (safe-llist-positional-args lst #t)))) +;; argument name for the function itself given `function (f::T)(...)`, otherwise () +(define (self-argname name) + (if (and (length= name 3) (eq? (car name) '|::|)) + (list (cadr name)) + '())) + ;; resolve-expansion-vars-with-new-env, but turn on `inarg` once we get inside ;; the formal argument list. `e` in general might be e.g. `(f{T}(x)::T) where T`, ;; and we want `inarg` to be true for the `(x)` part. diff --git a/test/syntax.jl b/test/syntax.jl index 021d591d4e55a..6c6fc089b7203 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -1688,6 +1688,20 @@ end @test B28593.var.name === :S @test C28593.var.name === :S +# issue #25955 +macro noeffect25955(e) + return e +end + +struct foo25955 +end + +@noeffect25955 function (f::foo25955)() + 42 +end + +@test foo25955()() == 42 + # issue #28833 macro m28833(expr) esc(:(global a28833)) From 8edfd15e47e135fe33b807ab5b98fbc67ada2a01 Mon Sep 17 00:00:00 2001 From: dehann Date: Fri, 7 Sep 2018 23:48:41 -0400 Subject: [PATCH 119/166] Documentation `mynorm` should not divide by n (#29091) Test with: ```julia a = randn(10) abs(norm(a) - mynorm(a)) < 1e10 ``` Tested here: ```julia-repl _ _ _(_)_ | A fresh approach to technical computing (_) | (_) (_) | Documentation: https://docs.julialang.org _ _ _| |_ __ _ | Type "?help" for help. | | | | | | |/ _` | | | | |_| | | | (_| | | Version 0.6.4 (2018-07-09 19:09 UTC) _/ |\__'_|_|_|\__'_| | Official http://julialang.org/ release |__/ | x86_64-pc-linux-gnu julia> function mynorm(u::Vector) n = length(u) T = eltype(u) s = zero(T) @fastmath @inbounds @simd for i in 1:n s += u[i]^2 end @fastmath @inbounds return sqrt(s) end mynorm (generic function with 1 method) julia> function mynorm_old(u::Vector) n = length(u) T = eltype(u) s = zero(T) @fastmath @inbounds @simd for i in 1:n s += u[i]^2 end @fastmath @inbounds return sqrt(s/n) end mynorm_old (generic function with 1 method) julia> a = randn(10) 10-element Array{Float64,1}: -0.564163 -3.45236 -0.50901 -0.030296 0.114156 0.661961 -1.19972 2.20883 1.74529 0.82515 julia> abs(norm(a)-mynorm(a)) 0.0 julia> abs(norm(a)-mynorm_old(a)) 3.2787896367314344 ``` (cherry picked from commit a57250432abfafcc3b3ffa9df26e79516d1f6160) --- doc/src/manual/performance-tips.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/performance-tips.md b/doc/src/manual/performance-tips.md index b830f34a07b1d..ce86bc9ffdf9a 100644 --- a/doc/src/manual/performance-tips.md +++ b/doc/src/manual/performance-tips.md @@ -1231,7 +1231,7 @@ function mynorm(u::Vector) @fastmath @inbounds @simd for i in 1:n s += u[i]^2 end - @fastmath @inbounds return sqrt(s/n) + @fastmath @inbounds return sqrt(s) end function main() From e76410006b211722b451bc1a5a174b97dc67aa4d Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 7 Sep 2018 12:45:00 -0400 Subject: [PATCH 120/166] fix logic in `getfield_nothrow` to allow removing more getfields (cherry picked from commit 42e89201452a5bb161bdc3f250511a9f8df199c5) --- base/compiler/tfuncs.jl | 6 ++++-- test/inline.jl | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index d4bc7253da23d..b63cd5784790d 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -537,8 +537,10 @@ function getfield_nothrow(@nospecialize(s00), @nospecialize(name), @nospecialize sv = s00.val end if isa(name, Const) - (isa(sv, Module) && isa(name.val, Symbol)) || return false - (isa(name.val, Symbol) || isa(name.val, Int)) || return false + if !isa(name.val, Symbol) + isa(sv, Module) && return false + isa(name.val, Int) || return false + end return isdefined(sv, name.val) end if bounds_check_disabled && !isa(sv, Module) diff --git a/test/inline.jl b/test/inline.jl index 1d5554b5b362c..272584faed94e 100644 --- a/test/inline.jl +++ b/test/inline.jl @@ -137,3 +137,7 @@ end (src, _) = code_typed(sum27403, Tuple{Vector{Int}})[1] @test !any(x -> x isa Expr && x.head === :invoke, src.code) end + +# check that type.mutable can be fully eliminated +f_mutable_nothrow(s::String) = Val{typeof(s).mutable} +@test length(code_typed(f_mutable_nothrow, (String,))[1][1].code) == 1 From c306dbc0ffcd204e82e5b5d8e4480fd05b5b7606 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 7 Sep 2018 13:16:55 -0400 Subject: [PATCH 121/166] fix #29083, not eliminating kwfunc due to logic error in builtin_nothrow (cherry picked from commit 65e4c1391b8062fd9f333a43116f8d67691d006b) --- base/compiler/tfuncs.jl | 2 +- test/inline.jl | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index b63cd5784790d..8e9a33b34f00b 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -1058,7 +1058,7 @@ function _builtin_nothrow(@nospecialize(f), argtypes::Array{Any,1}, @nospecializ length(argtypes) == 1 || return false return sizeof_nothrow(argtypes[1]) elseif f === Core.kwfunc - length(argtypes) == 2 || return false + length(argtypes) == 1 || return false return isa(rt, Const) end return false diff --git a/test/inline.jl b/test/inline.jl index 272584faed94e..447bcdee51a22 100644 --- a/test/inline.jl +++ b/test/inline.jl @@ -111,6 +111,16 @@ let a = read21311() @test a[] == 1 end +# issue #29083 +f29083(;μ,σ) = μ + σ*randn() +g29083() = f29083(μ=2.0,σ=0.1) +let c = code_typed(g29083, ())[1][1].code + # make sure no call to kwfunc remains + @test !any(e->(isa(e,Expr) && ((e.head === :invoke && e.args[1].def.name === :kwfunc) || + (e.head === :foreigncall && e.args[1] === QuoteNode(:jl_get_keyword_sorter)))), + c) +end + @testset "issue #19122: [no]inline of short func. def. with return type annotation" begin exf19122 = @macroexpand(@inline f19122()::Bool = true) exg19122 = @macroexpand(@noinline g19122()::Bool = true) From e9093a12ae98708ac46147d83292d59ea37e8a41 Mon Sep 17 00:00:00 2001 From: Iblis Lin Date: Sun, 9 Sep 2018 07:01:18 +0800 Subject: [PATCH 122/166] doc/interface: correct signature of `size` (#29094) (cherry picked from commit 0c73ad1d72318f4a314a708bb1b51a6fd758e9a9) --- doc/src/manual/interfaces.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/manual/interfaces.md b/doc/src/manual/interfaces.md index d21c493bea36f..5b529022997ee 100644 --- a/doc/src/manual/interfaces.md +++ b/doc/src/manual/interfaces.md @@ -16,12 +16,12 @@ to generically build upon those behaviors. | `IteratorEltype(IterType)` | `HasEltype()` | Either `EltypeUnknown()` or `HasEltype()` as appropriate | | `eltype(IterType)` | `Any` | The type of the first entry of the tuple returned by `iterate()` | | `length(iter)` | (*undefined*) | The number of items, if known | -| `size(iter, [dim...])` | (*undefined*) | The number of items in each dimension, if known | +| `size(iter, [dim])` | (*undefined*) | The number of items in each dimension, if known | | Value returned by `IteratorSize(IterType)` | Required Methods | |:------------------------------------------ |:------------------------------------------ | | `HasLength()` | [`length(iter)`](@ref) | -| `HasShape{N}()` | `length(iter)` and `size(iter, [dim...])` | +| `HasShape{N}()` | `length(iter)` and `size(iter, [dim])` | | `IsInfinite()` | (*none*) | | `SizeUnknown()` | (*none*) | From af420c6f31692bf949475997c2122b33d8c9cde3 Mon Sep 17 00:00:00 2001 From: Malcolm Parsons Date: Sat, 8 Sep 2018 22:10:15 +0100 Subject: [PATCH 123/166] This comma confused me. Remove it (cherry picked from commit 68db9b4179ce49782d0fe9ff6c278cfd176f33e4) --- doc/src/manual/integers-and-floating-point-numbers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/integers-and-floating-point-numbers.md b/doc/src/manual/integers-and-floating-point-numbers.md index 8478d497d91ad..b4d82c39fe44c 100644 --- a/doc/src/manual/integers-and-floating-point-numbers.md +++ b/doc/src/manual/integers-and-floating-point-numbers.md @@ -178,7 +178,7 @@ of the binary data item is the minimal needed size, if the leading digit of the `0`. In the case of leading zeros, the size is determined by the minimal needed size for a literal, which has the same length but leading digit `1`. That allows the user to control the size. -Values, which cannot be stored in `UInt128` cannot be written as such literals. +Values which cannot be stored in `UInt128` cannot be written as such literals. Binary, octal, and hexadecimal literals may be signed by a `-` immediately preceding the unsigned literal. They produce an unsigned integer of the same size as the unsigned literal From d3096d8a822fbd4eb6338f3c8f622b43dcf0f41b Mon Sep 17 00:00:00 2001 From: Justin Willmert Date: Sat, 8 Sep 2018 12:46:21 -0500 Subject: [PATCH 124/166] Avoid duplicated =value in Enum errors. (cherry picked from commit ecff881203ed3d1b0b5260f47bd33f4126e47986) --- base/Enums.jl | 2 +- test/enums.jl | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/base/Enums.jl b/base/Enums.jl index 4c457443f678d..234fc42d28afa 100644 --- a/base/Enums.jl +++ b/base/Enums.jl @@ -103,7 +103,7 @@ macro enum(T, syms...) length(s.args) == 2 && isa(s.args[1], Symbol) i = Core.eval(__module__, s.args[2]) # allow exprs, e.g. uint128"1" if !isa(i, Integer) - throw(ArgumentError("invalid value for Enum $typename, $s=$i; values must be integers")) + throw(ArgumentError("invalid value for Enum $typename, $s; values must be integers")) end i = convert(basetype, i) s = s.args[1] diff --git a/test/enums.jl b/test/enums.jl index aeccadb44e502..c85ef556dd58f 100644 --- a/test/enums.jl +++ b/test/enums.jl @@ -77,8 +77,8 @@ end @test Int(_neg4) === -4 @test Int(_neg3) === -3 -@test_throws ArgumentError("invalid value for Enum Test1, _zerofp = 0.0=0.0; values must be integers") @macrocall(@enum Test1 _zerofp=0.0) -@test_throws ArgumentError("invalid value for Enum Test11, _zerofp2 = 0.5=0.5; values must be integers") @macrocall(@enum Test11 _zerofp2=0.5) +@test_throws ArgumentError("invalid value for Enum Test1, _zerofp = 0.0; values must be integers") @macrocall(@enum Test1 _zerofp=0.0) +@test_throws ArgumentError("invalid value for Enum Test11, _zerofp2 = 0.5; values must be integers") @macrocall(@enum Test11 _zerofp2=0.5) @enum Test111 _zerobi=BigInt(1) @test Integer(_zerobi) == 1 @@ -107,9 +107,9 @@ end @test typeof(Integer(_one_Test6)) == UInt128 # enum values must be integers -@test_throws ArgumentError("invalid value for Enum Test7, _zero = \"zero\"=zero; values must be integers") @macrocall(@enum Test7 _zero="zero") -@test_throws ArgumentError("invalid value for Enum Test8, _zero = '0'=0; values must be integers") @macrocall(@enum Test8 _zero='0') -@test_throws ArgumentError("invalid value for Enum Test9, _zero = 0.5=0.5; values must be integers") @macrocall(@enum Test9 _zero=0.5) +@test_throws ArgumentError("invalid value for Enum Test7, _zero = \"zero\"; values must be integers") @macrocall(@enum Test7 _zero="zero") +@test_throws ArgumentError("invalid value for Enum Test8, _zero = '0'; values must be integers") @macrocall(@enum Test8 _zero='0') +@test_throws ArgumentError("invalid value for Enum Test9, _zero = 0.5; values must be integers") @macrocall(@enum Test9 _zero=0.5) # test macro handles keyword arguments @enum(Test11, _zero_Test11=2, From fd06f0574b047ba556e7ba3b299756b6b9248a88 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 6 Sep 2018 23:32:38 -0400 Subject: [PATCH 125/166] fix #29036, poor inference of `val,i = iterate(x,i)` In this case, the result of `iterate` has not been checked for `nothing`, so we try to call `indexed_iterate` (for destructuring assignment) on a Union of Nothing and the tuple returned by `iterate`. That has two method matches, and so was excluded from constant propagation. This commit fixes that by generalizing the constant prop heuristic from requiring one method match to requiring one non-Bottom method match. This issue caused a large slowdown in DelimitedFiles, where the inner loop consists of ``` while idx <= slen val,idx = iterate(dbuff, idx) ``` (cherry picked from commit 957b9c059bc8720b9a62c844c29ed84d7716d5e4) --- base/compiler/abstractinterpretation.jl | 27 +++++++++++++++++-------- base/tuple.jl | 2 +- test/compiler/compiler.jl | 7 +++++++ 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 9ca7db1f669a6..17f9eba24044e 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -55,12 +55,15 @@ function abstract_call_gf_by_type(@nospecialize(f), argtypes::Vector{Any}, @nosp rettype = Bottom edgecycle = false edges = Any[] + nonbot = 0 # the index of the only non-Bottom inference result if > 0 + seen = 0 # number of signatures actually inferred for i in 1:napplicable match = applicable[i]::SimpleVector method = match[3]::Method sig = match[1] sigtuple = unwrap_unionall(sig)::DataType splitunions = false + this_rt = Bottom # TODO: splitunions = 1 < countunionsplit(sigtuple.parameters) * napplicable <= sv.params.MAX_UNION_SPLITTING # currently this triggers a bug in inference recursion detection if splitunions @@ -71,24 +74,32 @@ function abstract_call_gf_by_type(@nospecialize(f), argtypes::Vector{Any}, @nosp push!(edges, edge) end edgecycle |= edgecycle1::Bool - rettype = tmerge(rettype, rt) - rettype === Any && break + this_rt = tmerge(this_rt, rt) + this_rt === Any && break end - rettype === Any && break else - rt, edgecycle, edge = abstract_call_method(method, sig, match[2]::SimpleVector, sv) + this_rt, edgecycle, edge = abstract_call_method(method, sig, match[2]::SimpleVector, sv) if edge !== nothing push!(edges, edge) end - rettype = tmerge(rettype, rt) - rettype === Any && break end + if this_rt !== Bottom + if nonbot === 0 + nonbot = i + else + nonbot = -1 + end + end + seen += 1 + rettype = tmerge(rettype, this_rt) + rettype === Any && break end - if napplicable == 1 && !edgecycle && isa(rettype, Type) && sv.params.ipo_constant_propagation + # try constant propagation if only 1 method is inferred to non-Bottom + if nonbot > 0 && seen == napplicable && !edgecycle && isa(rettype, Type) && sv.params.ipo_constant_propagation # if there's a possibility we could constant-propagate a better result # (hopefully without doing too much work), try to do that now # TODO: it feels like this could be better integrated into abstract_call_method / typeinf_edge - const_rettype = abstract_call_method_with_const_args(f, argtypes, applicable[1]::SimpleVector, sv) + const_rettype = abstract_call_method_with_const_args(f, argtypes, applicable[nonbot]::SimpleVector, sv) if const_rettype ⊑ rettype # use the better result, if it's a refinement of rettype rettype = const_rettype diff --git a/base/tuple.jl b/base/tuple.jl index 518715644f677..ef1eea3f50099 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -57,7 +57,7 @@ end # this allows partial evaluation of bounded sequences of next() calls on tuples, # while reducing to plain next() for arbitrary iterables. -indexed_iterate(t::Tuple, i::Int, state=1) = (@_inline_meta; (t[i], i+1)) +indexed_iterate(t::Tuple, i::Int, state=1) = (@_inline_meta; (getfield(t, i), i+1)) indexed_iterate(a::Array, i::Int, state=1) = (@_inline_meta; (a[i], i+1)) function indexed_iterate(I, i) x = iterate(I) diff --git a/test/compiler/compiler.jl b/test/compiler/compiler.jl index 7ddca137ed2c4..008b05d1de56c 100644 --- a/test/compiler/compiler.jl +++ b/test/compiler/compiler.jl @@ -1990,3 +1990,10 @@ struct VoxelIndices{T <: Integer} end f28641(x::VoxelIndices, f) = getfield(x, f) @test Base.return_types(f28641, (Any,Symbol)) == Any[Tuple] + +# issue #29036 +function f29036(s, i) + val, i = iterate(s, i) + val +end +@test Base.return_types(f29036, (String, Int)) == Any[Char] From 447103c345e05d6fa9037d025ee87724a1137083 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 6 Sep 2018 23:37:03 -0400 Subject: [PATCH 126/166] slightly more efficient lowering of destructuring assignment There is no need to fetch the next state after the last element. (cherry picked from commit 446bc7af363f2170aca71018a727af2463ba3a6b) --- src/julia-syntax.scm | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 8d6a08daae273..323c6b472e2e9 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1916,16 +1916,19 @@ (ssavalue? x)) x (make-ssavalue))) (ini (if (eq? x xx) '() `((= ,xx ,(expand-forms x))))) + (n (length lhss)) (st (gensy))) `(block ,@ini ,.(map (lambda (i lhs) (expand-forms (lower-tuple-assignment - (list lhs st) + (if (= i (- n 1)) + (list lhs) + (list lhs st)) `(call (top indexed_iterate) ,xx ,(+ i 1) ,.(if (eq? i 0) '() `(,st)))))) - (iota (length lhss)) + (iota n) lhss) (unnecessary ,xx)))))) ((typed_hcat) From a2de5273fa5d318d88e57bf7ecc2e7f815d1c5c5 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Mon, 10 Sep 2018 13:37:58 -0500 Subject: [PATCH 127/166] Check world age bounds on candidate ambiguities. Fixes #28899 (#28916) (cherry picked from commit 513db98da448454597dbffbb1f09fd650e423bbd) --- base/compiler/utilities.jl | 2 +- base/errorshow.jl | 2 ++ base/methodshow.jl | 2 +- base/reflection.jl | 2 +- src/dump.c | 3 ++- src/gf.c | 14 ++++++++------ src/jltypes.c | 10 ++++++---- src/julia.h | 1 + src/method.c | 4 +++- src/typemap.c | 2 +- test/reflection.jl | 12 ++++++++++++ 11 files changed, 38 insertions(+), 16 deletions(-) diff --git a/base/compiler/utilities.jl b/base/compiler/utilities.jl index 0edcec83bd038..89f5c0b05fb52 100644 --- a/base/compiler/utilities.jl +++ b/base/compiler/utilities.jl @@ -122,7 +122,7 @@ function retrieve_code_info(linfo::MethodInstance) end function code_for_method(method::Method, @nospecialize(atypes), sparams::SimpleVector, world::UInt, preexisting::Bool=false) - if world < min_world(method) + if world < min_world(method) || world > max_world(method) return nothing end if isdefined(method, :generator) && !isdispatchtuple(atypes) diff --git a/base/errorshow.jl b/base/errorshow.jl index c6c81a02081ba..f9de780cf0446 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -432,6 +432,8 @@ function show_method_candidates(io::IO, ex::MethodError, @nospecialize kwargs=() end if ex.world < min_world(method) print(iob, " (method too new to be called from this world context.)") + elseif ex.world > max_world(method) + print(iob, " (method deleted before this world age.)") end # TODO: indicate if it's in the wrong world push!(lines, (buf, right_matches)) diff --git a/base/methodshow.jl b/base/methodshow.jl index e02101ba533d1..2015a564ac1f8 100644 --- a/base/methodshow.jl +++ b/base/methodshow.jl @@ -76,7 +76,7 @@ end function kwarg_decl(m::Method, kwtype::DataType) sig = rewrap_unionall(Tuple{kwtype, Any, unwrap_unionall(m.sig).parameters...}, m.sig) - kwli = ccall(:jl_methtable_lookup, Any, (Any, Any, UInt), kwtype.name.mt, sig, typemax(UInt)) + kwli = ccall(:jl_methtable_lookup, Any, (Any, Any, UInt), kwtype.name.mt, sig, max_world(m)) if kwli !== nothing kwli = kwli::Method src = uncompressed_ast(kwli) diff --git a/base/reflection.jl b/base/reflection.jl index 2382766b743d0..da407a73c82eb 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -1103,7 +1103,7 @@ has_bottom_parameter(t::TypeVar) = t.ub == Bottom || has_bottom_parameter(t.ub) has_bottom_parameter(::Any) = false min_world(m::Method) = reinterpret(UInt, m.min_world) -max_world(m::Method) = typemax(UInt) +max_world(m::Method) = reinterpret(UInt, m.max_world) min_world(m::Core.MethodInstance) = reinterpret(UInt, m.min_world) max_world(m::Core.MethodInstance) = reinterpret(UInt, m.max_world) diff --git a/src/dump.c b/src/dump.c index e23210b38d762..0e355b87a4c5c 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1647,6 +1647,7 @@ static jl_value_t *jl_deserialize_value_method(jl_serializer_state *s, jl_value_ m->file = (jl_sym_t*)jl_deserialize_value(s, NULL); m->line = read_int32(s->s); m->min_world = jl_world_counter; + m->max_world = ~(size_t)0; m->ambig = jl_deserialize_value(s, (jl_value_t**)&m->ambig); jl_gc_wb(m, m->ambig); m->called = read_int32(s->s); @@ -2992,7 +2993,7 @@ static jl_method_instance_t *jl_recache_method_instance(jl_method_instance_t *li //assert(ti != jl_bottom_type); (void)ti; if (ti == jl_bottom_type) env = jl_emptysvec; // the intersection may fail now if the type system had made an incorrect subtype env in the past - jl_method_instance_t *_new = jl_specializations_get_linfo(m, (jl_value_t*)argtypes, env, jl_world_counter); + jl_method_instance_t *_new = jl_specializations_get_linfo(m, (jl_value_t*)argtypes, env, jl_world_counter < max_world ? jl_world_counter : max_world); _new->max_world = max_world; jl_update_backref_list((jl_value_t*)li, (jl_value_t*)_new, start); return _new; diff --git a/src/gf.c b/src/gf.c index c179563422013..194526ef7c7e7 100644 --- a/src/gf.c +++ b/src/gf.c @@ -148,7 +148,7 @@ static int8_t jl_cachearg_offset(jl_methtable_t *mt) // get or create the MethodInstance for a specialization JL_DLLEXPORT jl_method_instance_t *jl_specializations_get_linfo(jl_method_t *m, jl_value_t *type, jl_svec_t *sparams, size_t world) { - assert(world >= m->min_world && "typemap lookup is corrupted"); + assert(world >= m->min_world && world <= m->max_world && "typemap lookup is corrupted"); JL_LOCK(&m->writelock); jl_typemap_entry_t *sf = jl_typemap_assoc_by_type(m->specializations, type, NULL, /*subtype*/0, /*offs*/0, world, /*max_world_mask*/0); @@ -169,7 +169,7 @@ JL_DLLEXPORT jl_method_instance_t *jl_specializations_get_linfo(jl_method_t *m, li->min_world = world; } if (world == jl_world_counter) { - li->max_world = ~(size_t)0; + li->max_world = m->max_world; } else { li->max_world = world; @@ -358,6 +358,7 @@ JL_DLLEXPORT jl_method_instance_t* jl_set_method_inferred( else { JL_LOCK(&li->def.method->writelock); assert(min_world >= li->def.method->min_world); + assert(max_world <= li->def.method->max_world); int isinferred = jl_is_rettype_inferred(li); if (!isinferred && li->min_world >= min_world && li->max_world <= max_world) { // expand the current (uninferred) entry to cover the full inferred range @@ -955,7 +956,7 @@ static jl_method_instance_t *cache_method( jl_tupletype_t *cachett = tt; jl_svec_t* guardsigs = jl_emptysvec; size_t min_valid = definition->min_world; - size_t max_valid = ~(size_t)0; + size_t max_valid = definition->max_world; if (!cache_with_orig) { // now examine what will happen if we chose to use this sig in the cache temp = ml_matches(mt->defs, 0, compilationsig, -1, 0, world, &min_valid, &max_valid); // TODO: use MAX_UNSPECIALIZED_CONFLICTS? @@ -1501,6 +1502,7 @@ JL_DLLEXPORT void jl_method_table_disable(jl_methtable_t *mt, jl_method_t *metho jl_error("method not in method table"); JL_LOCK(&mt->writelock); // Narrow the world age on the method to make it uncallable + method->max_world = jl_world_counter; methodentry->max_world = jl_world_counter++; // Recompute ambiguities (deleting a more specific method might reveal ambiguities that it previously resolved) check_ambiguous_matches(mt->defs, methodentry, check_disabled_ambiguous_visitor); // TODO: decrease repeated work? @@ -1525,7 +1527,7 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method JL_LOCK(&mt->writelock); jl_typemap_entry_t *newentry = jl_typemap_insert(&mt->defs, (jl_value_t*)mt, (jl_tupletype_t*)type, simpletype, jl_emptysvec, (jl_value_t*)method, 0, &method_defs, - method->min_world, ~(size_t)0, &oldvalue); + method->min_world, method->max_world, &oldvalue); if (oldvalue) { if (oldvalue == (jl_value_t*)method) { // redundant add of same method; no need to do anything @@ -1982,7 +1984,7 @@ JL_DLLEXPORT int jl_is_call_ambiguous(jl_value_t *types, jl_method_t *m) return 0; for (size_t i = 0; i < jl_array_len(m->ambig); i++) { jl_method_t *mambig = (jl_method_t*)jl_array_ptr_ref(m->ambig, i); - if (jl_subtype((jl_value_t*)types, (jl_value_t*)mambig->sig)) + if (mambig->min_world <= jl_world_counter && jl_world_counter <= mambig->max_world && jl_subtype((jl_value_t*)types, (jl_value_t*)mambig->sig)) return 1; } return 0; @@ -1996,7 +1998,7 @@ JL_DLLEXPORT int jl_has_call_ambiguities(jl_value_t *types, jl_method_t *m) return 0; for (size_t i = 0; i < jl_array_len(m->ambig); i++) { jl_method_t *mambig = (jl_method_t*)jl_array_ptr_ref(m->ambig, i); - if (!jl_has_empty_intersection(mambig->sig, types)) + if (mambig->min_world <= jl_world_counter && jl_world_counter <= mambig->max_world && !jl_has_empty_intersection(mambig->sig, types)) return 1; } return 0; diff --git a/src/jltypes.c b/src/jltypes.c index 9a1f6a42b6449..2748cb4467dd9 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -2059,13 +2059,14 @@ void jl_init_types(void) jl_method_type = jl_new_datatype(jl_symbol("Method"), core, jl_any_type, jl_emptysvec, - jl_perm_symsvec(19, + jl_perm_symsvec(20, "name", "module", "file", "line", "sig", "min_world", + "max_world", "ambig", "specializations", "sparam_syms", @@ -2079,13 +2080,14 @@ void jl_init_types(void) "nospecialize", "isva", "pure"), - jl_svec(19, + jl_svec(20, jl_sym_type, jl_module_type, jl_sym_type, jl_int32_type, jl_type_type, jl_long_type, + jl_long_type, jl_any_type, // Union{Array, Nothing} jl_any_type, // TypeMap jl_simplevector_type, @@ -2099,7 +2101,7 @@ void jl_init_types(void) jl_int32_type, jl_bool_type, jl_bool_type), - 0, 1, 9); + 0, 1, 10); jl_method_instance_type = jl_new_datatype(jl_symbol("MethodInstance"), core, @@ -2211,7 +2213,7 @@ void jl_init_types(void) jl_svecset(jl_methtable_type->types, 7, jl_int32_type); // DWORD #endif jl_svecset(jl_methtable_type->types, 8, jl_int32_type); // uint32_t - jl_svecset(jl_method_type->types, 10, jl_method_instance_type); + jl_svecset(jl_method_type->types, 11, jl_method_instance_type); jl_svecset(jl_method_instance_type->types, 11, jl_voidpointer_type); jl_svecset(jl_method_instance_type->types, 12, jl_voidpointer_type); jl_svecset(jl_method_instance_type->types, 13, jl_voidpointer_type); diff --git a/src/julia.h b/src/julia.h index 8916a655ba1a7..48563ac331f33 100644 --- a/src/julia.h +++ b/src/julia.h @@ -264,6 +264,7 @@ typedef struct _jl_method_t { // method's type signature. redundant with TypeMapEntry->specTypes jl_value_t *sig; size_t min_world; + size_t max_world; // list of potentially-ambiguous methods (nothing = none, Vector{Any} of Methods otherwise) jl_value_t *ambig; diff --git a/src/method.c b/src/method.c index 981f917831fa3..223fa4eb4b8e1 100644 --- a/src/method.c +++ b/src/method.c @@ -460,7 +460,7 @@ jl_method_instance_t *jl_get_specialized(jl_method_t *m, jl_value_t *types, jl_s new_linfo->specTypes = types; new_linfo->sparam_vals = sp; new_linfo->min_world = m->min_world; - new_linfo->max_world = ~(size_t)0; + new_linfo->max_world = m->max_world; return new_linfo; } @@ -595,6 +595,7 @@ JL_DLLEXPORT jl_method_t *jl_new_method_uninit(jl_module_t *module) m->nargs = 0; m->traced = 0; m->min_world = 1; + m->max_world = ~(size_t)0; JL_MUTEX_INIT(&m->writelock); return m; } @@ -639,6 +640,7 @@ static jl_method_t *jl_new_method( JL_GC_POP(); m->min_world = ++jl_world_counter; + m->max_world = ~(size_t)0; return m; } diff --git a/src/typemap.c b/src/typemap.c index 03f9ec7564c58..222bf7136490c 100644 --- a/src/typemap.c +++ b/src/typemap.c @@ -743,7 +743,7 @@ jl_typemap_entry_t *jl_typemap_entry_assoc_exact(jl_typemap_entry_t *ml, jl_valu { // some manually-unrolled common special cases while (ml->simplesig == (void*)jl_nothing && ml->guardsigs == jl_emptysvec && ml->isleafsig) { - // use a tight loop for a long as possible + // use a tight loop for as long as possible if (world >= ml->min_world && world <= ml->max_world) { if (n == jl_field_count(ml->sig) && jl_typeof(args[0]) == jl_tparam(ml->sig, 0)) { if (n == 1) diff --git a/test/reflection.jl b/test/reflection.jl index 7c992072fbf79..b1f5fecc9178f 100644 --- a/test/reflection.jl +++ b/test/reflection.jl @@ -775,6 +775,18 @@ typeparam(::Type{T}, a::AbstractArray{T}) where T = 2 @test typeparam(Float64, rand(2)) == 1 @test typeparam(Int, rand(Int, 2)) == 2 +# prior ambiguities (issue #28899) +uambig(::Union{Int,Nothing}) = 1 +uambig(::Union{Float64,Nothing}) = 2 +@test uambig(1) == 1 +@test uambig(1.0) == 2 +@test_throws MethodError uambig(nothing) +m = which(uambig, Tuple{Int}) +Base.delete_method(m) +@test_throws MethodError uambig(1) +@test uambig(1.0) == 2 +@test uambig(nothing) == 2 + end # issue #26267 From b86b4353f16da56dfbd72c2af733f5a7e67c07e7 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Tue, 11 Sep 2018 02:22:06 -0400 Subject: [PATCH 128/166] Some more examples/formatting/xrefs for Distributed docs (#29011) (cherry picked from commit 448bc7de4279ff03f8ba73c846d365a1a58c600c) --- stdlib/Distributed/src/cluster.jl | 86 +++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 9 deletions(-) diff --git a/stdlib/Distributed/src/cluster.jl b/stdlib/Distributed/src/cluster.jl index 49df11b6eef0d..e1d4bae511d91 100644 --- a/stdlib/Distributed/src/cluster.jl +++ b/stdlib/Distributed/src/cluster.jl @@ -720,6 +720,15 @@ const map_del_wrkr = Set{Int}() myid() Get the id of the current process. + +# Examples +```julia-repl +julia> myid() +1 + +julia> remotecall_fetch(() -> myid(), 4) +4 +``` """ myid() = LPROC.id @@ -727,6 +736,17 @@ myid() = LPROC.id nprocs() Get the number of available processes. + +# Examples +```julia-repl +julia> nprocs() +3 + +julia> workers() +5-element Array{Int64,1}: + 2 + 3 +``` """ function nprocs() if myid() == 1 || (PGRP.topology == :all_to_all && !isclusterlazy()) @@ -746,8 +766,19 @@ end """ nworkers() -Get the number of available worker processes. This is one less than `nprocs()`. Equal to +Get the number of available worker processes. This is one less than [`nprocs()`](@ref). Equal to `nprocs()` if `nprocs() == 1`. + +# Examples +```julia-repl +\$ julia -p 5 + +julia> nprocs() +6 + +julia> nworkers() +5 +``` """ function nworkers() n = nprocs() @@ -757,7 +788,18 @@ end """ procs() -Return a list of all process identifiers. +Return a list of all process identifiers, including pid 1 (which is not included by [`workers()`](@ref)). + +# Examples +```julia-repl +\$ julia -p 5 + +julia> procs() +3-element Array{Int64,1}: + 1 + 2 + 3 +``` """ function procs() if myid() == 1 || (PGRP.topology == :all_to_all && !isclusterlazy()) @@ -809,6 +851,16 @@ end workers() Return a list of all worker process identifiers. + +# Examples +```julia-repl +\$ julia -p 5 + +julia> workers() +2-element Array{Int64,1}: + 2 + 3 +``` """ function workers() allp = procs() @@ -832,13 +884,29 @@ Remove the specified workers. Note that only process 1 can add or remove workers. Argument `waitfor` specifies how long to wait for the workers to shut down: - - If unspecified, `rmprocs` will wait until all requested `pids` are removed. - - An `ErrorException` is raised if all workers cannot be terminated before - the requested `waitfor` seconds. - - With a `waitfor` value of 0, the call returns immediately with the workers - scheduled for removal in a different task. The scheduled `Task` object is - returned. The user should call `wait` on the task before invoking any other - parallel calls. + - If unspecified, `rmprocs` will wait until all requested `pids` are removed. + - An [`ErrorException`](@ref) is raised if all workers cannot be terminated before + the requested `waitfor` seconds. + - With a `waitfor` value of 0, the call returns immediately with the workers + scheduled for removal in a different task. The scheduled [`Task`](@ref) object is + returned. The user should call [`wait`](@ref) on the task before invoking any other + parallel calls. + +# Examples +```julia-repl +\$ julia -p 5 + +julia> t = rmprocs(2, 3, waitfor=0) +Task (runnable) @0x0000000107c718d0 + +julia> wait(t) + +julia> workers() +3-element Array{Int64,1}: + 4 + 5 + 6 +``` """ function rmprocs(pids...; waitfor=typemax(Int)) cluster_mgmt_from_master_check() From 843cfe8e56069aa20fc6ff26ac0cf19f7627ba9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Lage?= Date: Tue, 11 Sep 2018 04:08:04 -0300 Subject: [PATCH 129/166] Solving Issue #29101 (#29122) See Issue #29101 (cherry picked from commit e85af88d875a7d496f25ac630e5b6d8fde65002f) --- doc/src/manual/parallel-computing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/parallel-computing.md b/doc/src/manual/parallel-computing.md index d0d291901546d..6f178ff33a9e9 100644 --- a/doc/src/manual/parallel-computing.md +++ b/doc/src/manual/parallel-computing.md @@ -1595,7 +1595,7 @@ requirements for the inbuilt `LocalManager` and `SSHManager`: running the Julia REPL (i.e., the master) with the rest of the cluster on the cloud, say on Amazon EC2. In this case only port 22 needs to be opened at the remote cluster coupled with SSH client authenticated via public key infrastructure (PKI). Authentication credentials can be supplied - via `sshflags`, for example ```sshflags=`-e ` ```. + via `sshflags`, for example ```sshflags=`-i ` ```. In an all-to-all topology (the default), all workers connect to each other via plain TCP sockets. The security policy on the cluster nodes must thus ensure free connectivity between workers for From 76cc5337252b571a3891bd0e77ccddc31ae1e06f Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Tue, 11 Sep 2018 15:36:25 -0400 Subject: [PATCH 130/166] LibGit2: only call shutdown once [fix #28306] (#29121) (cherry picked from commit d8809f14bff44e3dc0d25a0114bcc66af131d882) --- stdlib/LibGit2/src/LibGit2.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/LibGit2/src/LibGit2.jl b/stdlib/LibGit2/src/LibGit2.jl index 133407b9a2ac4..38175f1c3eb7b 100644 --- a/stdlib/LibGit2/src/LibGit2.jl +++ b/stdlib/LibGit2/src/LibGit2.jl @@ -978,7 +978,7 @@ end atexit() do # refcount zero, no objects to be finalized - if Threads.atomic_sub!(REFCOUNT, 1) >= 1 + if Threads.atomic_sub!(REFCOUNT, 1) == 1 ccall((:git_libgit2_shutdown, :libgit2), Cint, ()) end end From 7834046e414d3606f5c3b70267eb08d61a88bac2 Mon Sep 17 00:00:00 2001 From: laborg Date: Tue, 11 Sep 2018 23:21:09 +0200 Subject: [PATCH 131/166] RFC: Iterate over smaller set for setdiff[!](a,b) (#29048) * Iterate over smaller set for setdiff[!] * Add comment and change to integer multiplication (cherry picked from commit 773540d286fc6a5610b12dfb6f0ad5c98c935732) --- base/set.jl | 20 ++++++++++++++++++++ test/sets.jl | 8 ++++++++ 2 files changed, 28 insertions(+) diff --git a/base/set.jl b/base/set.jl index a3e9954d21477..ab64837aa9ce1 100644 --- a/base/set.jl +++ b/base/set.jl @@ -67,6 +67,26 @@ rehash!(s::Set) = (rehash!(s.dict); s) iterate(s::Set, i...) = iterate(KeySet(s.dict), i...) +# In case the size(s) is smaller than size(t) its more efficient to iterate through +# elements of s instead and only delete the ones also contained in t. +# The threshold for this decision boils down to a tradeoff between +# size(s) * cost(in() + delete!()) ≶ size(t) * cost(delete!()) +# Empirical observations on Ints point towards a threshold of 0.8. +# To be on the safe side (e.g. cost(in) >>> cost(delete!) ) a +# conservative threshold of 0.5 was chosen. +function setdiff!(s::Set, t::Set) + if 2 * length(s) < length(t) + for x in s + x in t && delete!(s, x) + end + else + for x in t + delete!(s, x) + end + end + return s +end + """ unique(itr) diff --git a/test/sets.jl b/test/sets.jl index 35155633abb9d..daddf0bc7bb8b 100644 --- a/test/sets.jl +++ b/test/sets.jl @@ -264,6 +264,14 @@ end s = Set([1,2,3,4]) setdiff!(s, Set([2,4,5,6])) @test isequal(s,Set([1,3])) + + # setdiff iterates the shorter set - make sure this algorithm works + sa, sb = Set([1,2,3,4,5,6,7]), Set([2,3,9]) + @test Set([1,4,5,6,7]) == setdiff(sa, sb) !== sa + @test Set([1,4,5,6,7]) == setdiff!(sa, sb) === sa + sa, sb = Set([1,2,3,4,5,6,7]), Set([2,3,9]) + @test Set([9]) == setdiff(sb, sa) !== sb + @test Set([9]) == setdiff!(sb, sa) === sb end @testset "ordering" begin From 35e9ad46843d0ec905c480655d4479530e59a2a1 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Wed, 12 Sep 2018 10:34:02 -0400 Subject: [PATCH 132/166] Fix some signatures and add examples for Random docs (#29119) (cherry picked from commit 3608e5063915e2cc1a4172408fef8ad47c54145c) --- stdlib/Random/src/misc.jl | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/stdlib/Random/src/misc.jl b/stdlib/Random/src/misc.jl index 7b94abb062314..d24fe9c457ccf 100644 --- a/stdlib/Random/src/misc.jl +++ b/stdlib/Random/src/misc.jl @@ -121,10 +121,24 @@ function randsubseq!(r::AbstractRNG, S::AbstractArray, A::AbstractArray, p::Real end """ - randsubseq!(S, A, p) + randsubseq!([rng=GLOBAL_RNG,] S, A, p) Like [`randsubseq`](@ref), but the results are stored in `S` (which is resized as needed). + +# Examples +```jldoctest +julia> rng = MersenneTwister(1234); + +julia> S = Int64[]; + +julia> randsubseq!(rng, S, collect(1:8), 0.3); + +julia> S +2-element Array{Int64,1}: + 7 + 8 +``` """ randsubseq!(S::AbstractArray, A::AbstractArray, p::Real) = randsubseq!(GLOBAL_RNG, S, A, p) @@ -132,12 +146,22 @@ randsubseq(r::AbstractRNG, A::AbstractArray{T}, p::Real) where {T} = randsubseq!(r, T[], A, p) """ - randsubseq(A, p) -> Vector + randsubseq([rng=GLOBAL_RNG,] A, p) -> Vector Return a vector consisting of a random subsequence of the given array `A`, where each element of `A` is included (in order) with independent probability `p`. (Complexity is linear in `p*length(A)`, so this function is efficient even if `p` is small and `A` is large.) Technically, this process is known as "Bernoulli sampling" of `A`. + +# Examples +```jldoctest +julia> rng = MersenneTwister(1234); + +julia> randsubseq(rng, collect(1:8), 0.3) +2-element Array{Int64,1}: + 7 + 8 +``` """ randsubseq(A::AbstractArray, p::Real) = randsubseq(GLOBAL_RNG, A, p) From 1ccc25f04d8ce8c1305ffa0eaeb455fe1eafa909 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Wed, 12 Sep 2018 10:38:11 -0400 Subject: [PATCH 133/166] fix perf regression from not specializing on iterate on tuples (#29133) (cherry picked from commit 2cd1bf85aea0e7cdf8736301d1c9ae4d60de4834) --- base/tuple.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/tuple.jl b/base/tuple.jl index ef1eea3f50099..a1889b79b6faa 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -38,7 +38,7 @@ _setindex(v, i::Integer) = () ## iterating ## -iterate(@nospecialize(t::Tuple), i::Int=1) = 1 <= i <= length(t) ? (@inbounds t[i], i+1) : nothing +iterate(t::Tuple, i::Int=1) = 1 <= i <= length(t) ? (@inbounds t[i], i+1) : nothing keys(@nospecialize t::Tuple) = OneTo(length(t)) From 04643c313a576aa4dc2363ff8bba173662ffe111 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Wed, 12 Sep 2018 10:43:32 -0400 Subject: [PATCH 134/166] fix perf in exp(::Matrix) (#29116) (cherry picked from commit 6acaa10abdda04f8ef0971500ff33b1f24ad6213) --- stdlib/LinearAlgebra/src/dense.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stdlib/LinearAlgebra/src/dense.jl b/stdlib/LinearAlgebra/src/dense.jl index 8a4c9a857f514..c15a1bd0dcfbd 100644 --- a/stdlib/LinearAlgebra/src/dense.jl +++ b/stdlib/LinearAlgebra/src/dense.jl @@ -541,10 +541,10 @@ function exp!(A::StridedMatrix{T}) where T<:BlasFloat A2 = A * A A4 = A2 * A2 A6 = A2 * A4 - U = A * (A6 * (CC[14]*A6 + CC[12]*A4 + CC[10]*A2) + - CC[8]*A6 + CC[6]*A4 + CC[4]*A2 + CC[2]*Inn) - V = A6 * (CC[13]*A6 + CC[11]*A4 + CC[9]*A2) + - CC[7]*A6 + CC[5]*A4 + CC[3]*A2 + CC[1]*Inn + U = A * (A6 * (CC[14].*A6 .+ CC[12].*A4 .+ CC[10].*A2) .+ + CC[8].*A6 .+ CC[6].*A4 .+ CC[4].*A2 .+ CC[2].*Inn) + V = A6 * (CC[13].*A6 .+ CC[11].*A4 .+ CC[9].*A2) .+ + CC[7].*A6 .+ CC[5].*A4 .+ CC[3].*A2 .+ CC[1].*Inn X = V + U LAPACK.gesv!(V-U, X) From 9ee3f881b396302897b40f6987027d40478739ca Mon Sep 17 00:00:00 2001 From: Mark Date: Wed, 12 Sep 2018 15:43:51 +0100 Subject: [PATCH 135/166] Tried to fix the English of the first few paras (#29050) I don't have time to do this whole document, but it could do with an edit by a native English speaker. (cherry picked from commit 592a4745012a3d1b920fb1c95093bc5c7453323d) --- doc/src/manual/parallel-computing.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/src/manual/parallel-computing.md b/doc/src/manual/parallel-computing.md index 6f178ff33a9e9..11bf6669b26ce 100644 --- a/doc/src/manual/parallel-computing.md +++ b/doc/src/manual/parallel-computing.md @@ -7,22 +7,22 @@ the different levels of parallelism offered by Julia. We can divide them in thre 2. Multi-Threading 3. Multi-Core or Distributed Processing -We will first consider Julia [Tasks (aka Coroutines)](@ref man-tasks) and other modules that rely on the Julia runtime library, that allow to suspend and resume computations with full control of inter-`Tasks` communication without having to manually interface with the operative system's scheduler. -Julia also allows to communicate between `Tasks` through operations like [`wait`](@ref) and [`fetch`](@ref). -Communication and data synchronization is managed through [`Channel`](@ref)s, which are the conduit -that allows inter-`Tasks` communication. +We will first consider Julia [Tasks (aka Coroutines)](@ref man-tasks) and other modules that rely on the Julia runtime library, that allow us to suspend and resume computations with full control of inter-`Tasks` communication without having to manually interface with the operating system's scheduler. +Julia also supports communication between `Tasks` through operations like [`wait`](@ref) and [`fetch`](@ref). +Communication and data synchronization is managed through [`Channel`](@ref)s, which are the conduits +that provide inter-`Tasks` communication. Julia also supports experimental multi-threading, where execution is forked and an anonymous function is run across all threads. -Described as a fork-join approach, parallel threads are branched off and they all have to join the Julia main thread to make serial execution continue. +Known as the fork-join approach, parallel threads execute independently, and must ultimately be joined in Julia's main thread to allow serial execution to continue. Multi-threading is supported using the `Base.Threads` module that is still considered experimental, as Julia is -not fully thread-safe yet. In particular segfaults seem to emerge for I\O operations and task switching. -As an un up-to-date reference, keep an eye on [the issue tracker](https://github.com/JuliaLang/julia/issues?q=is%3Aopen+is%3Aissue+label%3Amultithreading). +not yet fully thread-safe. In particular segfaults seem to occur during I\O operations and task switching. +As an up-to-date reference, keep an eye on [the issue tracker](https://github.com/JuliaLang/julia/issues?q=is%3Aopen+is%3Aissue+label%3Amultithreading). Multi-Threading should only be used if you take into consideration global variables, locks and -atomics, so we will explain it later. +atomics, all of which are explained later. -In the end we will present Julia's way to distributed and parallel computing. With scientific computing -in mind, Julia natively implements interfaces to distribute a process through multiple cores or machines. +In the end we will present Julia's approach to distributed and parallel computing. With scientific computing +in mind, Julia natively implements interfaces to distribute a process across multiple cores or machines. Also we will mention useful external packages for distributed programming like `MPI.jl` and `DistributedArrays.jl`. # Coroutines From 21388f9a468d86f85bd84cd40aa95161f024e157 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Wed, 12 Sep 2018 15:35:03 -0400 Subject: [PATCH 136/166] Some xrefs and examples for Distiributed (#29137) (cherry picked from commit c2b61df607f24c0c58076c70dfb4f4a08f0f5a73) --- stdlib/Distributed/src/remotecall.jl | 18 ++++++- stdlib/Distributed/src/workerpool.jl | 76 ++++++++++++++++++++++++---- 2 files changed, 82 insertions(+), 12 deletions(-) diff --git a/stdlib/Distributed/src/remotecall.jl b/stdlib/Distributed/src/remotecall.jl index 052e4416efe4c..2ee8c5437820c 100644 --- a/stdlib/Distributed/src/remotecall.jl +++ b/stdlib/Distributed/src/remotecall.jl @@ -388,6 +388,20 @@ Any remote exceptions are captured in a [`RemoteException`](@ref) and thrown. See also [`fetch`](@ref) and [`remotecall`](@ref). + +# Examples +```julia-repl +\$ julia -p 2 + +julia> remotecall_fetch(sqrt, 2, 4) +2.0 + +julia> remotecall_fetch(sqrt, 2, -4) +ERROR: On worker 2: +DomainError with -4.0: +sqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)). +... +``` """ remotecall_fetch(f, id::Integer, args...; kwargs...) = remotecall_fetch(f, worker_from_id(id), args...; kwargs...) @@ -481,14 +495,14 @@ end """ wait(r::Future) -Wait for a value to become available for the specified future. +Wait for a value to become available for the specified [`Future`](@ref). """ wait(r::Future) = (r.v !== nothing && return r; call_on_owner(wait_ref, r, myid()); r) """ wait(r::RemoteChannel, args...) -Wait for a value to become available on the specified remote channel. +Wait for a value to become available on the specified [`RemoteChannel`](@ref). """ wait(r::RemoteChannel, args...) = (call_on_owner(wait_ref, r, myid(), args...); r) diff --git a/stdlib/Distributed/src/workerpool.jl b/stdlib/Distributed/src/workerpool.jl index e52f546e308a0..c8e3f111a5daa 100644 --- a/stdlib/Distributed/src/workerpool.jl +++ b/stdlib/Distributed/src/workerpool.jl @@ -32,7 +32,15 @@ end """ WorkerPool(workers::Vector{Int}) -Create a WorkerPool from a vector of worker ids. +Create a `WorkerPool` from a vector of worker ids. + +# Examples +```julia-repl +\$ julia -p 3 + +julia> WorkerPool([2, 3]) +WorkerPool(Channel{Int64}(sz_max:9223372036854775807,sz_curr:2), Set([2, 3]), RemoteChannel{Channel{Any}}(1, 1, 6)) +``` """ function WorkerPool(workers::Vector{Int}) pool = WorkerPool() @@ -155,7 +163,20 @@ end """ remotecall(f, pool::AbstractWorkerPool, args...; kwargs...) -> Future -`WorkerPool` variant of `remotecall(f, pid, ....)`. Waits for and takes a free worker from `pool` and performs a `remotecall` on it. +[`WorkerPool`](@ref) variant of `remotecall(f, pid, ....)`. Wait for and take a free worker from `pool` and perform a `remotecall` on it. + +# Examples +```julia-repl +\$ julia -p 3 + +julia> wp = WorkerPool([2, 3]); + +julia> A = rand(3000); + +julia> f = remotecall(maximum, wp, A) +Future(2, 1, 6, nothing) +``` +In this example, the task ran on pid 2, called from pid 1. """ remotecall(f, pool::AbstractWorkerPool, args...; kwargs...) = remotecall_pool(remotecall, f, pool, args...; kwargs...) @@ -163,8 +184,23 @@ remotecall(f, pool::AbstractWorkerPool, args...; kwargs...) = remotecall_pool(re """ remotecall_wait(f, pool::AbstractWorkerPool, args...; kwargs...) -> Future -`WorkerPool` variant of `remotecall_wait(f, pid, ....)`. Waits for and takes a free worker from `pool` and -performs a `remotecall_wait` on it. +[`WorkerPool`](@ref) variant of `remotecall_wait(f, pid, ....)`. Wait for and take a free worker from `pool` and +perform a `remotecall_wait` on it. + +# Examples +```julia-repl +\$ julia -p 3 + +julia> wp = WorkerPool([2, 3]); + +julia> A = rand(3000); + +julia> f = remotecall_wait(maximum, wp, A) +Future(3, 1, 9, nothing) + +julia> fetch(f) +0.9995177101692958 +``` """ remotecall_wait(f, pool::AbstractWorkerPool, args...; kwargs...) = remotecall_pool(remotecall_wait, f, pool, args...; kwargs...) @@ -172,16 +208,28 @@ remotecall_wait(f, pool::AbstractWorkerPool, args...; kwargs...) = remotecall_po """ remotecall_fetch(f, pool::AbstractWorkerPool, args...; kwargs...) -> result -`WorkerPool` variant of `remotecall_fetch(f, pid, ....)`. Waits for and takes a free worker from `pool` and +[`WorkerPool`](@ref) variant of `remotecall_fetch(f, pid, ....)`. Waits for and takes a free worker from `pool` and performs a `remotecall_fetch` on it. + +# Examples +```julia-repl +\$ julia -p 3 + +julia> wp = WorkerPool([2, 3]); + +julia> A = rand(3000); + +julia> remotecall_fetch(maximum, wp, A) +0.9995177101692958 +``` """ remotecall_fetch(f, pool::AbstractWorkerPool, args...; kwargs...) = remotecall_pool(remotecall_fetch, f, pool, args...; kwargs...) """ remote_do(f, pool::AbstractWorkerPool, args...; kwargs...) -> nothing -`WorkerPool` variant of `remote_do(f, pid, ....)`. Waits for and takes a free worker from `pool` and -performs a `remote_do` on it. +[`WorkerPool`](@ref) variant of `remote_do(f, pid, ....)`. Wait for and take a free worker from `pool` and +perform a `remote_do` on it. """ remote_do(f, pool::AbstractWorkerPool, args...; kwargs...) = remotecall_pool(remote_do, f, pool, args...; kwargs...) @@ -190,7 +238,15 @@ const _default_worker_pool = Ref{Union{WorkerPool, Nothing}}(nothing) """ default_worker_pool() -`WorkerPool` containing idle `workers` - used by `remote(f)` and [`pmap`](@ref) (by default). +[`WorkerPool`](@ref) containing idle [`workers`](@ref) - used by `remote(f)` and [`pmap`](@ref) (by default). + +# Examples +```julia-repl +\$ julia -p 3 + +julia> default_worker_pool() +WorkerPool(Channel{Int64}(sz_max:9223372036854775807,sz_curr:3), Set([4, 2, 3]), RemoteChannel{Channel{Any}}(1, 1, 4)) +``` """ function default_worker_pool() # On workers retrieve the default worker pool from the master when accessed @@ -206,10 +262,10 @@ function default_worker_pool() end """ - remote([::AbstractWorkerPool], f) -> Function + remote([p::AbstractWorkerPool], f) -> Function Return an anonymous function that executes function `f` on an available worker -using [`remotecall_fetch`](@ref). +(drawn from [`WorkerPool`](@ref) `p` if provided) using [`remotecall_fetch`](@ref). """ remote(f) = (args...; kwargs...)->remotecall_fetch(f, default_worker_pool(), args...; kwargs...) remote(p::AbstractWorkerPool, f) = (args...; kwargs...)->remotecall_fetch(f, p, args...; kwargs...) From df76714c3f69ca312bb44ab5e98987453a3001eb Mon Sep 17 00:00:00 2001 From: Stephan Hilb Date: Wed, 12 Sep 2018 22:41:56 +0200 Subject: [PATCH 137/166] doc: fix usage of NTuple{T} (#29104) (cherry picked from commit 5e4ca86b832937c44f76b04ee5bd660e778c3f7a) --- doc/src/manual/interfaces.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/src/manual/interfaces.md b/doc/src/manual/interfaces.md index 5b529022997ee..db69514a9f0bf 100644 --- a/doc/src/manual/interfaces.md +++ b/doc/src/manual/interfaces.md @@ -231,11 +231,11 @@ ourselves, we can officially define it as a subtype of an [`AbstractArray`](@ref | `length(A)` | `prod(size(A))` | Number of elements | | `similar(A)` | `similar(A, eltype(A), size(A))` | Return a mutable array with the same shape and element type | | `similar(A, ::Type{S})` | `similar(A, S, size(A))` | Return a mutable array with the same shape and the specified element type | -| `similar(A, dims::NTuple{Int})` | `similar(A, eltype(A), dims)` | Return a mutable array with the same element type and size *dims* | -| `similar(A, ::Type{S}, dims::NTuple{Int})` | `Array{S}(undef, dims)` | Return a mutable array with the specified element type and size | +| `similar(A, dims::Dims)` | `similar(A, eltype(A), dims)` | Return a mutable array with the same element type and size *dims* | +| `similar(A, ::Type{S}, dims::Dims)` | `Array{S}(undef, dims)` | Return a mutable array with the specified element type and size | | **Non-traditional indices** | **Default definition** | **Brief description** | | `axes(A)` | `map(OneTo, size(A))` | Return the `AbstractUnitRange` of valid indices | -| `Base.similar(A, ::Type{S}, inds::NTuple{Ind})` | `similar(A, S, Base.to_shape(inds))` | Return a mutable array with the specified indices `inds` (see below) | +| `Base.similar(A, ::Type{S}, inds)` | `similar(A, S, Base.to_shape(inds))` | Return a mutable array with the specified indices `inds` (see below) | | `Base.similar(T::Union{Type,Function}, inds)` | `T(Base.to_shape(inds))` | Return an array similar to `T` with the specified indices `inds` (see below) | If a type is defined as a subtype of `AbstractArray`, it inherits a very large set of rich behaviors From b5e2c2ff2f563140fa707674ec0789e03951b170 Mon Sep 17 00:00:00 2001 From: Klaus Crusius Date: Wed, 12 Sep 2018 23:35:11 +0200 Subject: [PATCH 138/166] Allow `Iterators.flatten` for empty tuple (#29112) (cherry picked from commit b4c370dd05ac33d0c8c02b440b861e8582d1fc74) --- base/generator.jl | 1 + base/iterators.jl | 1 + test/iterators.jl | 1 + 3 files changed, 3 insertions(+) diff --git a/base/generator.jl b/base/generator.jl index b0f7e32d0b22f..73d0e8a2e3ee2 100644 --- a/base/generator.jl +++ b/base/generator.jl @@ -126,3 +126,4 @@ IteratorEltype(::Type) = HasEltype() # HasEltype is the default IteratorEltype(::Type{Generator{I,T}}) where {I,T} = EltypeUnknown() IteratorEltype(::Type{Any}) = EltypeUnknown() +IteratorEltype(::Type{Union{}}) = EltypeUnknown() diff --git a/base/iterators.jl b/base/iterators.jl index 1564ffa1be9a1..ac3c3ad88d9a3 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -880,6 +880,7 @@ _flatteneltype(I, et) = EltypeUnknown() flatten_iteratorsize(::Union{HasShape, HasLength}, ::Type{<:NTuple{N,Any}}) where {N} = HasLength() flatten_iteratorsize(::Union{HasShape, HasLength}, ::Type{<:Tuple}) = SizeUnknown() flatten_iteratorsize(::Union{HasShape, HasLength}, ::Type{<:Number}) = HasLength() +flatten_iteratorsize(::Union{HasShape, HasLength}, ::Type{Union{}}) = SizeUnknown() flatten_iteratorsize(a, b) = SizeUnknown() _flatten_iteratorsize(sz, ::EltypeUnknown, I) = SizeUnknown() diff --git a/test/iterators.jl b/test/iterators.jl index 5fca4f11b91ad..6e5f88a72cd0d 100644 --- a/test/iterators.jl +++ b/test/iterators.jl @@ -365,6 +365,7 @@ end @test length(flatten(zip(1:3, 4:6))) == 6 @test length(flatten(1:6)) == 6 @test collect(flatten(Any[])) == Any[] +@test collect(flatten(())) == Union{}[] @test_throws ArgumentError length(flatten(NTuple[(1,), ()])) # #16680 @test_throws ArgumentError length(flatten([[1], [1]])) From 5ac0cdc5b40611fe27da38ec3f7f3b042c38ec7f Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 13 Sep 2018 11:23:53 -0400 Subject: [PATCH 139/166] fix #22592, specificity of union compared to a subtype of it (#29139) We considered Union{A,B} more specific than B if A was more specific than B (but not a subtype of it). Clearly, it should not be. (cherry picked from commit 3143d8973f7367f5c5f8ee4e321fd41d89f783f5) --- src/subtype.c | 25 +++++++++++-------------- test/specificity.jl | 11 +++++++++++ 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index 6ecea1840559f..0575a3c830dbf 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -2619,18 +2619,6 @@ static int args_morespecific_fix1(jl_value_t *a, jl_value_t *b, int swap, jl_typ return ret; } -static int partially_morespecific(jl_value_t *a, jl_value_t *b, int invariant, jl_typeenv_t *env) -{ - if (jl_is_uniontype(b)) { - jl_uniontype_t *u = (jl_uniontype_t*)b; - if (type_morespecific_(a, u->a, invariant, env) || - type_morespecific_(a, u->b, invariant, env)) - return 1; - return 0; - } - return type_morespecific_(a, b, invariant, env); -} - static int count_occurs(jl_value_t *t, jl_tvar_t *v) { if (t == (jl_value_t*)v) @@ -2702,9 +2690,18 @@ static int type_morespecific_(jl_value_t *a, jl_value_t *b, int invariant, jl_ty if (jl_is_uniontype(a)) { // Union a is more specific than b if some element of a is more specific than b, but // not vice-versa. + if (sub_msp(b, a, env)) + return 0; jl_uniontype_t *u = (jl_uniontype_t*)a; - return ((partially_morespecific(u->a, b, invariant, env) || partially_morespecific(u->b, b, invariant, env)) && - !partially_morespecific(b, a, invariant, env)); + if (type_morespecific_(u->a, b, invariant, env) || type_morespecific_(u->b, b, invariant, env)) { + if (jl_is_uniontype(b)) { + jl_uniontype_t *v = (jl_uniontype_t*)b; + if (type_morespecific_(v->a, a, invariant, env) || type_morespecific_(v->b, a, invariant, env)) + return 0; + } + return 1; + } + return 0; } if (jl_is_type_type(a) && !invariant) { diff --git a/test/specificity.jl b/test/specificity.jl index f65776a3c4466..bcfd1e5284ee1 100644 --- a/test/specificity.jl +++ b/test/specificity.jl @@ -214,3 +214,14 @@ f27361(::M) where M <: Tuple{3} = nothing @test args_morespecific(Tuple{Type{Any}, Type}, Tuple{Type{T}, Type{T}} where T) @test !args_morespecific(Tuple{Type{Any}, Type}, Tuple{Type{T}, Type{T}} where T<:Union{}) + +# issue #22592 +abstract type Colorant22592{T,N} end +abstract type Color22592{T, N} <: Colorant22592{T,N} end +abstract type AbstractRGB22592{T} <: Color22592{T,3} end +AbstractGray22592{T} = Color22592{T,1} +MathTypes22592{T,C} = Union{AbstractRGB22592{T},AbstractGray22592{T}} +@test !args_morespecific(Tuple{MathTypes22592}, Tuple{AbstractGray22592}) +@test !args_morespecific(Tuple{MathTypes22592, MathTypes22592}, Tuple{AbstractGray22592}) + +@test args_morespecific(Union{Set,Dict,Vector}, Union{Vector,AbstractSet}) From a031553902986858c9257a72633294b3706fab55 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Thu, 13 Sep 2018 21:31:58 +0200 Subject: [PATCH 140/166] =?UTF-8?q?fix=20unsigned=20ndigits=20with=20neg?= =?UTF-8?q?=20base=20for=20`n=20>=20typemax(n)=C3=B72`=20(#29148)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It relies on the fact that `cld(x, b) == -fld(x, -b)` but does the conversion from unsigned to signed before negating the unsigned quotient; since `-b ≥ 2` the quotient always fits in the signed type. (cherry picked from commit 77ec1ec7003dd1ba86770a6be89333259c0e69da) --- base/intfuncs.jl | 3 ++- test/intfuncs.jl | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 2b75f09ac62e7..a6f6ea05efe41 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -440,7 +440,8 @@ function ndigits0znb(x::Integer, b::Integer) return d end -ndigits0znb(x::Unsigned, b::Integer) = ndigits0znb(signed(x), b) +# do first division before conversion with signed here, which can otherwise overflow +ndigits0znb(x::Unsigned, b::Integer) = ndigits0znb(-signed(fld(x, -b)), b) + (x != 0) ndigits0znb(x::Bool, b::Integer) = x % Int # The suffix "pb" stands for "positive base" diff --git a/test/intfuncs.jl b/test/intfuncs.jl index 4ead5b224fad0..b060bc69686b2 100644 --- a/test/intfuncs.jl +++ b/test/intfuncs.jl @@ -139,6 +139,15 @@ end @test iszero([Base.ndigits0z(false, b) for b in [-20:-2;2:20]]) @test all(n -> n == 1, Base.ndigits0z(true, b) for b in [-20:-2;2:20]) @test all(n -> n == 1, ndigits(x, base=b) for b in [-20:-2;2:20] for x in [true, false]) + + # issue #29148 + @test ndigits(typemax(UInt64), base=-2) == ndigits(big(typemax(UInt64)), base=-2) + for T in Base.BitInteger_types + n = rand(T) + b = -rand(2:100) + @test ndigits(n, base=b) == ndigits(big(n), base=b) + end + end @testset "bin/oct/dec/hex/bits" begin @test string(UInt32('3'), base = 2) == "110011" From 811862924df6c1911e0956b56f24f7a8ba931f9f Mon Sep 17 00:00:00 2001 From: cormullion Date: Fri, 14 Sep 2018 14:22:39 +0100 Subject: [PATCH 141/166] fixed some typos (#29164) (cherry picked from commit cda41aebb35eb12a806c586ebad57a20f1cab648) --- base/docs/basedocs.jl | 2 +- base/logging.jl | 2 +- doc/src/manual/arrays.md | 4 ++-- doc/src/manual/documentation.md | 6 +++--- stdlib/Dates/src/query.jl | 2 +- stdlib/LinearAlgebra/src/triangular.jl | 4 ++-- stdlib/Pkg/docs/src/index.md | 4 ++-- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 4c12bf68d80b5..f1cf823457985 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -857,7 +857,7 @@ ErrorException WrappedException(msg) Generic type for `Exception`s wrapping another `Exception`, such as `LoadError` and -`InitError`. Those exceptions contain information about the the root cause of an +`InitError`. Those exceptions contain information about the root cause of an exception. Subtypes define a field `error` containing the causing `Exception`. """ Core.WrappedException diff --git a/base/logging.jl b/base/logging.jl index c3570469a90fb..9034460a4dfe2 100644 --- a/base/logging.jl +++ b/base/logging.jl @@ -496,7 +496,7 @@ with_logger(f::Function, logger::AbstractLogger) = with_logstate(f, LogState(log current_logger() Return the logger for the current task, or the global logger if none is -is attached to the task. +attached to the task. """ current_logger() = current_logstate().logger diff --git a/doc/src/manual/arrays.md b/doc/src/manual/arrays.md index 4b4c4be24a7ac..d209686d1532c 100644 --- a/doc/src/manual/arrays.md +++ b/doc/src/manual/arrays.md @@ -777,7 +777,7 @@ julia> string.(1:3, ". ", ["First", "Second", "Third"]) ## Implementation -The base array type in Julia is the abstract type [`AbstractArray{T,N}`](@ref). It is parametrized by +The base array type in Julia is the abstract type [`AbstractArray{T,N}`](@ref). It is parameterized by the number of dimensions `N` and the element type `T`. [`AbstractVector`](@ref) and [`AbstractMatrix`](@ref) are aliases for the 1-d and 2-d cases. Operations on `AbstractArray` objects are defined using higher level operators and functions, in a way that is independent of the underlying storage. These operations @@ -828,7 +828,7 @@ index of dimension `k` by `1` should increase the index `i` of [`getindex(A,i)`] [`stride(A,k)`](@ref). If a pointer conversion method [`Base.unsafe_convert(Ptr{T}, A)`](@ref) is provided, the memory layout must correspond in the same way to these strides. `DenseArray` is a very specific example of a strided array where the elements are arranged contiguously, thus it -provides its subtypes with the approporiate definition of `strides`. More concrete examples +provides its subtypes with the appropriate definition of `strides`. More concrete examples can be found within the [interface guide for strided arrays](@ref man-interface-strided-arrays). [`StridedVector`](@ref) and [`StridedMatrix`](@ref) are convenient aliases for many of the builtin array types that are considered strided arrays, allowing them to dispatch to select specialized implementations that diff --git a/doc/src/manual/documentation.md b/doc/src/manual/documentation.md index 195df3eae514c..41ac5e44f4951 100644 --- a/doc/src/manual/documentation.md +++ b/doc/src/manual/documentation.md @@ -181,7 +181,7 @@ As in the example above, we recommend following some simple conventions when wri 9. Respect the line length limit used in the surrounding code. Docstrings are edited using the same tools as code. Therefore, the same conventions should apply. - It it advised to add line breaks after 92 characters. + It is advised to add line breaks after 92 characters. 6. Provide information allowing custom types to implement the function in an `# Implementation` section. These implementation details intended for developers rather than users, explaining e.g. which functions should be overridden and which functions @@ -568,7 +568,7 @@ A paragraph containing a **bold** word. Surround words with one asterisk, `*`, to display the enclosed text in italics. ``` -A paragraph containing an *emphasised* word. +A paragraph containing an *emphasized* word. ``` #### Literals @@ -665,7 +665,7 @@ in the [Inline elements](@ref) section above, with one or more blank lines above ``` This is a paragraph. -And this is *another* one containing some emphasised text. +And this is *another* one containing some emphasized text. A new line, but still part of the same paragraph. ``` diff --git a/stdlib/Dates/src/query.jl b/stdlib/Dates/src/query.jl index 88806673cc157..cbad78689e62c 100644 --- a/stdlib/Dates/src/query.jl +++ b/stdlib/Dates/src/query.jl @@ -187,7 +187,7 @@ julia> Dates.dayofweekofmonth(Date("2000-02-08")) julia> Dates.dayofweekofmonth(Date("2000-02-15")) 3 -```` +``` """ function dayofweekofmonth(dt::TimeType) d = day(dt) diff --git a/stdlib/LinearAlgebra/src/triangular.jl b/stdlib/LinearAlgebra/src/triangular.jl index ca5f4d2e0e014..93f54f7ee5a2f 100644 --- a/stdlib/LinearAlgebra/src/triangular.jl +++ b/stdlib/LinearAlgebra/src/triangular.jl @@ -58,7 +58,7 @@ UpperTriangular(U::LowerTriangular) = throw(ArgumentError( """ LowerTriangular(A::AbstractMatrix) -Construct a `LowerTriangular` view of the the matrix `A`. +Construct a `LowerTriangular` view of the matrix `A`. # Examples ```jldoctest @@ -79,7 +79,7 @@ LowerTriangular """ UpperTriangular(A::AbstractMatrix) -Construct an `UpperTriangular` view of the the matrix `A`. +Construct an `UpperTriangular` view of the matrix `A`. # Examples ```jldoctest diff --git a/stdlib/Pkg/docs/src/index.md b/stdlib/Pkg/docs/src/index.md index 53eada6779862..3206a829ae97c 100644 --- a/stdlib/Pkg/docs/src/index.md +++ b/stdlib/Pkg/docs/src/index.md @@ -81,7 +81,7 @@ identify the package in projects that depend on it. **Application:** a project which provides standalone functionality not intended to be reused by other Julia projects. For example a web application or a -commmand-line utility, or simulation/analytics code accompanying a scientific paper. +command-line utility, or simulation/analytics code accompanying a scientific paper. An application may have a UUID but does not need one. An application may also provide global configuration options for packages it depends on. Packages, on the other hand, may not provide global configuration @@ -427,7 +427,7 @@ Note the pin symbol `⚲` showing that the package is pinned. Removing the pin i ### Testing packages -The tests for a package can be run using `test`command: +The tests for a package can be run using `test` command: ``` (v1.0) pkg> test Example From e174444c8a9898ad654080a18785de6a928a7e0b Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 14 Sep 2018 15:54:01 -0400 Subject: [PATCH 142/166] fix #25474, support more forms in edit, which, etc. macros (#29159) (cherry picked from commit cb269aa042c38e3afa487e7bad01a5bcfd43fe65) --- stdlib/InteractiveUtils/src/macros.jl | 48 +++++++++++++++++++----- stdlib/InteractiveUtils/test/runtests.jl | 25 ++++++------ 2 files changed, 52 insertions(+), 21 deletions(-) diff --git a/stdlib/InteractiveUtils/src/macros.jl b/stdlib/InteractiveUtils/src/macros.jl index 1d13e7020a3e1..6415bb68c64af 100644 --- a/stdlib/InteractiveUtils/src/macros.jl +++ b/stdlib/InteractiveUtils/src/macros.jl @@ -15,22 +15,50 @@ function gen_call_with_extracted_types(__module__, fcn, ex0) $(fcn)(Core.kwfunc(arg1), Tuple{typeof(kwargs), Core.Typeof(arg1), map(Core.Typeof, args)...}) end - elseif ex0.head == :call + elseif ex0.head === :call return Expr(:call, fcn, esc(ex0.args[1]), Expr(:call, typesof, map(esc, ex0.args[2:end])...)) - elseif ex0.head == :(=) && length(ex0.args) == 2 && ex0.args[1].head == :(.) - return Expr(:call, fcn, Base.setproperty!, - Expr(:call, typesof, map(esc, [ex0.args[1].args..., ex0.args[2]])...)) + elseif ex0.head === :(=) && length(ex0.args) == 2 + lhs, rhs = ex0.args + if isa(lhs, Expr) + if lhs.head === :(.) + return Expr(:call, fcn, Base.setproperty!, + Expr(:call, typesof, map(esc, lhs.args)..., esc(rhs))) + elseif lhs.head === :ref + return Expr(:call, fcn, Base.setindex!, + Expr(:call, typesof, esc(lhs.args[1]), esc(rhs), map(esc, lhs.args[2:end])...)) + end + end + elseif ex0.head === :vcat || ex0.head === :typed_vcat + if ex0.head === :vcat + f, hf = Base.vcat, Base.hvcat + args = ex0.args + else + f, hf = Base.typed_vcat, Base.typed_hvcat + args = ex0.args[2:end] + end + if any(a->isa(a,Expr) && a.head === :row, args) + rows = Any[ (isa(x,Expr) && x.head === :row ? x.args : Any[x]) for x in args ] + lens = map(length, rows) + return Expr(:call, fcn, hf, + Expr(:call, typesof, + (ex0.head === :vcat ? [] : Any[esc(ex0.args[1])])..., + Expr(:tuple, lens...), + map(esc, vcat(rows...))...)) + else + return Expr(:call, fcn, f, + Expr(:call, typesof, map(esc, ex0.args)...)) + end else - for (head, f) in (:ref => Base.getindex, :vcat => Base.vcat, :hcat => Base.hcat, :(.) => Base.getproperty, :vect => Base.vect) - if ex0.head == head + for (head, f) in (:ref => Base.getindex, :hcat => Base.hcat, :(.) => Base.getproperty, :vect => Base.vect, Symbol("'") => Base.adjoint, :typed_hcat => Base.typed_hcat, :string => string) + if ex0.head === head return Expr(:call, fcn, f, Expr(:call, typesof, map(esc, ex0.args)...)) end end end end - if isa(ex0, Expr) && ex0.head == :macrocall # Make @edit @time 1+2 edit the macro by using the types of the *expressions* + if isa(ex0, Expr) && ex0.head === :macrocall # Make @edit @time 1+2 edit the macro by using the types of the *expressions* return Expr(:call, fcn, esc(ex0.args[1]), Tuple{#=__source__=#LineNumberNode, #=__module__=#Module, Any[ Core.Typeof(a) for a in ex0.args[3:end] ]...}) end @@ -40,8 +68,8 @@ function gen_call_with_extracted_types(__module__, fcn, ex0) end exret = Expr(:none) - if ex.head == :call - if any(e->(isa(e, Expr) && e.head==:(...)), ex0.args) && + if ex.head === :call + if any(e->(isa(e, Expr) && e.head === :(...)), ex0.args) && (ex.args[1] === GlobalRef(Core,:_apply) || ex.args[1] === GlobalRef(Base,:_apply)) # check for splatting @@ -53,7 +81,7 @@ function gen_call_with_extracted_types(__module__, fcn, ex0) Expr(:call, typesof, map(esc, ex.args[2:end])...)) end end - if ex.head == :thunk || exret.head == :none + if ex.head === :thunk || exret.head === :none exret = Expr(:call, :error, "expression is not a function call, " * "or is too complex for @$fcn to analyze; " * "break it down to simpler parts if possible") diff --git a/stdlib/InteractiveUtils/test/runtests.jl b/stdlib/InteractiveUtils/test/runtests.jl index 14a5068c36c6d..3e522ce24a54e 100644 --- a/stdlib/InteractiveUtils/test/runtests.jl +++ b/stdlib/InteractiveUtils/test/runtests.jl @@ -198,20 +198,23 @@ const curmod_str = curmod === Main ? "Main" : join(curmod_name, ".") # issue #13264 @test (@which vcat(1...)).name == :vcat -# PR #28122 +# PR #28122, issue #25474 @test (@which [1][1]).name === :getindex -@test (@which [1 2]).name == :hcat -@test (@which [1; 2]).name == :vcat -@test (@which [1]).name == :vect +@test (@which [1][1] = 2).name === :setindex! +@test (@which [1]).name === :vect +@test (@which [1 2]).name === :hcat +@test (@which [1; 2]).name === :vcat +@test (@which Int[1 2]).name === :typed_hcat +@test (@which Int[1; 2]).name === :typed_vcat +@test (@which [1 2;3 4]).name === :hvcat +@test (@which Int[1 2;3 4]).name === :typed_hvcat # issue #13464 -let t13464 = "hey there sailor" - try - @which t13464[1,1] = (1.0,true) - error("unexpected") - catch err13464 - @test startswith(err13464.msg, "expression is not a function call, or is too complex") - end +try + @which x = 1 + error("unexpected") +catch err13464 + @test startswith(err13464.msg, "expression is not a function call, or is too complex") end module MacroTest From 499fb01ebd9b0fafa7978c6818d410b8763af99b Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Fri, 14 Sep 2018 17:07:50 -0400 Subject: [PATCH 143/166] Xrefs and a few examples for math stuff (#29150) (cherry picked from commit 02aa9bbc258a380b5c9fbe2f2d3276a90a72abca) --- base/math.jl | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/base/math.jl b/base/math.jl index 2d58744d61b0d..0793e4996792f 100644 --- a/base/math.jl +++ b/base/math.jl @@ -393,6 +393,19 @@ atanh(x::Number) Compute the natural logarithm of `x`. Throws [`DomainError`](@ref) for negative [`Real`](@ref) arguments. Use complex negative arguments to obtain complex results. + +# Examples +```jldoctest; filter = r"Stacktrace:(\\n \\[[0-9]+\\].*)*" +julia> log(2) +0.6931471805599453 + +julia> log(-3) +ERROR: DomainError with -3.0: +log will only return a complex result if called with a complex argument. Try log(Complex(x)). +Stacktrace: + [1] throw_complex_domainerror(::Symbol, ::Float64) at ./math.jl:31 +[...] +``` """ log(x::Number) @@ -709,18 +722,18 @@ according to the rounding mode `r`. In other words, the quantity without any intermediate rounding. - if `r == RoundNearest`, then the result is exact, and in the interval - ``[-|y|/2, |y|/2]``. + ``[-|y|/2, |y|/2]``. See also [`RoundNearest`](@ref). - if `r == RoundToZero` (default), then the result is exact, and in the interval - ``[0, |y|)`` if `x` is positive, or ``(-|y|, 0]`` otherwise. + ``[0, |y|)`` if `x` is positive, or ``(-|y|, 0]`` otherwise. See also [`RoundToZero`](@ref). - if `r == RoundDown`, then the result is in the interval ``[0, y)`` if `y` is positive, or ``(y, 0]`` otherwise. The result may not be exact if `x` and `y` have different signs, and - `abs(x) < abs(y)`. + `abs(x) < abs(y)`. See also[`RoundDown`](@ref). - if `r == RoundUp`, then the result is in the interval `(-y,0]` if `y` is positive, or `[0,-y)` otherwise. The result may not be exact if `x` and `y` have the same sign, and - `abs(x) < abs(y)`. + `abs(x) < abs(y)`. See also [`RoundUp`](@ref). """ rem(x, y, ::RoundingMode{:ToZero}) = rem(x,y) @@ -820,14 +833,15 @@ without any intermediate rounding. This internally uses a high precision approxi 2π, and so will give a more accurate result than `rem(x,2π,r)` - if `r == RoundNearest`, then the result is in the interval ``[-π, π]``. This will generally - be the most accurate result. + be the most accurate result. See also [`RoundNearest`](@ref). - if `r == RoundToZero`, then the result is in the interval ``[0, 2π]`` if `x` is positive,. - or ``[-2π, 0]`` otherwise. + or ``[-2π, 0]`` otherwise. See also [`RoundToZero`](@ref). - if `r == RoundDown`, then the result is in the interval ``[0, 2π]``. - + See also [`RoundDown`](@ref). - if `r == RoundUp`, then the result is in the interval ``[-2π, 0]``. + See also [`RoundUp`](@ref). # Examples ```jldoctest From b57c1f110d3d723f2c365ec8319036afb412ecfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hamza=20Yusuf=20=C3=87ak=C4=B1r?= <32282514+hycakir@users.noreply.github.com> Date: Sat, 15 Sep 2018 15:35:30 +0300 Subject: [PATCH 144/166] Add `undef` to Vector allocations (#29184) Without the `undef` initializer, the corresponding samples give error for julia version >= 1.0. (cherry picked from commit e2c98780e211c7b0887751b7eb2b7a141c2fd5e8) --- doc/src/manual/calling-c-and-fortran-code.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/src/manual/calling-c-and-fortran-code.md b/doc/src/manual/calling-c-and-fortran-code.md index dfd82b475fb42..6155952a813a4 100644 --- a/doc/src/manual/calling-c-and-fortran-code.md +++ b/doc/src/manual/calling-c-and-fortran-code.md @@ -130,7 +130,7 @@ Here is a slightly more complex example that discovers the local machine's hostn ```julia function gethostname() - hostname = Vector{UInt8}(128) + hostname = Vector{UInt8}(undef, 128) ccall((:gethostname, "libc"), Int32, (Ptr{UInt8}, Csize_t), hostname, sizeof(hostname)) @@ -820,7 +820,7 @@ function sf_bessel_Jn_array(nmin::Integer, nmax::Integer, x::Real) if nmax < nmin throw(DomainError()) end - result_array = Vector{Cdouble}(nmax - nmin + 1) + result_array = Vector{Cdouble}(undef, nmax - nmin + 1) errorcode = ccall( (:gsl_sf_bessel_Jn_array, :libgsl), # name of C function and library Cint, # output type @@ -973,7 +973,7 @@ Other supported conventions are: `stdcall`, `cdecl`, `fastcall`, and `thiscall` signature for Windows: ```julia -hn = Vector{UInt8}(256) +hn = Vector{UInt8}(undef, 256) err = ccall(:gethostname, stdcall, Int32, (Ptr{UInt8}, UInt32), hn, length(hn)) ``` From 3212800fe9a05b8dad93def8f66097b400262ac0 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 17 Sep 2018 11:03:43 -0400 Subject: [PATCH 145/166] fix #28481, faster reading of primitive types from IOStream and IOBuffer (#29186) (cherry picked from commit c0afddf640bc487d8c627d8a078bc276c86fda5a) --- base/iobuffer.jl | 15 +++++++++++++++ base/iostream.jl | 4 ++++ 2 files changed, 19 insertions(+) diff --git a/base/iobuffer.jl b/base/iobuffer.jl index b3efe5076c1ac..dec5735d2ed3b 100644 --- a/base/iobuffer.jl +++ b/base/iobuffer.jl @@ -167,6 +167,21 @@ function unsafe_read(from::GenericIOBuffer, p::Ptr{UInt8}, nb::UInt) nothing end +function read(from::GenericIOBuffer, T::Union{Type{Int16},Type{UInt16},Type{Int32},Type{UInt32},Type{Int64},Type{UInt64},Type{Int128},Type{UInt128},Type{Float16},Type{Float32},Type{Float64}}) + from.readable || throw(ArgumentError("read failed, IOBuffer is not readable")) + avail = bytesavailable(from) + nb = sizeof(T) + if nb > avail + throw(EOFError()) + end + GC.@preserve from begin + ptr::Ptr{T} = pointer(from.data, from.ptr) + x = unsafe_load(ptr) + end + from.ptr += nb + return x +end + function read_sub(from::GenericIOBuffer, a::AbstractArray{T}, offs, nel) where T @assert !has_offset_axes(a) from.readable || throw(ArgumentError("read failed, IOBuffer is not readable")) diff --git a/base/iostream.jl b/base/iostream.jl index 8454a1e330175..0f9ef99b146e1 100644 --- a/base/iostream.jl +++ b/base/iostream.jl @@ -401,6 +401,10 @@ if ENDIAN_BOM == 0x04030201 function read(s::IOStream, T::Union{Type{Int16},Type{UInt16},Type{Int32},Type{UInt32},Type{Int64},Type{UInt64}}) return ccall(:jl_ios_get_nbyte_int, UInt64, (Ptr{Cvoid}, Csize_t), s.ios, sizeof(T)) % T end + +read(s::IOStream, ::Type{Float16}) = reinterpret(Float16, read(s, Int16)) +read(s::IOStream, ::Type{Float32}) = reinterpret(Float32, read(s, Int32)) +read(s::IOStream, ::Type{Float64}) = reinterpret(Float64, read(s, Int64)) end function unsafe_read(s::IOStream, p::Ptr{UInt8}, nb::UInt) From f95275462e4b6448c55df35647caf75475f3a721 Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Thu, 13 Sep 2018 16:44:51 -0500 Subject: [PATCH 146/166] Improve support for constructing zero-step float ranges (#29056) * Improve support for constructing zero-step float ranges Fixes `0.0 * (1:4)`, for example. From https://github.com/JuliaLang/julia/issues/29052#issuecomment-418825887 * simplify (cherry picked from commit 26b6a5811c464bd66a371ddb341df140c677a2a3) --- base/twiceprecision.jl | 2 +- test/ranges.jl | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/base/twiceprecision.jl b/base/twiceprecision.jl index e80c87c2eb8e5..c2be8f53dfa24 100644 --- a/base/twiceprecision.jl +++ b/base/twiceprecision.jl @@ -357,7 +357,7 @@ StepRangeLen(ref::TwicePrecision{T}, step::TwicePrecision{T}, # Construct range for rational start=start_n/den, step=step_n/den function floatrange(::Type{T}, start_n::Integer, step_n::Integer, len::Integer, den::Integer) where T - if len < 2 + if len < 2 || step_n == 0 return steprangelen_hp(T, (start_n, den), (step_n, den), 0, Int(len), 1) end # index of smallest-magnitude value diff --git a/test/ranges.jl b/test/ranges.jl index ad720f7a2553f..cfb41a477ebef 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -1372,6 +1372,40 @@ end # module NonStandardIntegerRangeTest end end +@testset "constant-valued ranges (issues #10391 and #29052)" begin + for r in ((1:4), (1:1:4), (1.0:4.0)) + if eltype(r) === Int + @test_broken @inferred(0 * r) == [0.0, 0.0, 0.0, 0.0] + @test_broken @inferred(0 .* r) == [0.0, 0.0, 0.0, 0.0] + @test_broken @inferred(r + (4:-1:1)) == [5.0, 5.0, 5.0, 5.0] + @test_broken @inferred(r .+ (4:-1:1)) == [5.0, 5.0, 5.0, 5.0] + else + @test @inferred(0 * r) == [0.0, 0.0, 0.0, 0.0] + @test @inferred(0 .* r) == [0.0, 0.0, 0.0, 0.0] + @test @inferred(r + (4:-1:1)) == [5.0, 5.0, 5.0, 5.0] + @test @inferred(r .+ (4:-1:1)) == [5.0, 5.0, 5.0, 5.0] + end + @test @inferred(r .+ (4.0:-1:1)) == [5.0, 5.0, 5.0, 5.0] + @test @inferred(0.0 * r) == [0.0, 0.0, 0.0, 0.0] + @test @inferred(0.0 .* r) == [0.0, 0.0, 0.0, 0.0] + @test @inferred(r / Inf) == [0.0, 0.0, 0.0, 0.0] + @test @inferred(r ./ Inf) == [0.0, 0.0, 0.0, 0.0] + end + + @test_broken @inferred(range(0, step=0, length=4)) == [0, 0, 0, 0] + @test @inferred(range(0, stop=0, length=4)) == [0, 0, 0, 0] + @test @inferred(range(0.0, step=0.0, length=4)) == [0.0, 0.0, 0.0, 0.0] + @test @inferred(range(0.0, stop=0.0, length=4)) == [0.0, 0.0, 0.0, 0.0] + @test @inferred(range(0, step=0.0, length=4)) == [0.0, 0.0, 0.0, 0.0] + @test @inferred(range(0.0, step=0, length=4)) == [0.0, 0.0, 0.0, 0.0] + @test @inferred(range(0, stop=0.0, length=4)) == [0.0, 0.0, 0.0, 0.0] + @test @inferred(range(0.0, stop=0, length=4)) == [0.0, 0.0, 0.0, 0.0] + + z4 = 0.0 * (1:4) + @test @inferred(z4 .+ (1:4)) === 1.0:1.0:4.0 + @test @inferred(z4 .+ z4) === z4 +end + @testset "allocation of TwicePrecision call" begin 0:286.493442:360 0:286:360 From 6c2eb8ac24371faf0e2d7ea41743bd6a915d200a Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 14 Sep 2018 15:53:06 -0400 Subject: [PATCH 147/166] fix #29145, error for `new{}` with incomplete type (#29154) (cherry picked from commit c3660f7188b773fc349c5f770202732d71f7abd6) --- src/datatype.c | 15 ++++++++++++--- src/interpreter.c | 18 ++++++------------ test/core.jl | 8 ++++++++ 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/datatype.c b/src/datatype.c index 63069f3675854..908a9a457d05b 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -770,7 +770,16 @@ JL_DLLEXPORT jl_value_t *jl_new_structv(jl_datatype_t *type, jl_value_t **args, uint32_t na) { jl_ptls_t ptls = jl_get_ptls_states(); - if (type->instance != NULL) return type->instance; + if (type->instance != NULL) { + for (size_t i = 0; i < na; i++) { + jl_value_t *ft = jl_field_type(type, i); + if (!jl_isa(args[i], ft)) + jl_type_error("new", ft, args[i]); + } + return type->instance; + } + if (type->layout == NULL) + jl_type_error("new", (jl_value_t*)jl_datatype_type, (jl_value_t*)type); size_t nf = jl_datatype_nfields(type); jl_value_t *jv = jl_gc_alloc(ptls, jl_datatype_size(type), type); JL_GC_PUSH1(&jv); @@ -783,8 +792,8 @@ JL_DLLEXPORT jl_value_t *jl_new_structv(jl_datatype_t *type, jl_value_t **args, for(size_t i=na; i < nf; i++) { if (jl_field_isptr(type, i)) { *(jl_value_t**)((char*)jl_data_ptr(jv)+jl_field_offset(type,i)) = NULL; - - } else { + } + else { jl_value_t *ft = jl_field_type(type, i); if (jl_is_uniontype(ft)) { uint8_t *psel = &((uint8_t *)jv)[jl_field_offset(type, i) + jl_field_size(type, i) - 1]; diff --git a/src/interpreter.c b/src/interpreter.c index 61d803cbf043a..feb0bbbe168a4 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -477,18 +477,12 @@ SECT_INTERP static jl_value_t *eval_value(jl_value_t *e, interpreter_state *s) return jl_nothing; } else if (head == new_sym) { - jl_value_t *thetype = eval_value(args[0], s); - jl_value_t *v=NULL, *fldv=NULL; - JL_GC_PUSH3(&thetype, &v, &fldv); - assert(jl_is_structtype(thetype)); - v = jl_new_struct_uninit((jl_datatype_t*)thetype); - for (size_t i = 1; i < nargs; i++) { - jl_value_t *ft = jl_field_type(thetype, i - 1); - fldv = eval_value(args[i], s); - if (!jl_isa(fldv, ft)) - jl_type_error("new", ft, fldv); - jl_set_nth_field(v, i - 1, fldv); - } + jl_value_t **argv; + JL_GC_PUSHARGS(argv, nargs); + for (size_t i = 0; i < nargs; i++) + argv[i] = eval_value(args[i], s); + assert(jl_is_structtype(argv[0])); + jl_value_t *v = jl_new_structv((jl_datatype_t*)argv[0], &argv[1], nargs - 1); JL_GC_POP(); return v; } diff --git a/test/core.jl b/test/core.jl index ff9282a243b40..f1e4112c86677 100644 --- a/test/core.jl +++ b/test/core.jl @@ -6702,3 +6702,11 @@ end @test_throws ErrorException Array{Int, 2}(undef, 0, -10) @test_throws ErrorException Array{Int, 2}(undef, -10, 0) @test_throws ErrorException Array{Int, 2}(undef, -1, -1) + +# issue #29145 +struct T29145{A,B} + function T29145() + new{S,Ref{S}}() where S + end +end +@test_throws TypeError T29145() From 65278e4c0cdbdf857d8b5dd66ea2029946067d98 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 17 Sep 2018 11:05:47 -0400 Subject: [PATCH 148/166] fix #29175, invalid lowered IR from repeating code for declared types (#29194) (cherry picked from commit 3255f2834c8f6eed00eb3f61cd8a05125ea30c68) --- src/julia-syntax.scm | 31 ++++++++++++++++++++++++++++--- test/core.jl | 9 +++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 323c6b472e2e9..be21b395c0338 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -2750,12 +2750,37 @@ f(x) = yt(x) ,(delete-duplicates (append (lam:sp lam) capt-sp))) ,body))) +;; renumber ssavalues assigned in an expr, allowing it to be repeated +(define (renumber-assigned-ssavalues e) + (let ((vals (expr-find-all (lambda (x) (and (assignment? x) (ssavalue? (cadr x)))) + e + cadadr))) + (if (null? vals) + e + (let ((repl (table))) + (for-each (lambda (id) (put! repl id (make-ssavalue))) + vals) + (let do-replace ((x e)) + (if (or (atom? x) (quoted? x)) + x + (if (eq? (car x) 'ssavalue) + (or (get repl (cadr x) #f) x) + (cons (car x) + (map do-replace (cdr x)))))))))) + (define (convert-for-type-decl rhs t) (if (equal? t '(core Any)) rhs - `(call (core typeassert) - (call (top convert) ,t ,rhs) - ,t))) + (let* ((temp (if (or (atom? t) (ssavalue? t) (quoted? t)) + #f + (make-ssavalue))) + (ty (or temp t)) + (ex `(call (core typeassert) + (call (top convert) ,ty ,rhs) + ,ty))) + (if temp + `(block (= ,temp ,(renumber-assigned-ssavalues t)) ,ex) + ex)))) ;; convert assignment to a closed variable to a setfield! call. ;; while we're at it, generate `convert` calls for variables with diff --git a/test/core.jl b/test/core.jl index f1e4112c86677..be7876b9b2bb9 100644 --- a/test/core.jl +++ b/test/core.jl @@ -6710,3 +6710,12 @@ struct T29145{A,B} end end @test_throws TypeError T29145() + +# issue #29175 +function f29175(tuple::T) where {T<:Tuple} + prefix::Tuple{T.parameters[1:end-1]...} = tuple[1:length(T.parameters)-1] + x = prefix + prefix = x # force another conversion to declared type + return prefix +end +@test f29175((1,2,3)) === (1,2) From 6b715cd79fb37b0977242f38d4f03763c1c28f3e Mon Sep 17 00:00:00 2001 From: sunoru Date: Tue, 4 Sep 2018 10:25:46 -0400 Subject: [PATCH 149/166] Fix the statements for checking repeat in packages' UUID. (cherry picked from commit d3a1bfa7c85cc491c8cf57d3789f20886fd12cab) (cherry picked from commit 20efc39707e9859b8c8c999c8dc5b33016b5a9c1) (cherry picked from commit 3d4426a2bd240d392bc2d20ece92a09d737fa80d) --- stdlib/Pkg/src/Types.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/Pkg/src/Types.jl b/stdlib/Pkg/src/Types.jl index 0b989386b0458..284993bacb9df 100644 --- a/stdlib/Pkg/src/Types.jl +++ b/stdlib/Pkg/src/Types.jl @@ -786,7 +786,7 @@ end # Disambiguate name/uuid package specifications using project info. function project_deps_resolve!(env::EnvCache, pkgs::AbstractVector{PackageSpec}) uuids = env.project["deps"] - names = Dict(uuid => name for (uuid, name) in uuids) + names = Dict(uuid => name for (name, uuid) in uuids) length(uuids) < length(names) && # TODO: handle this somehow? pkgerror("duplicate UUID found in project file's [deps] section") for pkg in pkgs From 974f7093fb09ec7d991ad65070078f92f8486028 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Thu, 6 Sep 2018 01:03:24 -0700 Subject: [PATCH 150/166] Close the braces in docstring (cherry picked from commit e3236594c52e4c344fe5d1b899988560e9dbdf96) (cherry picked from commit caaa3905cd06ed621ba23ffa3c20a9a38da24cb0) (cherry picked from commit 6333ee419e8f87039c94717037e4d1caf01d8e52) --- stdlib/Pkg/src/Pkg.jl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/stdlib/Pkg/src/Pkg.jl b/stdlib/Pkg/src/Pkg.jl index 818e45e9aacb4..dbca8c257fd15 100644 --- a/stdlib/Pkg/src/Pkg.jl +++ b/stdlib/Pkg/src/Pkg.jl @@ -74,7 +74,7 @@ const UpgradeLevel = Types.UpgradeLevel # Define new variables so tab comleting Pkg. works. """ - Pkg.add(pkg::Union{String, Vector{String}) + Pkg.add(pkg::Union{String, Vector{String}}) Pkg.add(pkg::Union{PackageSpec, Vector{PackageSpec}}) Add a package to the current project. This package will be available using the @@ -94,7 +94,7 @@ See also [`PackageSpec`](@ref). const add = API.add """ - Pkg.rm(pkg::Union{String, Vector{String}) + Pkg.rm(pkg::Union{String, Vector{String}}) Pkg.rm(pkg::Union{PackageSpec, Vector{PackageSpec}}) Remove a package from the current project. If the `mode` of `pkg` is @@ -107,7 +107,7 @@ const rm = API.rm """ Pkg.update(; level::UpgradeLevel=UPLEVEL_MAJOR, mode::PackageMode = PKGMODE_PROJECT) - Pkg.update(pkg::Union{String, Vector{String}) + Pkg.update(pkg::Union{String, Vector{String}}) Pkg.update(pkg::Union{PackageSpec, Vector{PackageSpec}}) Update a package `pkg`. If no posistional argument is given, update all packages in the manifest if `mode` is `PKGMODE_MANIFEST` and packages in both manifest and project if `mode` is `PKGMODE_PROJECT`. @@ -162,7 +162,7 @@ const gc = API.gc """ Pkg.build() - Pkg.build(pkg::Union{String, Vector{String}) + Pkg.build(pkg::Union{String, Vector{String}}) Pkg.build(pkgs::Union{PackageSpec, Vector{PackageSpec}}) Run the build script in `deps/build.jl` for `pkg` and all of the dependencies in @@ -178,7 +178,7 @@ const build = API.build const installed = API.installed """ - Pkg.pin(pkg::Union{String, Vector{String}) + Pkg.pin(pkg::Union{String, Vector{String}}) Pkg.pin(pkgs::Union{Packagespec, Vector{Packagespec}}) Pin a package to the current version (or the one given in the `packagespec` or a certain @@ -187,7 +187,7 @@ git revision. A pinned package is never updated. const pin = API.pin """ - Pkg.free(pkg::Union{String, Vector{String}) + Pkg.free(pkg::Union{String, Vector{String}}) Pkg.free(pkgs::Union{Packagespec, Vector{Packagespec}}) Free a package which removes a `pin` if it exists, or if the package is tracking a path, @@ -203,7 +203,7 @@ const free = API.free """ - Pkg.develop(pkg::Union{String, Vector{String}) + Pkg.develop(pkg::Union{String, Vector{String}}) Pkg.develop(pkgs::Union{Packagespec, Vector{Packagespec}}) Make a package available for development by tracking it by path. From 3793ebaa52bc57b06154b91cfc65804c6a10babf Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Tue, 11 Sep 2018 16:06:00 +0200 Subject: [PATCH 151/166] Throw PkgError instead of ErrorException when looking for the project file. (cherry picked from commit 7c9f041603a257c960999bb9202194d04174b057) (cherry picked from commit d4a66a095c7f1d4da77dec48771dc28289949d72) (cherry picked from commit 9705bac510831c1a03bd80eadc30675e4883e537) --- stdlib/Pkg/src/Types.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stdlib/Pkg/src/Types.jl b/stdlib/Pkg/src/Types.jl index 284993bacb9df..1099d3012da9c 100644 --- a/stdlib/Pkg/src/Types.jl +++ b/stdlib/Pkg/src/Types.jl @@ -240,13 +240,13 @@ function find_project_file(env::Union{Nothing,String}=nothing) project_file = nothing if env isa Nothing project_file = Base.active_project() - project_file == nothing && error("no active project") + project_file == nothing && pkgerror("no active project") elseif startswith(env, '@') project_file = Base.load_path_expand(env) - project_file === nothing && error("package environment does not exist: $env") + project_file === nothing && pkgerror("package environment does not exist: $env") elseif env isa String if isdir(env) - isempty(readdir(env)) || error("environment is a package directory: $env") + isempty(readdir(env)) || pkgerror("environment is a package directory: $env") project_file = joinpath(env, Base.project_names[end]) else project_file = endswith(env, ".toml") ? abspath(env) : From 86e6f430c84d618730a220501bf149532fd1fc36 Mon Sep 17 00:00:00 2001 From: David Varela <00.varela.david@gmail.com> Date: Tue, 11 Sep 2018 11:40:30 -0700 Subject: [PATCH 152/166] Fix typo in help docs (cherry picked from commit 34a1867933af3e02a7ce6648c5a4bf9e69e17de7) (cherry picked from commit 3b2880cfeae06b08e9b74e2c2b0c84a5289f581f) (cherry picked from commit 4b74adf92f8932f962046d92a02971f919289a02) --- stdlib/Pkg/src/REPLMode.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index 744df6d24b13b..3edbc61883e79 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -1174,7 +1174,7 @@ The `startup.jl` file is disabled during building unless julia is started with ` resolve Resolve the project i.e. run package resolution and update the Manifest. This is useful in case the dependencies of developed -packages have changed causing the current Manifest to_indices be out of sync. +packages have changed causing the current Manifest to be out of sync. """, ),( CMD_ACTIVATE, ["activate"], From e267492e461f54152aaea56910905a925c0fe6f4 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Thu, 6 Sep 2018 15:21:02 -0700 Subject: [PATCH 153/166] Don't mutate argument passed to Pkg.add (cherry picked from commit 1cdbe0e08cb576f8bae58573da7eb69308cae89c) (cherry picked from commit 97af750d3fe766014259025927fbfd9c734ab3f9) (cherry picked from commit dc696b2060608294d65100c2dd693c799644b496) --- stdlib/Pkg/src/API.jl | 7 +++++++ stdlib/Pkg/test/pkg.jl | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/stdlib/Pkg/src/API.jl b/stdlib/Pkg/src/API.jl index 28937ddc859b0..6c7b784fcfb8e 100644 --- a/stdlib/Pkg/src/API.jl +++ b/stdlib/Pkg/src/API.jl @@ -29,6 +29,7 @@ add_or_develop(pkgs::Vector{String}; kwargs...) = add_or_develop([che add_or_develop(pkgs::Vector{PackageSpec}; kwargs...) = add_or_develop(Context(), pkgs; kwargs...) function add_or_develop(ctx::Context, pkgs::Vector{PackageSpec}; mode::Symbol, shared::Bool=true, kwargs...) + pkgs = deepcopy(pkgs) # deepcopy for avoid mutating PackageSpec members Context!(ctx; kwargs...) # All developed packages should go through handle_repos_develop so just give them an empty repo @@ -73,6 +74,7 @@ rm(pkgs::Vector{String}; kwargs...) = rm([PackageSpec(pkg) for pkg in rm(pkgs::Vector{PackageSpec}; kwargs...) = rm(Context(), pkgs; kwargs...) function rm(ctx::Context, pkgs::Vector{PackageSpec}; mode=PKGMODE_PROJECT, kwargs...) + pkgs = deepcopy(pkgs) # deepcopy for avoid mutating PackageSpec members for pkg in pkgs # TODO only overwrite pkg.mode if default value ? pkg.mode = mode @@ -166,6 +168,7 @@ up(pkgs::Vector{PackageSpec}; kwargs...) = up(Context(), pkgs; kwargs...) function up(ctx::Context, pkgs::Vector{PackageSpec}; level::UpgradeLevel=UPLEVEL_MAJOR, mode::PackageMode=PKGMODE_PROJECT, do_update_registry=true, kwargs...) + pkgs = deepcopy(pkgs) # deepcopy for avoid mutating PackageSpec members for pkg in pkgs # TODO only override if they are not already set pkg.mode = mode @@ -205,6 +208,7 @@ pin(pkgs::Vector{String}; kwargs...) = pin([PackageSpec(pkg) for pkg pin(pkgs::Vector{PackageSpec}; kwargs...) = pin(Context(), pkgs; kwargs...) function pin(ctx::Context, pkgs::Vector{PackageSpec}; kwargs...) + pkgs = deepcopy(pkgs) # deepcopy for avoid mutating PackageSpec members Context!(ctx; kwargs...) ctx.preview && preview_info() project_deps_resolve!(ctx.env, pkgs) @@ -219,6 +223,7 @@ free(pkgs::Vector{String}; kwargs...) = free([PackageSpec(pkg) for pk free(pkgs::Vector{PackageSpec}; kwargs...) = free(Context(), pkgs; kwargs...) function free(ctx::Context, pkgs::Vector{PackageSpec}; kwargs...) + pkgs = deepcopy(pkgs) # deepcopy for avoid mutating PackageSpec members Context!(ctx; kwargs...) ctx.preview && preview_info() registry_resolve!(ctx.env, pkgs) @@ -250,6 +255,7 @@ test(pkgs::Vector{String}; kwargs...) = test([PackageSpec(pkg) for p test(pkgs::Vector{PackageSpec}; kwargs...) = test(Context(), pkgs; kwargs...) function test(ctx::Context, pkgs::Vector{PackageSpec}; coverage=false, kwargs...) + pkgs = deepcopy(pkgs) # deepcopy for avoid mutating PackageSpec members Context!(ctx; kwargs...) ctx.preview && preview_info() if isempty(pkgs) @@ -419,6 +425,7 @@ build(pkg::Array{Union{}, 1}) = build(PackageSpec[]) build(pkg::PackageSpec) = build([pkg]) build(pkgs::Vector{PackageSpec}) = build(Context(), pkgs) function build(ctx::Context, pkgs::Vector{PackageSpec}; kwargs...) + pkgs = deepcopy(pkgs) # deepcopy for avoid mutating PackageSpec members Context!(ctx; kwargs...) ctx.preview && preview_info() diff --git a/stdlib/Pkg/test/pkg.jl b/stdlib/Pkg/test/pkg.jl index 63f5834e3b8bb..0f4ca25c9835c 100644 --- a/stdlib/Pkg/test/pkg.jl +++ b/stdlib/Pkg/test/pkg.jl @@ -500,6 +500,16 @@ end @test Pkg.Types.pathrepr(path) == "`@stdlib/Test`" end + +temp_pkg_dir() do project_path + @testset "Pkg.add should not mutate" begin + package_names = ["JSON"] + packages = PackageSpec.(package_names) + Pkg.add(packages) + @test [p.name for p in packages] == package_names + end +end + include("repl.jl") include("api.jl") From 64eee0473f641e254baf964d3392c5062694fe8d Mon Sep 17 00:00:00 2001 From: Robin Deits Date: Sat, 15 Sep 2018 11:41:19 -0400 Subject: [PATCH 154/166] Fix spelling of "precompile" (cherry picked from commit 44adf6c89a09695f73556b0f1636b9aaf06dea0e) (cherry picked from commit e9ae5e2738aa7fc33d33430657e17e275170b1e7) (cherry picked from commit d60b82bd55b00c6fcb198dab8b87c9a4c26be98e) --- stdlib/Pkg/src/API.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/Pkg/src/API.jl b/stdlib/Pkg/src/API.jl index 6c7b784fcfb8e..20e4591114cfe 100644 --- a/stdlib/Pkg/src/API.jl +++ b/stdlib/Pkg/src/API.jl @@ -492,7 +492,7 @@ function precompile(ctx::Context) sourcepath = Base.locate_package(pkg) if sourcepath == nothing # XXX: this isn't supposed to be fatal - pkgerror("couldn't find path to $(pkg.name) when trying to precompilie project") + pkgerror("couldn't find path to $(pkg.name) when trying to precompile project") end stale = true for path_to_try in paths::Vector{String} From 5b3ea04f3de075645e92e95a52be1701f73e743c Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Mon, 17 Sep 2018 10:24:13 -0400 Subject: [PATCH 155/166] fix type in isjoinable (cherry picked from commit cbe0d1ff735787553e24a2187f132c10d932b9da) (cherry picked from commit 7c4c62b3d91b225b94eea9e44b0efb64e01d0d82) (cherry picked from commit 7112453b732b38e2234d4ccc951be91c86b29f9c) --- stdlib/Pkg/src/versions.jl | 2 +- stdlib/Pkg/test/pkg.jl | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/stdlib/Pkg/src/versions.jl b/stdlib/Pkg/src/versions.jl index c088c7de2c1a1..3ef108678654b 100644 --- a/stdlib/Pkg/src/versions.jl +++ b/stdlib/Pkg/src/versions.jl @@ -66,7 +66,7 @@ stricterupper(a::VersionBound, b::VersionBound) = isless_uu(a, b) ? a : b # `2.3.4` can be joined with `2.3.5` etc. function isjoinable(up::VersionBound, lo::VersionBound) - up.n == 0 && up.lo == 0 && return true + up.n == 0 && lo.n == 0 && return true if up.n == lo.n n = up.n for i = 1:(n - 1) diff --git a/stdlib/Pkg/test/pkg.jl b/stdlib/Pkg/test/pkg.jl index 0f4ca25c9835c..7cbf01b0e8bfb 100644 --- a/stdlib/Pkg/test/pkg.jl +++ b/stdlib/Pkg/test/pkg.jl @@ -88,6 +88,9 @@ import Pkg.Types: semver_spec, VersionSpec @test_throws ErrorException semver_spec("^^0.2.3") @test_throws ErrorException semver_spec("^^0.2.3.4") @test_throws ErrorException semver_spec("0.0.0") + + @test Pkg.Types.isjoinable(Pkg.Types.VersionBound((1,5)), Pkg.Types.VersionBound((1,6))) + @test !(Pkg.Types.isjoinable(Pkg.Types.VersionBound((1,5)), Pkg.Types.VersionBound((1,6,0)))) end # TODO: Should rewrite these tests not to rely on internals like field names From a92abd2aecd20bb81e6fd7390e8b4ce9476c4a21 Mon Sep 17 00:00:00 2001 From: David Varela <00.varela.david@gmail.com> Date: Wed, 12 Sep 2018 16:53:59 -0700 Subject: [PATCH 156/166] Only complete directories on `add`/`dev` (cherry picked from commit 076c74d94440452de99b3d8c7fe41926a406f4b5) (cherry picked from commit d0dfde4337ce1ef8cbd43da36a6b2ace28d80c6b) (cherry picked from commit 258b8940d27db52dd4d9f19d33bb7a73191cc7a9) --- stdlib/Pkg/src/REPLMode.jl | 3 ++- stdlib/Pkg/test/repl.jl | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index 3edbc61883e79..d786a77d5569c 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -764,7 +764,8 @@ end function complete_local_path(s, i1, i2) cmp = REPL.REPLCompletions.complete_path(s, i2) - [REPL.REPLCompletions.completion_text(p) for p in cmp[1]], cmp[2], !isempty(cmp[1]) + completions = filter!(isdir, [REPL.REPLCompletions.completion_text(p) for p in cmp[1]]) + return completions, cmp[2], !isempty(completions) end function complete_installed_package(s, i1, i2, project_opt) diff --git a/stdlib/Pkg/test/repl.jl b/stdlib/Pkg/test/repl.jl index 3b7cf7e5fa74f..1b6b1bb0cde2c 100644 --- a/stdlib/Pkg/test/repl.jl +++ b/stdlib/Pkg/test/repl.jl @@ -462,6 +462,10 @@ temp_pkg_dir() do project_path; cd(project_path) do @test apply_completion("add ./tes") == (Sys.iswindows() ? "add ./testdir\\\\" : "add ./testdir/") c, r = test_complete("dev ./") @test (Sys.iswindows() ? ("testdir\\\\" in c) : ("testdir/" in c)) + # dont complete files + touch("README.md") + c, r = test_complete("add RE") + @test !("README.md" in c) end # testset end end From 1a82cf6ae905847d0530b73660fdd949c30ab0ef Mon Sep 17 00:00:00 2001 From: Christof Stocker Date: Tue, 28 Aug 2018 11:33:23 +0200 Subject: [PATCH 157/166] add support for ssh protocol (cherry picked from commit d3b54bbf690c4707a52b9eaec31f24701fb7e6c7) (cherry picked from commit c46d13e30f4d32daea3eb9a9b28091afcadd7446) (cherry picked from commit 1b0926a00814950a577b06dc2c415c2fca2ad2d0) --- stdlib/Pkg/src/GitTools.jl | 9 +++++++-- stdlib/Pkg/test/pkg.jl | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/stdlib/Pkg/src/GitTools.jl b/stdlib/Pkg/src/GitTools.jl index acd988ead9bd9..d480f46b02f03 100644 --- a/stdlib/Pkg/src/GitTools.jl +++ b/stdlib/Pkg/src/GitTools.jl @@ -75,8 +75,13 @@ setprotocol!(proto::Union{Nothing, AbstractString}=nothing) = GIT_PROTOCOL[] = p # TODO: extend this to more urls function normalize_url(url::AbstractString) m = match(GITHUB_REGEX, url) - (m === nothing || GIT_PROTOCOL[] === nothing) ? - url : "$(GIT_PROTOCOL[])://github.com/$(m.captures[1]).git" + if m === nothing || GIT_PROTOCOL[] === nothing + url + elseif GIT_PROTOCOL[] == "ssh" + "ssh://git@github.com/$(m.captures[1]).git" + else + "$(GIT_PROTOCOL[])://github.com/$(m.captures[1]).git" + end end function clone(url, source_path; header=nothing, kwargs...) diff --git a/stdlib/Pkg/test/pkg.jl b/stdlib/Pkg/test/pkg.jl index 7cbf01b0e8bfb..d8af07ebbbee5 100644 --- a/stdlib/Pkg/test/pkg.jl +++ b/stdlib/Pkg/test/pkg.jl @@ -256,6 +256,23 @@ temp_pkg_dir() do project_path end end end + mktempdir() do devdir + withenv("JULIA_PKG_DEVDIR" => devdir) do + try + https_url = "https://github.com/JuliaLang/Example.jl.git" + ssh_url = "ssh://git@github.com/JuliaLang/Example.jl.git" + @test Pkg.GitTools.normalize_url(https_url) == https_url + Pkg.setprotocol!("ssh") + @test Pkg.GitTools.normalize_url(https_url) == ssh_url + # TODO: figure out how to test this without + # having to deploy a ssh key on github + #Pkg.develop("Example") + #@test isinstalled(TEST_PKG) + finally + Pkg.setprotocol!() + end + end + end end @testset "check logging" begin From 08b1586b0ca1faf17b29d5fc8fe65f419dc9d102 Mon Sep 17 00:00:00 2001 From: Mary McGrath Date: Tue, 4 Sep 2018 15:48:57 -0400 Subject: [PATCH 158/166] Update project.toml compat example Adding this PR here instead of [JuliaLang](https://github.com/JuliaLang/julia/pull/28947) per @KristofferC (cherry picked from commit 96736153524144d83e9d6458feae7a39be7d1b7d) (cherry picked from commit ac5965bf9a8a5b4de535e3b3e2bc4668719fd51b) (cherry picked from commit 4a72ad43a588f1091200ec7fd6812530e11831ab) --- stdlib/Pkg/docs/src/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/stdlib/Pkg/docs/src/index.md b/stdlib/Pkg/docs/src/index.md index 3206a829ae97c..66ed06686add9 100644 --- a/stdlib/Pkg/docs/src/index.md +++ b/stdlib/Pkg/docs/src/index.md @@ -731,6 +731,7 @@ Compatibility for a dependency is entered in the `Project.toml` file as for exam ```toml [compat] +julia = "1.0" Example = "0.4.3" ``` From 15a25ff38c8f20291b55188b14fc556ebc79f6cd Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Mon, 17 Sep 2018 17:33:15 -0400 Subject: [PATCH 159/166] only look up name from url if it is unset (cherry picked from commit 3a0e2ab727380ccb2c9b284282223e94ee4af2cc) (cherry picked from commit e9de77f2da8a403c63ba4cc937195b793b6a0abc) (cherry picked from commit de7c7c335649a66d4b62759df3312e415bf273c1) --- stdlib/Pkg/src/Types.jl | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/stdlib/Pkg/src/Types.jl b/stdlib/Pkg/src/Types.jl index 1099d3012da9c..3ddcaeb009d4a 100644 --- a/stdlib/Pkg/src/Types.jl +++ b/stdlib/Pkg/src/Types.jl @@ -708,14 +708,16 @@ function parse_package!(ctx, pkg, project_path) if !isempty(ctx.old_pkg2_clone_name) # remove when legacy CI script support is removed pkg.name = ctx.old_pkg2_clone_name else - # This is an old style package, get the name from src/PackageName - if isdir_windows_workaround(pkg.repo.url) - m = match(reg_pkg, abspath(pkg.repo.url)) - else - m = match(reg_pkg, pkg.repo.url) + # This is an old style package, if not set, get the name from src/PackageName + if !has_name(pkg) + if isdir_windows_workaround(pkg.repo.url) + m = match(reg_pkg, abspath(pkg.repo.url)) + else + m = match(reg_pkg, pkg.repo.url) + end + m === nothing && pkgerror("cannot determine package name from URL or path: $(pkg.repo.url), provide a name argument to `PackageSpec`") + pkg.name = m.captures[1] end - m === nothing && pkgerror("cannot determine package name from URL or path: $(pkg.repo.url)") - pkg.name = m.captures[1] end reg_uuids = registered_uuids(env, pkg.name) is_registered = !isempty(reg_uuids) From f039d97288478bb851eab1328709608dfc77cc47 Mon Sep 17 00:00:00 2001 From: David Varela Date: Tue, 18 Sep 2018 07:47:08 -0700 Subject: [PATCH 160/166] Reword `activate` docs (#742) (cherry picked from commit ac84b7fcf6b3b18fb02e2c79f7e204d598ee860a) (cherry picked from commit 854cf42190f1be2cd7036539a76dfbb555cfa7f5) (cherry picked from commit 794c1f1c09ea72ec423f022f7ab865ede5bb1250) --- stdlib/Pkg/src/Pkg.jl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/stdlib/Pkg/src/Pkg.jl b/stdlib/Pkg/src/Pkg.jl index dbca8c257fd15..0e2ffc0859cac 100644 --- a/stdlib/Pkg/src/Pkg.jl +++ b/stdlib/Pkg/src/Pkg.jl @@ -270,16 +270,16 @@ that is modified by executing package commands. The logic for what path is activated is as follows: * If `shared` is `true`, the first existing environment named `s` from the depots - in the depot stack will be activated. If no such environment exists yet, - activate it in the first depot. - * If `s` is a path that exist, that environment will be activated. - * If `s` is a package name in the current project activate that is tracking a path, - activate the environment at that path. - * If `s` is a non-existing path, activate that path. - -If no argument is given to `activate`, activate the home project, -which is the one specified by either `--project` command line when starting julia, -or `JULIA_PROJECT` environment variable. + in the depot stack will be activated. If no such environment exists, + create and activate that environment in the first depot. + * If `s` is an existing path, then activate the environment at that path. + * If `s` is a package in the current project and `s` is tracking a path, then + activate the environment at the tracked path. + * Else, `s` is interpreted as a non-existing path, activate that path. + +If no argument is given to `activate`, then activate the home project. +The home project is specified by either the `--project` command line option to +the julia executable, or the `JULIA_PROJECT` environment variable. # Examples ``` From 98e50a8023f4dea0168168c70f63ff69c3170008 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Tue, 18 Sep 2018 10:54:54 -0400 Subject: [PATCH 161/166] only do a radiobutton if we are in interactive mode (#735) (cherry picked from commit 8e91d902458b9dbeab76fa7194ee58d1a6137334) (cherry picked from commit 909508ab4b4458b6f58c0a870bd3b7f896e5a818) (cherry picked from commit a416c9f0c1474d8726cd8b37315e4b3f92d037fd) --- stdlib/Pkg/src/Types.jl | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/stdlib/Pkg/src/Types.jl b/stdlib/Pkg/src/Types.jl index 3ddcaeb009d4a..8376a93711332 100644 --- a/stdlib/Pkg/src/Types.jl +++ b/stdlib/Pkg/src/Types.jl @@ -1056,12 +1056,16 @@ function registered_uuid(env::EnvCache, name::String)::UUID end end length(choices_cache) == 1 && return choices_cache[1][1] - # prompt for which UUID was intended: - menu = RadioMenu(choices) - choice = request("There are multiple registered `$name` packages, choose one:", menu) - choice == -1 && return UUID(zero(UInt128)) - env.paths[choices_cache[choice][1]] = [choices_cache[choice][2]] - return choices_cache[choice][1] + if isinteractive() + # prompt for which UUID was intended: + menu = RadioMenu(choices) + choice = request("There are multiple registered `$name` packages, choose one:", menu) + choice == -1 && return UUID(zero(UInt128)) + env.paths[choices_cache[choice][1]] = [choices_cache[choice][2]] + return choices_cache[choice][1] + else + pkgerror("there are multiple registered `$name` packages, explicitly set the uuid") + end end # Determine current name for a given package UUID From 4ffd2a839d1ed3b0f19def777f1103e116cb3cca Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Fri, 6 Jul 2018 16:26:31 +0200 Subject: [PATCH 162/166] don't use startup.jl when precompiling, building and testing (#470) unless the user has explicitly asked for it with --startup-file=yes (cherry picked from commit 40d7f27f2ff08ec466df536f267129a9f5e950b4) (cherry picked from commit eb968114a6225e93b91ab8321abb6b458dccebb3) --- stdlib/Pkg/src/Operations.jl | 2 +- stdlib/Pkg/src/REPLMode.jl | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/stdlib/Pkg/src/Operations.jl b/stdlib/Pkg/src/Operations.jl index 610171372a0f9..a2198ae261d98 100644 --- a/stdlib/Pkg/src/Operations.jl +++ b/stdlib/Pkg/src/Operations.jl @@ -1046,7 +1046,7 @@ function build_versions(ctx::Context, uuids::Vector{UUID}; might_need_to_resolve """ cmd = ``` $(Base.julia_cmd()) -O0 --color=no --history-file=no - --startup-file=$(Base.JLOptions().startupfile != 2 ? "yes" : "no") + --startup-file=$(Base.JLOptions().startupfile == 1 ? "yes" : "no") --compiled-modules=$(Bool(Base.JLOptions().use_compiled_modules) ? "yes" : "no") --eval $code ``` diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index d786a77d5569c..0ed813bae5063 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -1246,7 +1246,6 @@ Create a project called `pkgname` in the current folder. precompile Precompile all the dependencies of the project by running `import` on all of them in a new process. -The `startup.jl` file is disabled during precompilation unless julia is started with `--startup-file=yes`. """, ),( CMD_STATUS, ["status", "st"], From 15c443b3daca0757320c450756fc256b43efe2a8 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Wed, 12 Sep 2018 15:56:02 -0400 Subject: [PATCH 163/166] do not precompile packages that have opt out to precompilation (cherry picked from commit 57f7380a2641944be12695e92a3ad9f4cc20e6f2) (cherry picked from commit 5829a4051aeb534251c940d95cbc87f7eb961884) --- stdlib/Pkg/src/API.jl | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/stdlib/Pkg/src/API.jl b/stdlib/Pkg/src/API.jl index 20e4591114cfe..62b5f67de8fad 100644 --- a/stdlib/Pkg/src/API.jl +++ b/stdlib/Pkg/src/API.jl @@ -490,10 +490,9 @@ function precompile(ctx::Context) for pkg in pkgids paths = Base.find_all_in_cache_path(pkg) sourcepath = Base.locate_package(pkg) - if sourcepath == nothing - # XXX: this isn't supposed to be fatal - pkgerror("couldn't find path to $(pkg.name) when trying to precompile project") - end + sourcepath == nothing && continue + # Heuristic for when precompilation is disabled + occursin(r"\b__precompile__\(\s*false\s*\)", read(sourcepath, String)) && continue stale = true for path_to_try in paths::Vector{String} staledeps = Base.stale_cachefile(sourcepath, path_to_try) From 997bddb8d50303dc87b640111b62f91d5386daff Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Mon, 24 Sep 2018 21:10:44 -0700 Subject: [PATCH 164/166] Add missing test dependencies to SparseArrays Project.toml (#29354) The tests use InteractiveUtils but it is not listed as a test dependency in the SparseArrays Project.toml file. This is causing SparseArrays to fail its tests when run on NewPkgEval, which means every package that uses SparseArrays gets their tests skipped. (cherry picked from commit f2ad0098636cf948a1020d8845691dda5a13f810) --- stdlib/SparseArrays/Project.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stdlib/SparseArrays/Project.toml b/stdlib/SparseArrays/Project.toml index c3d35186e1b8e..bffdfc775fdc6 100644 --- a/stdlib/SparseArrays/Project.toml +++ b/stdlib/SparseArrays/Project.toml @@ -7,6 +7,7 @@ Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" [targets] -test = ["Test"] +test = ["Test", "InteractiveUtils"] From 93c3abd4104f56614f077cff82ae0fe4a2730adb Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 13 Sep 2018 11:04:18 -0400 Subject: [PATCH 165/166] See if building our own PCRE fixes the travis issues (#29162) (cherry picked from commit d974f93391b9e2b3d21437fe83711b2fec74bd19) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 322ff5c8fd21e..9787360f69f4e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -80,7 +80,7 @@ before_install: BUILDOPTS="$BUILDOPTS USE_BINARYBUILDER_LLVM=1 LLVM_CONFIG=$TRAVIS_BUILD_DIR/usr/tools/llvm-config LLVM_SIZE=$TRAVIS_BUILD_DIR/usr/tools/llvm-size"; BUILDOPTS="$BUILDOPTS VERBOSE=1 USE_BLAS64=0 SUITESPARSE_INC=-I$(brew --prefix suite-sparse-julia)/include FORCE_ASSERTIONS=1"; BUILDOPTS="$BUILDOPTS LIBBLAS=-lopenblas LIBBLASNAME=libopenblas LIBLAPACK=-lopenblas LIBLAPACKNAME=libopenblas"; - for lib in SUITESPARSE BLAS LAPACK GMP MPFR PCRE LIBUNWIND; do + for lib in SUITESPARSE BLAS LAPACK GMP MPFR LIBUNWIND; do BUILDOPTS="$BUILDOPTS USE_SYSTEM_$lib=1"; done; export LDFLAGS="-L$(brew --prefix openblas-julia)/lib -L$(brew --prefix suite-sparse-julia)/lib"; From 1aaf6f021e00db0c62e970df6b15102baabf7596 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Sat, 22 Sep 2018 12:11:43 -0400 Subject: [PATCH 166/166] bump JSON version check to a non-capped version (#29315) (cherry picked from commit f8b52dab77415a22d28497f48407aca92fbbd4c3) --- stdlib/Pkg/test/repl.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/Pkg/test/repl.jl b/stdlib/Pkg/test/repl.jl index 1b6b1bb0cde2c..9c9651ce24887 100644 --- a/stdlib/Pkg/test/repl.jl +++ b/stdlib/Pkg/test/repl.jl @@ -498,12 +498,12 @@ temp_pkg_dir() do project_path; cd(project_path) do print(io, """ [compat] - JSON = "0.16.0" + JSON = "0.18.0" """ ) end pkg"up" - @test Pkg.API.installed()["JSON"].minor == 16 + @test Pkg.API.installed()["JSON"].minor == 18 write("Project.toml", old_project) pkg"up" @test Pkg.API.installed()["JSON"] == current_json