From f7bf6b00752ee76bfab79f0268557d01e85617dc Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Wed, 28 Feb 2018 17:36:42 -0500 Subject: [PATCH 01/28] [PPC] backport llvm patch for invalid ctr loop with `mod` --- deps/llvm.mk | 3 + deps/patches/llvm-PR36292-5.0.patch | 97 +++++++++++++++++++++++++++++ deps/patches/llvm-PR36292.patch | 96 ++++++++++++++++++++++++++++ 3 files changed, 196 insertions(+) create mode 100644 deps/patches/llvm-PR36292-5.0.patch create mode 100644 deps/patches/llvm-PR36292.patch diff --git a/deps/llvm.mk b/deps/llvm.mk index 01657f6af6cd1..dc342210ab139 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -466,6 +466,7 @@ $(eval $(call LLVM_PATCH,llvm-D42262-jumpthreading-not-i1)) $(eval $(call LLVM_PATCH,llvm-3.9-c_api_nullptr)) $(eval $(call LLVM_PATCH,llvm-PPC-addrspaces)) # PPC $(eval $(call LLVM_PATCH,llvm-D30114)) # PPC remove for 5.0 +$(eval $(call LLVM_PATCH,llvm-PR36292)) # PPC fixes #26249, remove for 6.0 ifeq ($(BUILD_LLVM_CLANG),1) $(eval $(call LLVM_PATCH,compiler_rt-3.9-glibc_2.25.90)) # Remove for 5.0 endif @@ -496,6 +497,7 @@ $(eval $(call LLVM_PATCH,llvm-D31524-sovers_4.0)) # Remove for 5.0 $(eval $(call LLVM_PATCH,llvm-D42262-jumpthreading-not-i1)) $(eval $(call LLVM_PATCH,llvm-PPC-addrspaces)) # PPC $(eval $(call LLVM_PATCH,llvm-D30114)) # PPC remove for 5.0 +$(eval $(call LLVM_PATCH,llvm-PR36292)) # PPC fixes #26249, remove for 6.0 ifeq ($(BUILD_LLVM_CLANG),1) $(eval $(call LLVM_PATCH,compiler_rt-3.9-glibc_2.25.90)) # Remove for 5.0 endif @@ -511,6 +513,7 @@ $(eval $(call LLVM_PATCH,llvm-4.0.0-D37576-NVPTX-sm_70)) # NVPTX, Remove for 6.0 $(eval $(call LLVM_PATCH,llvm-D38765-gvn_5.0)) # Remove for 6.0 $(eval $(call LLVM_PATCH,llvm-D42262-jumpthreading-not-i1)) $(eval $(call LLVM_PATCH,llvm-PPC-addrspaces)) # PPC +$(eval $(call LLVM_PATCH,llvm-PR36292-5.0)) # PPC fixes #26249, remove for 6.0 endif # LLVM_VER # Remove hardcoded OS X requirements in compilter-rt cmake build diff --git a/deps/patches/llvm-PR36292-5.0.patch b/deps/patches/llvm-PR36292-5.0.patch new file mode 100644 index 0000000000000..7d5d8d167f533 --- /dev/null +++ b/deps/patches/llvm-PR36292-5.0.patch @@ -0,0 +1,97 @@ +From 94f96f87fa44f2fa2cf86ecb644d3cdc3fc609ad Mon Sep 17 00:00:00 2001 +From: Nemanja Ivanovic +Date: Thu, 22 Feb 2018 03:02:41 +0000 +Subject: [PATCH] [PowerPC] Do not produce invalid CTR loop with an FRem + +An FRem instruction inside a loop should prevent the loop from being converted +into a CTR loop since this is not an operation that is legal on any PPC +subtarget. This will always be a call to a library function which means the +loop will be invalid if this instruction is in the body. + +Fixes PR36292. + + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@325739 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/Target/PowerPC/PPCCTRLoops.cpp | 5 ++++- + test/CodeGen/PowerPC/pr36292.ll | 46 ++++++++++++++++++++++++++++++++++++++ + 2 files changed, 50 insertions(+), 1 deletion(-) + create mode 100644 test/CodeGen/PowerPC/pr36292.ll + +diff --git a/lib/Target/PowerPC/PPCCTRLoops.cpp b/lib/Target/PowerPC/PPCCTRLoops.cpp +index 53f33ac1fc0..97917a1d096 100644 +--- a/lib/Target/PowerPC/PPCCTRLoops.cpp ++++ b/lib/Target/PowerPC/PPCCTRLoops.cpp +@@ -437,13 +437,16 @@ bool PPCCTRLoops::mightUseCTR(BasicBlock *BB) { + return true; + } + ++ // FREM is always a call. ++ if (J->getOpcode() == Instruction::FRem) ++ return true; ++ + if (STI->useSoftFloat()) { + switch(J->getOpcode()) { + case Instruction::FAdd: + case Instruction::FSub: + case Instruction::FMul: + case Instruction::FDiv: +- case Instruction::FRem: + case Instruction::FPTrunc: + case Instruction::FPExt: + case Instruction::FPToUI: +diff --git a/test/CodeGen/PowerPC/pr36292.ll b/test/CodeGen/PowerPC/pr36292.ll +new file mode 100644 +index 00000000000..a171918b9e0 +--- /dev/null ++++ b/test/CodeGen/PowerPC/pr36292.ll +@@ -0,0 +1,46 @@ ++; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-unknown < %s | \ ++; RUN: FileCheck %s --implicit-check-not=mtctr --implicit-check-not=bdnz ++$test = comdat any ++ ++; No CTR loop due to frem (since it is always a call). ++define void @test() #0 comdat { ++; CHECK-LABEL: test: ++; CHECK: ld 29, 0(3) ++; CHECK: ld 30, 40(1) ++; CHECK: xxlxor 31, 31, 31 ++; CHECK: cmpld 30, 29 ++; CHECK-NEXT: bge- 0, .LBB0_2 ++; CHECK-NEXT: .p2align 5 ++; CHECK-NEXT: .LBB0_1: # %bounds.ok ++; CHECK: fmr 1, 31 ++; CHECK-NEXT: lfsx 2, 0, 3 ++; CHECK-NEXT: bl fmodf ++; CHECK-NEXT: nop ++; CHECK-NEXT: addi 30, 30, 1 ++; CHECK-NEXT: stfsx 1, 0, 3 ++; CHECK-NEXT: cmpld 30, 29 ++; CHECK-NEXT: blt+ 0, .LBB0_1 ++; CHECK-NEXT: .LBB0_2: # %bounds.fail ++; CHECK-NEXT: std 30, 40(1) ++ %pos = alloca i64, align 8 ++ br label %forcond ++ ++forcond: ; preds = %bounds.ok, %0 ++ %1 = load i64, i64* %pos ++ %.len1 = load i64, i64* undef ++ %bounds.cmp = icmp ult i64 %1, %.len1 ++ br i1 %bounds.cmp, label %bounds.ok, label %bounds.fail ++ ++bounds.ok: ; preds = %forcond ++ %2 = load float, float* undef ++ %3 = frem float 0.000000e+00, %2 ++ store float %3, float* undef ++ %4 = load i64, i64* %pos ++ %5 = add i64 %4, 1 ++ store i64 %5, i64* %pos ++ br label %forcond ++ ++bounds.fail: ; preds = %forcond ++ unreachable ++} ++ +-- +2.16.2 + diff --git a/deps/patches/llvm-PR36292.patch b/deps/patches/llvm-PR36292.patch new file mode 100644 index 0000000000000..8d5f72b146ac3 --- /dev/null +++ b/deps/patches/llvm-PR36292.patch @@ -0,0 +1,96 @@ +From bf6e0a9a6dacce55de9f72de06318e7b97b44e3d Mon Sep 17 00:00:00 2001 +From: Nemanja Ivanovic +Date: Thu, 22 Feb 2018 03:02:41 +0000 +Subject: [PATCH] [PowerPC] Do not produce invalid CTR loop with an FRem + +An FRem instruction inside a loop should prevent the loop from being converted +into a CTR loop since this is not an operation that is legal on any PPC +subtarget. This will always be a call to a library function which means the +loop will be invalid if this instruction is in the body. + +Fixes PR36292. + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@325739 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/Target/PowerPC/PPCCTRLoops.cpp | 5 ++++- + test/CodeGen/PowerPC/pr36292.ll | 46 ++++++++++++++++++++++++++++++++++++++ + 2 files changed, 50 insertions(+), 1 deletion(-) + create mode 100644 test/CodeGen/PowerPC/pr36292.ll + +diff --git a/lib/Target/PowerPC/PPCCTRLoops.cpp b/lib/Target/PowerPC/PPCCTRLoops.cpp +index 87522663591..6a327781ca2 100644 +--- a/lib/Target/PowerPC/PPCCTRLoops.cpp ++++ b/lib/Target/PowerPC/PPCCTRLoops.cpp +@@ -435,13 +435,16 @@ bool PPCCTRLoops::mightUseCTR(const Triple &TT, BasicBlock *BB) { + return true; + } + ++ // FREM is always a call. ++ if (J->getOpcode() == Instruction::FRem) ++ return true; ++ + if (TM->getSubtargetImpl(*BB->getParent())->getTargetLowering()->useSoftFloat()) { + switch(J->getOpcode()) { + case Instruction::FAdd: + case Instruction::FSub: + case Instruction::FMul: + case Instruction::FDiv: +- case Instruction::FRem: + case Instruction::FPTrunc: + case Instruction::FPExt: + case Instruction::FPToUI: +diff --git a/test/CodeGen/PowerPC/pr36292.ll b/test/CodeGen/PowerPC/pr36292.ll +new file mode 100644 +index 00000000000..a171918b9e0 +--- /dev/null ++++ b/test/CodeGen/PowerPC/pr36292.ll +@@ -0,0 +1,46 @@ ++; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-unknown < %s | \ ++; RUN: FileCheck %s --implicit-check-not=mtctr --implicit-check-not=bdnz ++$test = comdat any ++ ++; No CTR loop due to frem (since it is always a call). ++define void @test() #0 comdat { ++; CHECK-LABEL: test: ++; CHECK: ld 29, 0(3) ++; CHECK: ld 30, 40(1) ++; CHECK: xxlxor 31, 31, 31 ++; CHECK: cmpld 30, 29 ++; CHECK-NEXT: bge- 0, .LBB0_2 ++; CHECK-NEXT: .p2align 5 ++; CHECK-NEXT: .LBB0_1: # %bounds.ok ++; CHECK: fmr 1, 31 ++; CHECK-NEXT: lfsx 2, 0, 3 ++; CHECK-NEXT: bl fmodf ++; CHECK-NEXT: nop ++; CHECK-NEXT: addi 30, 30, 1 ++; CHECK-NEXT: stfsx 1, 0, 3 ++; CHECK-NEXT: cmpld 30, 29 ++; CHECK-NEXT: blt+ 0, .LBB0_1 ++; CHECK-NEXT: .LBB0_2: # %bounds.fail ++; CHECK-NEXT: std 30, 40(1) ++ %pos = alloca i64, align 8 ++ br label %forcond ++ ++forcond: ; preds = %bounds.ok, %0 ++ %1 = load i64, i64* %pos ++ %.len1 = load i64, i64* undef ++ %bounds.cmp = icmp ult i64 %1, %.len1 ++ br i1 %bounds.cmp, label %bounds.ok, label %bounds.fail ++ ++bounds.ok: ; preds = %forcond ++ %2 = load float, float* undef ++ %3 = frem float 0.000000e+00, %2 ++ store float %3, float* undef ++ %4 = load i64, i64* %pos ++ %5 = add i64 %4, 1 ++ store i64 %5, i64* %pos ++ br label %forcond ++ ++bounds.fail: ; preds = %forcond ++ unreachable ++} ++ +-- +2.16.2 + From 029fb723c08530d6a9fadb61cb84f5c1b6cc3402 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Thu, 1 Mar 2018 17:15:26 +0100 Subject: [PATCH 02/28] move diff to base, does not really belong in LinearAlgebra (#26270) --- base/deprecated.jl | 2 ++ base/exports.jl | 1 + base/multidimensional.jl | 38 +++++++++++++++++++++++ base/sysimg.jl | 1 - doc/src/base/arrays.md | 2 +- stdlib/LinearAlgebra/src/LinearAlgebra.jl | 1 - stdlib/LinearAlgebra/src/deprecated.jl | 2 -- stdlib/LinearAlgebra/src/generic.jl | 38 ----------------------- stdlib/LinearAlgebra/test/generic.jl | 15 --------- stdlib/SparseArrays/src/SparseArrays.jl | 4 +-- test/arrayops.jl | 15 +++++++++ 11 files changed, 59 insertions(+), 60 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index e9d0e2a1fd999..44a0107d9f65c 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1468,6 +1468,8 @@ end @deprecate(matchall(r::Regex, s::AbstractString; overlap::Bool = false), collect(m.match for m in eachmatch(r, s, overlap = overlap))) +@deprecate diff(A::AbstractMatrix) diff(A, 1) + # PR 26194 export assert function assert(x) diff --git a/base/exports.jl b/base/exports.jl index e9946232af844..5ef5845dbfacf 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -370,6 +370,7 @@ export conj!, copy!, copyto!, + diff, cumprod, cumprod!, cumsum, diff --git a/base/multidimensional.jl b/base/multidimensional.jl index ebb5cf6347a97..d88794cd46798 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -1087,6 +1087,44 @@ function _accumulate1!(op, B, v1, A::AbstractVector, dim::Integer) return B end +diff(a::AbstractVector) = [ a[i+1] - a[i] for i=1:length(a)-1 ] + +""" + diff(A::AbstractVector) + diff(A::AbstractMatrix, dim::Integer) + +Finite difference operator of matrix or vector `A`. If `A` is a matrix, +specify the dimension over which to operate with the `dim` argument. + +# Examples +```jldoctest +julia> a = [2 4; 6 16] +2×2 Array{Int64,2}: + 2 4 + 6 16 + +julia> diff(a,2) +2×1 Array{Int64,2}: + 2 + 10 + +julia> diff(vec(a)) +3-element Array{Int64,1}: + 4 + -2 + 12 +``` +""" +function diff(A::AbstractMatrix, dim::Integer) + if dim == 1 + [A[i+1,j] - A[i,j] for i=1:size(A,1)-1, j=1:size(A,2)] + elseif dim == 2 + [A[i,j+1] - A[i,j] for i=1:size(A,1), j=1:size(A,2)-1] + else + throw(ArgumentError("dimension dim must be 1 or 2, got $dim")) + end +end + ### from abstractarray.jl # In the common case where we have two views into the same parent, aliasing checks diff --git a/base/sysimg.jl b/base/sysimg.jl index 03103f5ad15d4..c952f7a83dca2 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -739,7 +739,6 @@ end @deprecate_stdlib diag LinearAlgebra true @deprecate_stdlib diagind LinearAlgebra true @deprecate_stdlib diagm LinearAlgebra true - @deprecate_stdlib diff LinearAlgebra true @deprecate_stdlib dot LinearAlgebra true @deprecate_stdlib eig LinearAlgebra true @deprecate_stdlib eigfact! LinearAlgebra true diff --git a/doc/src/base/arrays.md b/doc/src/base/arrays.md index 6ea60b55c4d19..402ebab2d4da8 100644 --- a/doc/src/base/arrays.md +++ b/doc/src/base/arrays.md @@ -144,7 +144,7 @@ Base.cumprod Base.cumprod! Base.cumsum Base.cumsum! -LinearAlgebra.diff +Base.diff Base.repeat Base.rot180 Base.rotl90 diff --git a/stdlib/LinearAlgebra/src/LinearAlgebra.jl b/stdlib/LinearAlgebra/src/LinearAlgebra.jl index a7900f9c1a46b..678952f745e6b 100644 --- a/stdlib/LinearAlgebra/src/LinearAlgebra.jl +++ b/stdlib/LinearAlgebra/src/LinearAlgebra.jl @@ -77,7 +77,6 @@ export diag, diagind, diagm, - diff, dot, eig, eigfact, diff --git a/stdlib/LinearAlgebra/src/deprecated.jl b/stdlib/LinearAlgebra/src/deprecated.jl index d1b94d363eff2..c68016c29d816 100644 --- a/stdlib/LinearAlgebra/src/deprecated.jl +++ b/stdlib/LinearAlgebra/src/deprecated.jl @@ -333,8 +333,6 @@ end @deprecate chol!(x::Number, uplo) chol(x) false -@deprecate diff(A::AbstractMatrix) diff(A, 1) - ### deprecations for lazier, less jazzy linalg transition in the next several blocks ### # deprecate ConjArray diff --git a/stdlib/LinearAlgebra/src/generic.jl b/stdlib/LinearAlgebra/src/generic.jl index 71558c27d51d0..77789197884c1 100644 --- a/stdlib/LinearAlgebra/src/generic.jl +++ b/stdlib/LinearAlgebra/src/generic.jl @@ -238,44 +238,6 @@ See also [`tril`](@ref). """ tril!(M::AbstractMatrix) = tril!(M,0) -diff(a::AbstractVector) = [ a[i+1] - a[i] for i=1:length(a)-1 ] - -""" - diff(A::AbstractVector) - diff(A::AbstractMatrix, dim::Integer) - -Finite difference operator of matrix or vector `A`. If `A` is a matrix, -specify the dimension over which to operate with the `dim` argument. - -# Examples -```jldoctest -julia> a = [2 4; 6 16] -2×2 Array{Int64,2}: - 2 4 - 6 16 - -julia> diff(a,2) -2×1 Array{Int64,2}: - 2 - 10 - -julia> diff(vec(a)) -3-element Array{Int64,1}: - 4 - -2 - 12 -``` -""" -function diff(A::AbstractMatrix, dim::Integer) - if dim == 1 - [A[i+1,j] - A[i,j] for i=1:size(A,1)-1, j=1:size(A,2)] - elseif dim == 2 - [A[i,j+1] - A[i,j] for i=1:size(A,1), j=1:size(A,2)-1] - else - throw(ArgumentError("dimension dim must be 1 or 2, got $dim")) - end -end - diag(A::AbstractVector) = throw(ArgumentError("use diagm instead of diag to construct a diagonal matrix")) ########################################################################################### diff --git a/stdlib/LinearAlgebra/test/generic.jl b/stdlib/LinearAlgebra/test/generic.jl index 9f583cfe0df20..00a560af9be51 100644 --- a/stdlib/LinearAlgebra/test/generic.jl +++ b/stdlib/LinearAlgebra/test/generic.jl @@ -89,21 +89,6 @@ n = 5 # should be odd end end -@testset "diff" begin - # test diff, throw ArgumentError for invalid dimension argument - X = [3 9 5; - 7 4 2; - 2 1 10] - @test diff(X,1) == [4 -5 -3; -5 -3 8] - @test diff(X,2) == [6 -4; -3 -2; -1 9] - @test diff(view(X, 1:2, 1:2),1) == [4 -5] - @test diff(view(X, 1:2, 1:2),2) == reshape([6; -3], (2,1)) - @test diff(view(X, 2:3, 2:3),1) == [-3 8] - @test diff(view(X, 2:3, 2:3),2) == reshape([-2; 9], (2,1)) - @test_throws ArgumentError diff(X,3) - @test_throws ArgumentError diff(X,-1) -end - @testset "linrange" begin # make sure unequal input arrays throw an error x = [2; 5; 6] diff --git a/stdlib/SparseArrays/src/SparseArrays.jl b/stdlib/SparseArrays/src/SparseArrays.jl index 7cc27133c825f..7be327ace17f9 100644 --- a/stdlib/SparseArrays/src/SparseArrays.jl +++ b/stdlib/SparseArrays/src/SparseArrays.jl @@ -12,7 +12,7 @@ using Base.Sort: Forward using LinearAlgebra import Base: +, -, *, \, /, &, |, xor, == -import LinearAlgebra: mul!, ldiv!, rdiv!, chol, adjoint!, diag, diff, dot, eig, +import LinearAlgebra: mul!, ldiv!, rdiv!, chol, adjoint!, diag, dot, eig, issymmetric, istril, istriu, lu, trace, transpose!, tril!, triu!, vecnorm, cond, diagm, factorize, ishermitian, norm, lmul!, rmul!, tril, triu @@ -28,7 +28,7 @@ import Base: @get!, acos, acosd, acot, acotd, acsch, asech, asin, asind, asinh, vcat, hcat, hvcat, cat, imag, argmax, kron, length, log, log1p, max, min, maximum, minimum, one, promote_eltype, real, reshape, rot180, rotl90, rotr90, round, setindex!, similar, size, transpose, - vec, permute!, map, map!, Array + vec, permute!, map, map!, Array, diff using Random: GLOBAL_RNG, AbstractRNG, randsubseq, randsubseq! diff --git a/test/arrayops.jl b/test/arrayops.jl index 4e0118a20808b..570c1510592b3 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -2184,6 +2184,21 @@ end @test all(x -> x isa U, b) end +@testset "diff" begin + # test diff, throw ArgumentError for invalid dimension argument + X = [3 9 5; + 7 4 2; + 2 1 10] + @test diff(X,1) == [4 -5 -3; -5 -3 8] + @test diff(X,2) == [6 -4; -3 -2; -1 9] + @test diff(view(X, 1:2, 1:2),1) == [4 -5] + @test diff(view(X, 1:2, 1:2),2) == reshape([6; -3], (2,1)) + @test diff(view(X, 2:3, 2:3),1) == [-3 8] + @test diff(view(X, 2:3, 2:3),2) == reshape([-2; 9], (2,1)) + @test_throws ArgumentError diff(X,3) + @test_throws ArgumentError diff(X,-1) +end + @testset "accumulate, accumulate!" begin @test accumulate(+, [1,2,3]) == [1, 3, 6] @test accumulate(min, [1 2; 3 4], dims=1) == [1 2; 1 2] From cde00cf7536455cf0216606e127a9da5a5835ccb Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Thu, 1 Mar 2018 12:22:20 -0500 Subject: [PATCH 03/28] bugfixes for rsplit (for unicode and empty strings) (#26238) * bugfixes for rsplit (for unicode and empty strings) * replace isequal in tests with ==, equivalent for strings --- base/strings/util.jl | 26 +++----- test/strings/util.jl | 147 ++++++++++++++++++++++--------------------- 2 files changed, 87 insertions(+), 86 deletions(-) diff --git a/base/strings/util.jl b/base/strings/util.jl index 223510155e018..39dbb6603ab20 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -275,9 +275,9 @@ split(str::T, splitter::Char; _split(str, equalto(splitter), limit, keep, T <: SubString ? T[] : SubString{T}[]) function _split(str::AbstractString, splitter, limit::Integer, keep_empty::Bool, strs::Array) - i = start(str) + @assert (i = firstindex(str)) == 1 n = lastindex(str) - r = coalesce(findfirst(splitter,str), i - 1) + r = coalesce(findfirst(splitter,str), 0) if r != 0:-1 j, k = first(r), nextind(str,last(r)) while 0 < j <= n && length(strs) != limit-1 @@ -342,22 +342,16 @@ rsplit(str::T, splitter::Char; _rsplit(str, equalto(splitter), limit, keep, T <: SubString ? T[] : SubString{T}[]) function _rsplit(str::AbstractString, splitter, limit::Integer, keep_empty::Bool, strs::Array) - i = start(str) n = lastindex(str) - r = coalesce(findlast(splitter, str), i - 1) - j = first(r)-1 - k = last(r) - while((0 <= j < n) && (length(strs) != limit-1)) - if i <= k - (keep_empty || (k < n)) && pushfirst!(strs, SubString(str,k+1,n)) - n = j - end - (k <= j) && (j = prevind(str,j)) - r = coalesce(findprev(splitter,str,j), 0) - j = first(r)-1 - k = last(r) + r = coalesce(findlast(splitter, str), 0) + j, k = first(r), last(r) + while j > 0 && k > 0 && length(strs) != limit-1 + (keep_empty || k < n) && pushfirst!(strs, SubString(str,nextind(str,k),n)) + n = prevind(str, j) + r = coalesce(findprev(splitter,str,n), 0) + j, k = first(r), last(r) end - (keep_empty || (n > 0)) && pushfirst!(strs, SubString(str,1,n)) + (keep_empty || n > 0) && pushfirst!(strs, SubString(str,1,n)) return strs end #rsplit(str::AbstractString) = rsplit(str, _default_delims, 0, false) diff --git a/test/strings/util.jl b/test/strings/util.jl index b76b0005fe283..f6e727a110f1e 100644 --- a/test/strings/util.jl +++ b/test/strings/util.jl @@ -75,81 +75,88 @@ end end @testset "rsplit/split" begin - @test isequal(split("foo,bar,baz", 'x'), ["foo,bar,baz"]) - @test isequal(split("foo,bar,baz", ','), ["foo","bar","baz"]) - @test isequal(split("foo,bar,baz", ","), ["foo","bar","baz"]) - @test isequal(split("foo,bar,baz", r","), ["foo","bar","baz"]) - @test isequal(split("foo,bar,baz", ','; limit=0), ["foo","bar","baz"]) - @test isequal(split("foo,bar,baz", ','; limit=1), ["foo,bar,baz"]) - @test isequal(split("foo,bar,baz", ','; limit=2), ["foo","bar,baz"]) - @test isequal(split("foo,bar,baz", ','; limit=3), ["foo","bar","baz"]) - @test isequal(split("foo,bar", "o,b"), ["fo","ar"]) - - @test isequal(split("", ','), [""]) - @test isequal(split(",", ','), ["",""]) - @test isequal(split(",,", ','), ["","",""]) - @test isequal(split("", ',' ; keep=false), []) - @test isequal(split(",", ',' ; keep=false), []) - @test isequal(split(",,", ','; keep=false), []) - - @test isequal(split("a b c"), ["a","b","c"]) - @test isequal(split("a b \t c\n"), ["a","b","c"]) - - @test isequal(rsplit("foo,bar,baz", 'x'), ["foo,bar,baz"]) - @test isequal(rsplit("foo,bar,baz", ','), ["foo","bar","baz"]) - @test isequal(rsplit("foo,bar,baz", ","), ["foo","bar","baz"]) - @test isequal(rsplit("foo,bar,baz", ','; limit=0), ["foo","bar","baz"]) - @test isequal(rsplit("foo,bar,baz", ','; limit=1), ["foo,bar,baz"]) - @test isequal(rsplit("foo,bar,baz", ','; limit=2), ["foo,bar","baz"]) - @test isequal(rsplit("foo,bar,baz", ','; limit=3), ["foo","bar","baz"]) - @test isequal(rsplit("foo,bar", "o,b"), ["fo","ar"]) - - @test isequal(rsplit("", ','), [""]) - @test isequal(rsplit(",", ','), ["",""]) - @test isequal(rsplit(",,", ','), ["","",""]) - @test isequal(rsplit(",,", ','; limit=2), [",",""]) - @test isequal(rsplit("", ',' ; keep=false), []) - @test isequal(rsplit(",", ',' ; keep=false), []) - @test isequal(rsplit(",,", ','; keep=false), []) - - #@test isequal(rsplit("a b c"), ["a","b","c"]) - #@test isequal(rsplit("a b \t c\n"), ["a","b","c"]) + @test split("foo,bar,baz", 'x') == ["foo,bar,baz"] + @test split("foo,bar,baz", ',') == ["foo","bar","baz"] + @test split("foo,bar,baz", ",") == ["foo","bar","baz"] + @test split("foo,bar,baz", r",") == ["foo","bar","baz"] + @test split("foo,bar,baz", ','; limit=0) == ["foo","bar","baz"] + @test split("foo,bar,baz", ','; limit=1) == ["foo,bar,baz"] + @test split("foo,bar,baz", ','; limit=2) == ["foo","bar,baz"] + @test split("foo,bar,baz", ','; limit=3) == ["foo","bar","baz"] + @test split("foo,bar", "o,b") == ["fo","ar"] + + @test split("", ',') == [""] + @test split(",", ',') == ["",""] + @test split(",,", ',') == ["","",""] + @test split("", ',' ; keep=false) == [] + @test split(",", ',' ; keep=false) == [] + @test split(",,", ','; keep=false) == [] + + @test split("a b c") == ["a","b","c"] + @test split("a b \t c\n") == ["a","b","c"] + + @test rsplit("foo,bar,baz", 'x') == ["foo,bar,baz"] + @test rsplit("foo,bar,baz", ',') == ["foo","bar","baz"] + @test rsplit("foo,bar,baz", ",") == ["foo","bar","baz"] + @test rsplit("foo,bar,baz", ','; limit=0) == ["foo","bar","baz"] + @test rsplit("foo,bar,baz", ','; limit=1) == ["foo,bar,baz"] + @test rsplit("foo,bar,baz", ','; limit=2) == ["foo,bar","baz"] + @test rsplit("foo,bar,baz", ','; limit=3) == ["foo","bar","baz"] + @test rsplit("foo,bar", "o,b") == ["fo","ar"] + + @test rsplit("", ',') == [""] + @test rsplit(",", ',') == ["",""] + @test rsplit(",,", ',') == ["","",""] + @test rsplit(",,", ','; limit=2) == [",",""] + @test rsplit("", ',' ; keep=false) == [] + @test rsplit(",", ',' ; keep=false) == [] + @test rsplit(",,", ','; keep=false) == [] + + #@test rsplit("a b c") == ["a","b","c"] + #@test rsplit("a b \t c\n") == ["a","b","c"] let str = "a.:.ba..:..cba.:.:.dcba.:." - @test isequal(split(str, ".:."), ["a","ba.",".cba",":.dcba",""]) - @test isequal(split(str, ".:."; keep=false), ["a","ba.",".cba",":.dcba"]) - @test isequal(split(str, ".:."), ["a","ba.",".cba",":.dcba",""]) - @test isequal(split(str, r"\.(:\.)+"), ["a","ba.",".cba","dcba",""]) - @test isequal(split(str, r"\.(:\.)+"; keep=false), ["a","ba.",".cba","dcba"]) - @test isequal(split(str, r"\.+:\.+"), ["a","ba","cba",":.dcba",""]) - @test isequal(split(str, r"\.+:\.+"; keep=false), ["a","ba","cba",":.dcba"]) - - @test isequal(rsplit(str, ".:."), ["a","ba.",".cba.:","dcba",""]) - @test isequal(rsplit(str, ".:."; keep=false), ["a","ba.",".cba.:","dcba"]) - @test isequal(rsplit(str, ".:."; limit=2), ["a.:.ba..:..cba.:.:.dcba", ""]) - @test isequal(rsplit(str, ".:."; limit=3), ["a.:.ba..:..cba.:", "dcba", ""]) - @test isequal(rsplit(str, ".:."; limit=4), ["a.:.ba.", ".cba.:", "dcba", ""]) - @test isequal(rsplit(str, ".:."; limit=5), ["a", "ba.", ".cba.:", "dcba", ""]) - @test isequal(rsplit(str, ".:."; limit=6), ["a", "ba.", ".cba.:", "dcba", ""]) + @test split(str, ".:.") == ["a","ba.",".cba",":.dcba",""] + @test split(str, ".:."; keep=false) == ["a","ba.",".cba",":.dcba"] + @test split(str, ".:.") == ["a","ba.",".cba",":.dcba",""] + @test split(str, r"\.(:\.)+") == ["a","ba.",".cba","dcba",""] + @test split(str, r"\.(:\.)+"; keep=false) == ["a","ba.",".cba","dcba"] + @test split(str, r"\.+:\.+") == ["a","ba","cba",":.dcba",""] + @test split(str, r"\.+:\.+"; keep=false) == ["a","ba","cba",":.dcba"] + + @test rsplit(str, ".:.") == ["a","ba.",".cba.:","dcba",""] + @test rsplit(str, ".:."; keep=false) == ["a","ba.",".cba.:","dcba"] + @test rsplit(str, ".:."; limit=2) == ["a.:.ba..:..cba.:.:.dcba", ""] + @test rsplit(str, ".:."; limit=3) == ["a.:.ba..:..cba.:", "dcba", ""] + @test rsplit(str, ".:."; limit=4) == ["a.:.ba.", ".cba.:", "dcba", ""] + @test rsplit(str, ".:."; limit=5) == ["a", "ba.", ".cba.:", "dcba", ""] + @test rsplit(str, ".:."; limit=6) == ["a", "ba.", ".cba.:", "dcba", ""] end # zero-width splits - @test isequal(rsplit("", ""), [""]) - - @test isequal(split("", ""), [""]) - @test isequal(split("", r""), [""]) - @test isequal(split("abc", ""), ["a","b","c"]) - @test isequal(split("abc", r""), ["a","b","c"]) - @test isequal(split("abcd", r"b?"), ["a","c","d"]) - @test isequal(split("abcd", r"b*"), ["a","c","d"]) - @test isequal(split("abcd", r"b+"), ["a","cd"]) - @test isequal(split("abcd", r"b?c?"), ["a","d"]) - @test isequal(split("abcd", r"[bc]?"), ["a","","d"]) - @test isequal(split("abcd", r"a*"), ["","b","c","d"]) - @test isequal(split("abcd", r"a+"), ["","bcd"]) - @test isequal(split("abcd", r"d*"), ["a","b","c",""]) - @test isequal(split("abcd", r"d+"), ["abc",""]) - @test isequal(split("abcd", r"[ad]?"), ["","b","c",""]) + @test split("", "") == rsplit("", "") == [""] + @test split("abc", "") == rsplit("abc", "") == ["a","b","c"] + @test rsplit("abc", "", limit=2) == ["ab","c"] + @test split("abc", "", limit=2) == ["a","bc"] + + @test split("", r"") == [""] + @test split("abc", r"") == ["a","b","c"] + @test split("abcd", r"b?") == ["a","c","d"] + @test split("abcd", r"b*") == ["a","c","d"] + @test split("abcd", r"b+") == ["a","cd"] + @test split("abcd", r"b?c?") == ["a","d"] + @test split("abcd", r"[bc]?") == ["a","","d"] + @test split("abcd", r"a*") == ["","b","c","d"] + @test split("abcd", r"a+") == ["","bcd"] + @test split("abcd", r"d*") == ["a","b","c",""] + @test split("abcd", r"d+") == ["abc",""] + @test split("abcd", r"[ad]?") == ["","b","c",""] + + # multi-byte unicode characters (issue #26225) + @test split("α β γ", " ") == rsplit("α β γ", " ") == + split("α β γ", isspace) == rsplit("α β γ", isspace) == ["α","β","γ"] + @test split("ö.", ".") == rsplit("ö.", ".") == ["ö",""] + @test split("α β γ", "β") == rsplit("α β γ", "β") == ["α "," γ"] end @testset "replace" begin From fc4071f1da6ef9235af513f238f811d03efc5a60 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Thu, 1 Mar 2018 12:42:19 -0500 Subject: [PATCH 04/28] rm problematic assert introduced by #26238 --- base/strings/util.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/strings/util.jl b/base/strings/util.jl index 39dbb6603ab20..c20ed86fb7aee 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -275,7 +275,7 @@ split(str::T, splitter::Char; _split(str, equalto(splitter), limit, keep, T <: SubString ? T[] : SubString{T}[]) function _split(str::AbstractString, splitter, limit::Integer, keep_empty::Bool, strs::Array) - @assert (i = firstindex(str)) == 1 + i = 1 # firstindex(str) n = lastindex(str) r = coalesce(findfirst(splitter,str), 0) if r != 0:-1 From 4c759375304997199b76cb9d33ad9eba8b4b5f7d Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Thu, 1 Mar 2018 14:22:10 -0500 Subject: [PATCH 05/28] more unicode dotty operators (#26262) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * remve vdots-like punctuation chars; they can be canonicalized later * add \tricolon latex completion for ⁝ * treat ≕ and ⩴ the same --- NEWS.md | 6 ++++++ src/flisp/julia_extensions.c | 1 - src/julia-parser.scm | 6 +++--- stdlib/REPL/src/latex_symbols.jl | 2 ++ 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/NEWS.md b/NEWS.md index 2f1ae1a2bed57..17332744894b1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -208,6 +208,8 @@ Language changes * Underscores for `_italics_` and `__bold__` are now supported by the Base Markdown parser. ([#25564]) + * `…` (`\dots`) and `⁝` (`\tricolon`) are now parsed as binary operators ([#26262]). + Breaking changes ---------------- @@ -230,6 +232,10 @@ This section lists changes that do not have deprecation warnings. * `ntuple(f, n::Integer)` throws `ArgumentError` if `n` is negative. Previously an empty tuple was returned ([#21697]). + * `⋮`, `⋱`, `⋰`, and `⋯` are now parsed as binary operators, not ordinary + identifiers. `≔`, `≕`, and `⩴` now parse with assignment rather than comparison + precedence ([#26262]). + * Juxtaposing string literals (e.g. `"x"y`) is now a syntax error ([#20575]). * `finalizer(function, object)` now returns `object` rather than `nothing` ([#24679]). diff --git a/src/flisp/julia_extensions.c b/src/flisp/julia_extensions.c index 7b9ac64a81dfc..409ba05cd7dfb 100644 --- a/src/flisp/julia_extensions.c +++ b/src/flisp/julia_extensions.c @@ -70,7 +70,6 @@ static int is_wc_cat_id_start(uint32_t wc, utf8proc_category_t cat) ((wc >= 0x2140 && wc <= 0x2144) || // ⅀, ⅁, ⅂, ⅃, ⅄ wc == 0x223f || wc == 0x22be || wc == 0x22bf || // ∿, ⊾, ⊿ wc == 0x22a4 || wc == 0x22a5 || // ⊤ ⊥ - (wc >= 0x22ee && wc <= 0x22f1) || // ⋮, ⋯, ⋰, ⋱ (wc >= 0x2202 && wc <= 0x2233 && (wc == 0x2202 || wc == 0x2205 || wc == 0x2206 || // ∂, ∅, ∆ diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 1ac93141b6406..891406ee62768 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -7,7 +7,7 @@ ;; the way the lexer works, every prefix of an operator must also ;; be an operator. (define prec-assignment - (append! (add-dots '(= += -= *= /= //= |\\=| ^= ÷= %= <<= >>= >>>= |\|=| &= ⊻=)) + (append! (add-dots '(= += -= *= /= //= |\\=| ^= ÷= %= <<= >>= >>>= |\|=| &= ⊻= ≔ ⩴ ≕)) '(:= ~ $=))) ;; comma - higher than assignment outside parentheses, lower when inside (define prec-pair '(=>)) @@ -19,10 +19,10 @@ (define prec-lazy-and '(&&)) (define prec-comparison (append! '(|<:| |>:| in isa) - (add-dots '(> < >= ≥ <= ≤ == === ≡ != ≠ !== ≢ ∈ ∉ ∋ ∌ ⊆ ⊈ ⊂ ⊄ ⊊ ∝ ∊ ∍ ∥ ∦ ∷ ∺ ∻ ∽ ∾ ≁ ≃ ≄ ≅ ≆ ≇ ≈ ≉ ≊ ≋ ≌ ≍ ≎ ≐ ≑ ≒ ≓ ≔ ≕ ≖ ≗ ≘ ≙ ≚ ≛ ≜ ≝ ≞ ≟ ≣ ≦ ≧ ≨ ≩ ≪ ≫ ≬ ≭ ≮ ≯ ≰ ≱ ≲ ≳ ≴ ≵ ≶ ≷ ≸ ≹ ≺ ≻ ≼ ≽ ≾ ≿ ⊀ ⊁ ⊃ ⊅ ⊇ ⊉ ⊋ ⊏ ⊐ ⊑ ⊒ ⊜ ⊩ ⊬ ⊮ ⊰ ⊱ ⊲ ⊳ ⊴ ⊵ ⊶ ⊷ ⋍ ⋐ ⋑ ⋕ ⋖ ⋗ ⋘ ⋙ ⋚ ⋛ ⋜ ⋝ ⋞ ⋟ ⋠ ⋡ ⋢ ⋣ ⋤ ⋥ ⋦ ⋧ ⋨ ⋩ ⋪ ⋫ ⋬ ⋭ ⋲ ⋳ ⋴ ⋵ ⋶ ⋷ ⋸ ⋹ ⋺ ⋻ ⋼ ⋽ ⋾ ⋿ ⟈ ⟉ ⟒ ⦷ ⧀ ⧁ ⧡ ⧣ ⧤ ⧥ ⩦ ⩧ ⩪ ⩫ ⩬ ⩭ ⩮ ⩯ ⩰ ⩱ ⩲ ⩳ ⩴ ⩵ ⩶ ⩷ ⩸ ⩹ ⩺ ⩻ ⩼ ⩽ ⩾ ⩿ ⪀ ⪁ ⪂ ⪃ ⪄ ⪅ ⪆ ⪇ ⪈ ⪉ ⪊ ⪋ ⪌ ⪍ ⪎ ⪏ ⪐ ⪑ ⪒ ⪓ ⪔ ⪕ ⪖ ⪗ ⪘ ⪙ ⪚ ⪛ ⪜ ⪝ ⪞ ⪟ ⪠ ⪡ ⪢ ⪣ ⪤ ⪥ ⪦ ⪧ ⪨ ⪩ ⪪ ⪫ ⪬ ⪭ ⪮ ⪯ ⪰ ⪱ ⪲ ⪳ ⪴ ⪵ ⪶ ⪷ ⪸ ⪹ ⪺ ⪻ ⪼ ⪽ ⪾ ⪿ ⫀ ⫁ ⫂ ⫃ ⫄ ⫅ ⫆ ⫇ ⫈ ⫉ ⫊ ⫋ ⫌ ⫍ ⫎ ⫏ ⫐ ⫑ ⫒ ⫓ ⫔ ⫕ ⫖ ⫗ ⫘ ⫙ ⫷ ⫸ ⫹ ⫺ ⊢ ⊣ ⟂)))) + (add-dots '(> < >= ≥ <= ≤ == === ≡ != ≠ !== ≢ ∈ ∉ ∋ ∌ ⊆ ⊈ ⊂ ⊄ ⊊ ∝ ∊ ∍ ∥ ∦ ∷ ∺ ∻ ∽ ∾ ≁ ≃ ≄ ≅ ≆ ≇ ≈ ≉ ≊ ≋ ≌ ≍ ≎ ≐ ≑ ≒ ≓ ≖ ≗ ≘ ≙ ≚ ≛ ≜ ≝ ≞ ≟ ≣ ≦ ≧ ≨ ≩ ≪ ≫ ≬ ≭ ≮ ≯ ≰ ≱ ≲ ≳ ≴ ≵ ≶ ≷ ≸ ≹ ≺ ≻ ≼ ≽ ≾ ≿ ⊀ ⊁ ⊃ ⊅ ⊇ ⊉ ⊋ ⊏ ⊐ ⊑ ⊒ ⊜ ⊩ ⊬ ⊮ ⊰ ⊱ ⊲ ⊳ ⊴ ⊵ ⊶ ⊷ ⋍ ⋐ ⋑ ⋕ ⋖ ⋗ ⋘ ⋙ ⋚ ⋛ ⋜ ⋝ ⋞ ⋟ ⋠ ⋡ ⋢ ⋣ ⋤ ⋥ ⋦ ⋧ ⋨ ⋩ ⋪ ⋫ ⋬ ⋭ ⋲ ⋳ ⋴ ⋵ ⋶ ⋷ ⋸ ⋹ ⋺ ⋻ ⋼ ⋽ ⋾ ⋿ ⟈ ⟉ ⟒ ⦷ ⧀ ⧁ ⧡ ⧣ ⧤ ⧥ ⩦ ⩧ ⩪ ⩫ ⩬ ⩭ ⩮ ⩯ ⩰ ⩱ ⩲ ⩳ ⩵ ⩶ ⩷ ⩸ ⩹ ⩺ ⩻ ⩼ ⩽ ⩾ ⩿ ⪀ ⪁ ⪂ ⪃ ⪄ ⪅ ⪆ ⪇ ⪈ ⪉ ⪊ ⪋ ⪌ ⪍ ⪎ ⪏ ⪐ ⪑ ⪒ ⪓ ⪔ ⪕ ⪖ ⪗ ⪘ ⪙ ⪚ ⪛ ⪜ ⪝ ⪞ ⪟ ⪠ ⪡ ⪢ ⪣ ⪤ ⪥ ⪦ ⪧ ⪨ ⪩ ⪪ ⪫ ⪬ ⪭ ⪮ ⪯ ⪰ ⪱ ⪲ ⪳ ⪴ ⪵ ⪶ ⪷ ⪸ ⪹ ⪺ ⪻ ⪼ ⪽ ⪾ ⪿ ⫀ ⫁ ⫂ ⫃ ⫄ ⫅ ⫆ ⫇ ⫈ ⫉ ⫊ ⫋ ⫌ ⫍ ⫎ ⫏ ⫐ ⫑ ⫒ ⫓ ⫔ ⫕ ⫖ ⫗ ⫘ ⫙ ⫷ ⫸ ⫹ ⫺ ⊢ ⊣ ⟂)))) (define prec-pipe< '(|.<\|| |<\||)) (define prec-pipe> '(|.\|>| |\|>|)) -(define prec-colon '(: |..|)) +(define prec-colon (append! '(: |..|) (add-dots '(… ⁝ ⋮ ⋱ ⋰ ⋯)))) (define prec-plus (append! '($) (add-dots '(+ - |\|| ⊕ ⊖ ⊞ ⊟ |++| ∪ ∨ ⊔ ± ∓ ∔ ∸ ≂ ≏ ⊎ ⊻ ⊽ ⋎ ⋓ ⧺ ⧻ ⨈ ⨢ ⨣ ⨤ ⨥ ⨦ ⨧ ⨨ ⨩ ⨪ ⨫ ⨬ ⨭ ⨮ ⨹ ⨺ ⩁ ⩂ ⩅ ⩊ ⩌ ⩏ ⩐ ⩒ ⩔ ⩖ ⩗ ⩛ ⩝ ⩡ ⩢ ⩣)))) (define prec-bitshift (add-dots '(<< >> >>>))) diff --git a/stdlib/REPL/src/latex_symbols.jl b/stdlib/REPL/src/latex_symbols.jl index 33737b2204981..339b30496d81b 100644 --- a/stdlib/REPL/src/latex_symbols.jl +++ b/stdlib/REPL/src/latex_symbols.jl @@ -2576,6 +2576,8 @@ const latex_symbols = Dict( "\\smalltriangleright" => "▹", # right triangle, open "\\smalltriangleleft" => "◃", # left triangle, open + "\\tricolon" => "⁝", # tricolon + # fractions "\\1/4" => "¼", # vulgar fraction one quarter "\\1/2" => "½", # vulgar fraction one half From 180111f53155e99fa71bcb461ee562152307720a Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 1 Mar 2018 15:52:19 -0500 Subject: [PATCH 06/28] move Sockets out of Base (#25935) --- .circleci/config.yml | 2 +- base/deprecated.jl | 11 - base/exports.jl | 31 +- base/libuv.jl | 6 - base/stream.jl | 162 +---- base/sysimg.jl | 23 +- doc/src/base/io-network.md | 20 - .../clustermanager/simple/UnixDomainCM.jl | 2 +- stdlib/Distributed/Project.toml | 1 + stdlib/Distributed/src/Distributed.jl | 5 +- stdlib/Distributed/src/precompile.jl | 152 ++--- stdlib/Distributed/test/distributed_exec.jl | 4 +- stdlib/Serialization/src/precompile.jl | 2 - stdlib/Sockets/Project.toml | 2 + stdlib/Sockets/docs/src/index.md | 25 + stdlib/Sockets/src/IPAddr.jl | 253 +++++++ stdlib/Sockets/src/PipeServer.jl | 93 +++ .../Sockets/src/Sockets.jl | 637 ++++-------------- stdlib/Sockets/src/addrinfo.jl | 234 +++++++ .../Sockets/test}/nettest.jl | 2 + .../Sockets/test/runtests.jl | 46 +- test/choosetests.jl | 6 +- test/compile.jl | 2 +- test/read.jl | 3 +- test/spawn.jl | 2 +- 25 files changed, 890 insertions(+), 836 deletions(-) create mode 100644 stdlib/Sockets/Project.toml create mode 100644 stdlib/Sockets/docs/src/index.md create mode 100644 stdlib/Sockets/src/IPAddr.jl create mode 100644 stdlib/Sockets/src/PipeServer.jl rename base/socket.jl => stdlib/Sockets/src/Sockets.jl (52%) create mode 100644 stdlib/Sockets/src/addrinfo.jl rename {test/netload => stdlib/Sockets/test}/nettest.jl (99%) rename test/socket.jl => stdlib/Sockets/test/runtests.jl (91%) diff --git a/.circleci/config.yml b/.circleci/config.yml index a7c08632ffab9..86bea5d71509d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -53,7 +53,7 @@ jobs: /tmp/julia/bin/julia --sysimage-native-code=no -e 'true' && /tmp/julia/bin/julia-debug --sysimage-native-code=no -e 'true' && pushd /tmp/julia/share/julia/test && - /tmp/julia/bin/julia --check-bounds=yes runtests.jl all --skip socket | bar -i 30 && + /tmp/julia/bin/julia --check-bounds=yes runtests.jl all --skip Sockets | bar -i 30 && /tmp/julia/bin/julia --check-bounds=yes runtests.jl LibGit2/online Pkg/pkg Pkg3/pkg download && popd && mkdir /tmp/embedding-test && diff --git a/base/deprecated.jl b/base/deprecated.jl index 44a0107d9f65c..1889ad3426668 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -457,8 +457,6 @@ end @deprecate (convert(::Type{Integer}, x::Enum{T}) where {T<:Integer}) Integer(x) @deprecate (convert(::Type{T}, x::Enum{T2}) where {T<:Integer,T2<:Integer}) T(x) -@deprecate convert(dt::Type{<:Integer}, ip::IPAddr) dt(ip) - function (::Type{T})(arg) where {T} if applicable(convert, T, arg) sig = which(convert, (Type{T}, typeof(arg))).sig @@ -680,15 +678,6 @@ end Broadcast.dotview(A::AbstractArray{<:AbstractArray}, args::Integer...) = getindex(A, args...) # Upon removing deprecations, also enable the @testset "scalar .=" in test/broadcast.jl -@noinline function getaddrinfo(callback::Function, host::AbstractString) - depwarn("`getaddrinfo` with a callback function is deprecated, wrap code in `@async` instead for deferred execution.", :getaddrinfo) - @async begin - r = getaddrinfo(host) - callback(r) - end - nothing -end - # indexing with A[true] will throw an argument error in the future function to_index(i::Bool) depwarn("indexing with Bool values is deprecated. Convert the index to an integer first with `Int(i)`.", (:getindex, :setindex!, :view)) diff --git a/base/exports.jl b/base/exports.jl index 5ef5845dbfacf..156bd0a87dd02 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -616,6 +616,8 @@ export uppercase, # text output + IOContext, + displaysize, dump, print, println, @@ -704,6 +706,7 @@ export put!, isready, fetch, + bind, # missing values coalesce, @@ -793,39 +796,20 @@ export exit, ntuple, -# IP address stuff - @ip_str, - IPAddr, - IPv4, - IPv6, - # I/O and events - accept, - bind, close, - connect, countlines, eachline, eof, fd, fdio, flush, - getaddrinfo, - getalladdrinfo, - getnameinfo, gethostname, - getipaddr, - getpeername, - getsockname, htol, hton, - IOContext, - displaysize, ismarked, isopen, isreadonly, - listen, - listenany, ltoh, mark, bytesavailable, @@ -848,21 +832,18 @@ export redirect_stderr, redirect_stdin, redirect_stdout, - recv, - recvfrom, reset, seek, seekend, seekstart, - send, skip, skipchars, take!, truncate, unmark, + unsafe_read, + unsafe_write, write, - TCPSocket, - UDPSocket, # multimedia I/O AbstractDisplay, @@ -963,9 +944,7 @@ export unsafe_copyto!, unsafe_load, unsafe_pointer_to_objref, - unsafe_read, unsafe_store!, - unsafe_write, # implemented in Random module rand, diff --git a/base/libuv.jl b/base/libuv.jl index 2c551d41cc878..3012755e0982d 100644 --- a/base/libuv.jl +++ b/base/libuv.jl @@ -88,13 +88,7 @@ end function reinit_stdio() global uv_jl_alloc_buf = cfunction(uv_alloc_buf, Cvoid, Tuple{Ptr{Cvoid}, Csize_t, Ptr{Cvoid}}) global uv_jl_readcb = cfunction(uv_readcb, Cvoid, Tuple{Ptr{Cvoid}, Cssize_t, Ptr{Cvoid}}) - global uv_jl_connectioncb = cfunction(uv_connectioncb, Cvoid, Tuple{Ptr{Cvoid}, Cint}) - global uv_jl_connectcb = cfunction(uv_connectcb, Cvoid, Tuple{Ptr{Cvoid}, Cint}) global uv_jl_writecb_task = cfunction(uv_writecb_task, Cvoid, Tuple{Ptr{Cvoid}, Cint}) - global uv_jl_getaddrinfocb = cfunction(uv_getaddrinfocb, Cvoid, Tuple{Ptr{Cvoid}, Cint, Ptr{Cvoid}}) - global uv_jl_getnameinfocb = cfunction(uv_getnameinfocb, Cvoid, Tuple{Ptr{Cvoid}, Cint, Cstring, Cstring}) - global uv_jl_recvcb = cfunction(uv_recvcb, Cvoid, Tuple{Ptr{Cvoid}, Cssize_t, Ptr{Cvoid}, Ptr{Cvoid}, Cuint}) - global uv_jl_sendcb = cfunction(uv_sendcb, Cvoid, Tuple{Ptr{Cvoid}, Cint}) global uv_jl_return_spawn = cfunction(uv_return_spawn, Cvoid, Tuple{Ptr{Cvoid}, Int64, Int32}) global uv_jl_asynccb = cfunction(uv_asynccb, Cvoid, Tuple{Ptr{Cvoid}}) global uv_jl_timercb = cfunction(uv_timercb, Cvoid, Tuple{Ptr{Cvoid}}) diff --git a/base/stream.jl b/base/stream.jl index 775b8852bd1ac..93e9db949ac56 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -148,30 +148,6 @@ function PipeEndpoint() return pipe end -mutable struct PipeServer <: LibuvServer - handle::Ptr{Cvoid} - status::Int - connectnotify::Condition - closenotify::Condition - function PipeServer(handle::Ptr{Cvoid}, status) - p = new(handle, - status, - Condition(), - Condition()) - associate_julia_struct(p.handle, p) - finalizer(uvfinalize, p) - return p - end -end - -function PipeServer() - pipe = PipeServer(Libc.malloc(_sizeof_uv_named_pipe), StatusUninit) - err = ccall(:uv_pipe_init, Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Cint), eventloop(), pipe.handle, 0) - uv_error("failed to create pipe server", err) - pipe.status = StatusInit - return pipe -end - mutable struct TTY <: LibuvStream handle::Ptr{Cvoid} status::Int @@ -240,6 +216,8 @@ unlock(s::LibuvStream) = unlock(s.lock) rawhandle(stream::LibuvStream) = stream.handle unsafe_convert(::Type{Ptr{Cvoid}}, s::Union{LibuvStream, LibuvServer}) = s.handle +const Sockets_mod = Ref{Module}() + function init_stdio(handle::Ptr{Cvoid}) t = ccall(:jl_uv_handle_type, Int32, (Ptr{Cvoid},), handle) if t == UV_FILE @@ -255,7 +233,10 @@ function init_stdio(handle::Ptr{Cvoid}) elseif t == UV_TTY return TTY(handle, StatusOpen) elseif t == UV_TCP - return TCPSocket(handle, StatusOpen) + if !isassigned(Sockets_mod) + Sockets_mod[] = Base.require(Base, :Sockets) + end + return Sockets_mod[].TCPSocket(handle, StatusOpen) elseif t == UV_NAMED_PIPE return PipeEndpoint(handle, StatusOpen) else @@ -435,35 +416,6 @@ get(::TTY, key::Symbol, default) = key === :color ? have_color : default ### Libuv callbacks ### -#from `connect` -function uv_connectcb(conn::Ptr{Cvoid}, status::Cint) - hand = ccall(:jl_uv_connect_handle, Ptr{Cvoid}, (Ptr{Cvoid},), conn) - sock = @handle_as hand LibuvStream - @assert sock.status == StatusConnecting - if status >= 0 - sock.status = StatusOpen - notify(sock.connectnotify) - else - sock.status = StatusInit - err = UVError("connect", status) - notify_error(sock.connectnotify, err) - end - Libc.free(conn) - nothing -end - -# from `listen` -function uv_connectioncb(stream::Ptr{Cvoid}, status::Cint) - sock = @handle_as stream LibuvServer - if status >= 0 - notify(sock.connectnotify) - else - err = UVError("connection", status) - notify_error(sock.connectnotify, err) - end - nothing -end - ## BUFFER ## ## Allocate space in buffer (for immediate use) function alloc_request(buffer::IOBuffer, recommended_size::UInt) @@ -942,108 +894,6 @@ function uv_writecb_task(req::Ptr{Cvoid}, status::Cint) nothing end -## server functions ## - -function accept_nonblock(server::PipeServer, client::PipeEndpoint) - if client.status != StatusInit - error("client is already in use or has been closed") - end - err = ccall(:uv_accept, Int32, (Ptr{Cvoid}, Ptr{Cvoid}), server.handle, client.handle) - if err == 0 - client.status = StatusOpen - end - return err -end - -function accept_nonblock(server::PipeServer) - client = PipeEndpoint() - uv_error("accept", accept_nonblock(server, client) != 0) - return client -end - -function accept(server::LibuvServer, client::LibuvStream) - if server.status != StatusActive - throw(ArgumentError("server not connected, make sure \"listen\" has been called")) - end - while isopen(server) - err = accept_nonblock(server, client) - if err == 0 - return client - elseif err != UV_EAGAIN - uv_error("accept", err) - end - stream_wait(server, server.connectnotify) - end - uv_error("accept", UV_ECONNABORTED) -end - -const BACKLOG_DEFAULT = 511 - -function listen(sock::LibuvServer; backlog::Integer=BACKLOG_DEFAULT) - uv_error("listen", trylisten(sock)) - return sock -end - -function trylisten(sock::LibuvServer; backlog::Integer=BACKLOG_DEFAULT) - check_open(sock) - err = ccall(:uv_listen, Cint, (Ptr{Cvoid}, Cint, Ptr{Cvoid}), - sock, backlog, uv_jl_connectioncb::Ptr{Cvoid}) - sock.status = StatusActive - return err -end - -function bind(server::PipeServer, name::AbstractString) - @assert server.status == StatusInit - err = ccall(:uv_pipe_bind, Int32, (Ptr{Cvoid}, Cstring), - server, name) - if err != 0 - if err != UV_EADDRINUSE && err != UV_EACCES - #TODO: this codepath is currently not tested - throw(UVError("bind",err)) - else - return false - end - end - server.status = StatusOpen - return true -end - -""" - listen(path::AbstractString) -> PipeServer - -Create and listen on a named pipe / UNIX domain socket. -""" -function listen(path::AbstractString) - sock = PipeServer() - bind(sock, path) || throw(ArgumentError("could not listen on path $path")) - return listen(sock) -end - -function connect!(sock::PipeEndpoint, path::AbstractString) - @assert sock.status == StatusInit - req = Libc.malloc(_sizeof_uv_connect) - uv_req_set_data(req, C_NULL) - ccall(:uv_pipe_connect, Cvoid, (Ptr{Cvoid}, Ptr{Cvoid}, Cstring, Ptr{Cvoid}), req, sock.handle, path, uv_jl_connectcb::Ptr{Cvoid}) - sock.status = StatusConnecting - return sock -end - -function connect(sock::LibuvStream, args...) - connect!(sock, args...) - wait_connected(sock) - return sock -end - -# Libuv will internally reset read/writability, which is uses to -# mark that this is an invalid pipe. - -""" - connect(path::AbstractString) -> PipeEndpoint - -Connect to the named pipe / UNIX domain socket at `path`. -""" -connect(path::AbstractString) = connect(PipeEndpoint(), path) - _fd(x::IOStream) = RawFD(fd(x)) function _fd(x::Union{LibuvStream, LibuvServer}) diff --git a/base/sysimg.jl b/base/sysimg.jl index c952f7a83dca2..77244c36a867e 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -353,7 +353,6 @@ function randn end # I/O include("stream.jl") -include("socket.jl") include("filesystem.jl") using .Filesystem include("process.jl") @@ -527,6 +526,7 @@ let :Markdown, :LibGit2, :Logging, + :Sockets, :Printf, :Profile, @@ -891,6 +891,27 @@ end @eval @deprecate_stdlib $(Symbol("@code_lowered")) InteractiveUtils true @eval @deprecate_stdlib $(Symbol("@code_llvm")) InteractiveUtils true @eval @deprecate_stdlib $(Symbol("@code_native")) InteractiveUtils true + + @eval @deprecate_stdlib $(Symbol("@ip_str")) Sockets true + @deprecate_stdlib IPAddr Sockets true + @deprecate_stdlib IPv4 Sockets true + @deprecate_stdlib IPv6 Sockets true + @deprecate_stdlib accept Sockets true + @deprecate_stdlib connect Sockets true + @deprecate_stdlib getaddrinfo Sockets true + @deprecate_stdlib getalladdrinfo Sockets true + @deprecate_stdlib getnameinfo Sockets true + @deprecate_stdlib getipaddr Sockets true + @deprecate_stdlib getpeername Sockets true + @deprecate_stdlib getsockname Sockets true + @deprecate_stdlib listen Sockets true + @deprecate_stdlib listenany Sockets true + @deprecate_stdlib recv Sockets true + @deprecate_stdlib recvfrom Sockets true + @deprecate_stdlib send Sockets true + @deprecate_stdlib TCPSocket Sockets true + @deprecate_stdlib UDPSocket Sockets true + end end diff --git a/doc/src/base/io-network.md b/doc/src/base/io-network.md index b28cf9d0bfde5..c99684c3bd698 100644 --- a/doc/src/base/io-network.md +++ b/doc/src/base/io-network.md @@ -126,27 +126,7 @@ Base.Multimedia.istextmime ## Network I/O ```@docs -Base.connect(::TCPSocket, ::Integer) -Base.connect(::AbstractString) -Base.listen(::Any) -Base.listen(::AbstractString) -Base.getaddrinfo -Base.getalladdrinfo -Base.getnameinfo -Base.getsockname -Base.getpeername -Base.IPv4 -Base.IPv6 -Base.TCPSocket -Base.UDPSocket Base.bytesavailable -Base.accept -Base.listenany -Base.bind -Base.send -Base.recv -Base.recvfrom -Base.setopt Base.ntoh Base.hton Base.ltoh diff --git a/examples/clustermanager/simple/UnixDomainCM.jl b/examples/clustermanager/simple/UnixDomainCM.jl index 29eb4f1975720..5426a64010a04 100644 --- a/examples/clustermanager/simple/UnixDomainCM.jl +++ b/examples/clustermanager/simple/UnixDomainCM.jl @@ -1,6 +1,6 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -using Distributed +using Sockets, Distributed import Distributed: launch, manage, connect, exit mutable struct UnixDomainCM <: ClusterManager diff --git a/stdlib/Distributed/Project.toml b/stdlib/Distributed/Project.toml index f4b1d7014bf49..f369cc1bf1e3a 100644 --- a/stdlib/Distributed/Project.toml +++ b/stdlib/Distributed/Project.toml @@ -5,3 +5,4 @@ uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +Sockets = "6462fe0b-24de-5631-8697-dd941f90decc" diff --git a/stdlib/Distributed/src/Distributed.jl b/stdlib/Distributed/src/Distributed.jl index 02f1c86aae1e2..021d220302107 100644 --- a/stdlib/Distributed/src/Distributed.jl +++ b/stdlib/Distributed/src/Distributed.jl @@ -9,7 +9,7 @@ module Distributed # imports for extension import Base: getindex, wait, put!, take!, fetch, isready, push!, length, - hash, ==, connect, kill, close, showerror + hash, ==, kill, close, showerror # imports for use using Base: Process, Semaphore, JLOptions, AnyDict, buffer_writes, wait_connected, @@ -18,8 +18,9 @@ using Base: Process, Semaphore, JLOptions, AnyDict, buffer_writes, wait_connecte AsyncGenerator, acquire, release, invokelatest, shell_escape_posixly, uv_error, coalesce, notnothing -using Serialization +using Serialization, Sockets import Serialization: serialize, deserialize +import Sockets: connect # NOTE: clusterserialize.jl imports additional symbols from Serialization for use diff --git a/stdlib/Distributed/src/precompile.jl b/stdlib/Distributed/src/precompile.jl index 842d0403b3583..fe2b32653fa2f 100644 --- a/stdlib/Distributed/src/precompile.jl +++ b/stdlib/Distributed/src/precompile.jl @@ -36,7 +36,7 @@ precompile(Tuple{typeof(Distributed.launch), Distributed.LocalManager, Base.Dict precompile(Tuple{typeof(Distributed.start_worker), Base.PipeEndpoint, String}) precompile(Tuple{typeof(Distributed.socket_reuse_port)}) precompile(Tuple{typeof(Distributed.flush_gc_msgs)}) -precompile(Tuple{typeof(Distributed.disable_nagle), Base.TCPServer}) +precompile(Tuple{typeof(Distributed.disable_nagle), Sockets.TCPServer}) precompile(Tuple{typeof(Distributed.next_tunnel_port)}) precompile(Tuple{typeof(Base._delete!), Base.Dict{Int64, Union{Distributed.Worker, Distributed.LocalProcess}}, Int64}) precompile(Tuple{typeof(Distributed.send_msg_), Distributed.Worker, Distributed.MsgHeader, Distributed.JoinPGRPMsg, Bool}) @@ -44,14 +44,14 @@ precompile(Tuple{typeof(Distributed.send_msg_now), Distributed.Worker, Distribut precompile(Tuple{typeof(Distributed.connect_w2w), Int64, Distributed.WorkerConfig}) precompile(Tuple{typeof(Distributed.create_worker), Distributed.LocalManager, Distributed.WorkerConfig}) precompile(Tuple{typeof(Distributed.setup_launched_worker), Distributed.LocalManager, Distributed.WorkerConfig, Array{Int64, 1}}) -precompile(Tuple{typeof(Base.connect), Distributed.LocalManager, Int64, Distributed.WorkerConfig}) +precompile(Tuple{typeof(Sockets.connect), Distributed.LocalManager, Int64, Distributed.WorkerConfig}) precompile(Tuple{typeof(Distributed.read_worker_host_port), Base.Pipe}) precompile(Tuple{typeof(Distributed.parse_connection_info), String}) precompile(Tuple{typeof(Distributed.connect_to_worker), Base.SubString{String}, Int16}) -precompile(Tuple{typeof(Distributed.process_messages), Base.TCPSocket, Base.TCPSocket, Bool}) -precompile(Tuple{getfield(Core, Symbol("#kw#Type")), Array{Any, 1}, Type{Distributed.Worker}, Int64, Base.TCPSocket, Base.TCPSocket, Distributed.LocalManager}) -precompile(Tuple{typeof(Distributed.worker_id_from_socket), Base.TCPSocket}) -precompile(Tuple{Type{Distributed.ClusterSerializer{Base.TCPSocket}}, Base.TCPSocket}) +precompile(Tuple{typeof(Distributed.process_messages), Sockets.TCPSocket, Sockets.TCPSocket, Bool}) +precompile(Tuple{getfield(Core, Symbol("#kw#Type")), Array{Any, 1}, Type{Distributed.Worker}, Int64, Sockets.TCPSocket, Sockets.TCPSocket, Distributed.LocalManager}) +precompile(Tuple{typeof(Distributed.worker_id_from_socket), Sockets.TCPSocket}) +precompile(Tuple{Type{Distributed.ClusterSerializer{Sockets.TCPSocket}}, Sockets.TCPSocket}) precompile(Tuple{typeof(Distributed.send_msg_), Distributed.Worker, Distributed.MsgHeader, Distributed.ResultMsg, Bool}) precompile(Tuple{typeof(Distributed.send_msg_now), Distributed.Worker, Distributed.MsgHeader, Distributed.ResultMsg}) precompile(Tuple{Type{Core.Compiler.Generator{I, F} where F where I}, Type{Core.Compiler.Const}, Tuple{Int64, typeof(Distributed.rmprocs)}}) @@ -74,9 +74,9 @@ precompile(Tuple{typeof(Core.Compiler.indexed_next), Tuple{typeof(Distributed.rm precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Distributed.rmprocs), Int64}, Int64}) precompile(Tuple{typeof(Distributed.register_worker_streams), Distributed.Worker}) precompile(Tuple{typeof(Distributed.register_worker_streams), Distributed.LocalProcess}) -precompile(Tuple{Type{Distributed.ClusterSerializer{Base.TCPSocket}}, Base.TCPSocket}) -precompile(Tuple{typeof(Distributed.worker_id_from_socket), Base.TCPSocket}) -precompile(Tuple{typeof(Base.convert), Type{Distributed.ClusterSerializer{I} where I<:IO}, Distributed.ClusterSerializer{Base.TCPSocket}}) +precompile(Tuple{Type{Distributed.ClusterSerializer{Sockets.TCPSocket}}, Sockets.TCPSocket}) +precompile(Tuple{typeof(Distributed.worker_id_from_socket), Sockets.TCPSocket}) +precompile(Tuple{typeof(Base.convert), Type{Distributed.ClusterSerializer{I} where I<:IO}, Distributed.ClusterSerializer{Sockets.TCPSocket}}) precompile(Tuple{typeof(Base.convert), Type{Distributed.ClusterManager}, Distributed.LocalManager}) precompile(Tuple{typeof(Base.convert), Type{Distributed.WorkerConfig}, Distributed.WorkerConfig}) precompile(Tuple{typeof(Base.get), Base.Dict{Any, Any}, Distributed.RRID, Bool}) @@ -97,47 +97,47 @@ precompile(Tuple{getfield(Distributed, Symbol("#kw##remote_do")), Array{Any, 1}, precompile(Tuple{getfield(Distributed, Symbol("#kw##remote_do")), Array{Any, 1}, typeof(Distributed.remote_do), typeof(Distributed.rmprocs), Distributed.LocalProcess, Int64}) precompile(Tuple{Type{Distributed.ResultMsg}, Distributed.RemoteException}) precompile(Tuple{Type{Distributed.ResultMsg}, Symbol}) -precompile(Tuple{typeof(Distributed.send_msg_now), Base.TCPSocket, Distributed.MsgHeader, Distributed.ResultMsg}) +precompile(Tuple{typeof(Distributed.send_msg_now), Sockets.TCPSocket, Distributed.MsgHeader, Distributed.ResultMsg}) precompile(Tuple{typeof(Base._delete!), Base.Dict{Int64, Union{Distributed.Worker, Distributed.LocalProcess}}, Int64}) precompile(Tuple{typeof(Distributed.def_rv_channel)}) precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Distributed.RemoteValue, Distributed.RRID}) precompile(Tuple{typeof(Base.ht_keyindex2!), Base.Dict{Any, Any}, Distributed.RRID}) precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, Distributed.RemoteValue, Distributed.RRID, Int64}) precompile(Tuple{typeof(Base.notify), Base.Condition, Distributed.ProcessExitedException, Bool, Bool}) -precompile(Tuple{typeof(Distributed.process_messages), Base.TCPSocket, Base.TCPSocket, Bool}) +precompile(Tuple{typeof(Distributed.process_messages), Sockets.TCPSocket, Sockets.TCPSocket, Bool}) precompile(Tuple{typeof(Base.pop!), Base.Dict{Int64, Union{Distributed.Worker, Distributed.LocalProcess}}, Int64, Nothing}) precompile(Tuple{typeof(Distributed.send_connection_hdr), Distributed.Worker, Bool}) precompile(Tuple{typeof(Distributed.deregister_worker), Distributed.ProcessGroup, Int64}) -precompile(Tuple{typeof(Distributed.process_hdr), Base.TCPSocket, Bool}) -precompile(Tuple{typeof(Distributed.deserialize_msg), Distributed.ClusterSerializer{Base.TCPSocket}}) +precompile(Tuple{typeof(Distributed.process_hdr), Sockets.TCPSocket, Bool}) +precompile(Tuple{typeof(Distributed.deserialize_msg), Distributed.ClusterSerializer{Sockets.TCPSocket}}) precompile(Tuple{typeof(Distributed.null_id), Distributed.RRID}) -precompile(Tuple{typeof(Distributed.deliver_result), Base.TCPSocket, Symbol, Distributed.RRID, Distributed.RemoteException}) -precompile(Tuple{typeof(Distributed.disable_nagle), Base.TCPSocket}) -precompile(Tuple{typeof(Distributed.message_handler_loop), Base.TCPSocket, Base.TCPSocket, Bool}) -precompile(Tuple{typeof(Distributed.process_tcp_streams), Base.TCPSocket, Base.TCPSocket, Bool}) +precompile(Tuple{typeof(Distributed.deliver_result), Sockets.TCPSocket, Symbol, Distributed.RRID, Distributed.RemoteException}) +precompile(Tuple{typeof(Distributed.disable_nagle), Sockets.TCPSocket}) +precompile(Tuple{typeof(Distributed.message_handler_loop), Sockets.TCPSocket, Sockets.TCPSocket, Bool}) +precompile(Tuple{typeof(Distributed.process_tcp_streams), Sockets.TCPSocket, Sockets.TCPSocket, Bool}) precompile(Tuple{Type{Distributed.JoinPGRPMsg}, Int64, Array{Union{Tuple{Any, Int64}, Tuple{Tuple{}, Any, Bool}}, 1}, Symbol, Bool}) -precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Base.TCPSocket}, Distributed.JoinPGRPMsg}) -precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Base.TCPSocket}, Int64}) -precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Base.TCPSocket}, Array{Union{Tuple{Any, Int64}, Tuple{Tuple{}, Any, Bool}}, 1}}) -precompile(Tuple{typeof(Serialization.should_send_whole_type), Distributed.ClusterSerializer{Base.TCPSocket}, Type{Any}}) -precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Base.TCPSocket}, Core.SimpleVector}) -precompile(Tuple{typeof(Serialization.serialize_type_data), Distributed.ClusterSerializer{Base.TCPSocket}, Type{Any}, Bool}) -precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Base.TCPSocket}, Type{Any}}) -precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Base.TCPSocket}, Tuple{Int64}}) -precompile(Tuple{typeof(Serialization.serialize_cycle), Distributed.ClusterSerializer{Base.TCPSocket}, Type{Union{Tuple{Any, Int64}, Tuple{Tuple{}, Any, Bool}}}}) -precompile(Tuple{typeof(Serialization.serialize_type), Distributed.ClusterSerializer{Base.TCPSocket}, DataType}) -precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Base.TCPSocket}, Bool}) -precompile(Tuple{typeof(Distributed.serialize_global_from_main), Distributed.ClusterSerializer{Base.TCPSocket}, Symbol}) -precompile(Tuple{typeof(Serialization.serialize_mod_names), Distributed.ClusterSerializer{Base.TCPSocket}, Module}) -precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Base.TCPSocket}, Symbol}) -precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Base.TCPSocket}, Module}) -precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Base.TCPSocket}, Array{Any, 1}}) -precompile(Tuple{typeof(Serialization.serialize_cycle), Distributed.ClusterSerializer{Base.TCPSocket}, Core.TypeName}) -precompile(Tuple{typeof(Serialization.serialize_typename), Distributed.ClusterSerializer{Base.TCPSocket}, Core.TypeName}) -precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Base.TCPSocket}, Array{Symbol, 1}}) -precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Base.TCPSocket}, Core.TypeName}) -precompile(Tuple{typeof(Serialization.serialize_cycle_header), Distributed.ClusterSerializer{Base.TCPSocket}, Type{Union{Tuple{Any, Int64}, Tuple{Tuple{}, Any, Bool}}}}) -precompile(Tuple{typeof(Serialization.serialize_any), Distributed.ClusterSerializer{Base.TCPSocket}, Type{Union{Tuple{Any, Int64}, Tuple{Tuple{}, Any, Bool}}}}) +precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Distributed.JoinPGRPMsg}) +precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Int64}) +precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Array{Union{Tuple{Any, Int64}, Tuple{Tuple{}, Any, Bool}}, 1}}) +precompile(Tuple{typeof(Serialization.should_send_whole_type), Distributed.ClusterSerializer{Sockets.TCPSocket}, Type{Any}}) +precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Core.SimpleVector}) +precompile(Tuple{typeof(Serialization.serialize_type_data), Distributed.ClusterSerializer{Sockets.TCPSocket}, Type{Any}, Bool}) +precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Type{Any}}) +precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Tuple{Int64}}) +precompile(Tuple{typeof(Serialization.serialize_cycle), Distributed.ClusterSerializer{Sockets.TCPSocket}, Type{Union{Tuple{Any, Int64}, Tuple{Tuple{}, Any, Bool}}}}) +precompile(Tuple{typeof(Serialization.serialize_type), Distributed.ClusterSerializer{Sockets.TCPSocket}, DataType}) +precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Bool}) +precompile(Tuple{typeof(Distributed.serialize_global_from_main), Distributed.ClusterSerializer{Sockets.TCPSocket}, Symbol}) +precompile(Tuple{typeof(Serialization.serialize_mod_names), Distributed.ClusterSerializer{Sockets.TCPSocket}, Module}) +precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Symbol}) +precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Module}) +precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Array{Any, 1}}) +precompile(Tuple{typeof(Serialization.serialize_cycle), Distributed.ClusterSerializer{Sockets.TCPSocket}, Core.TypeName}) +precompile(Tuple{typeof(Serialization.serialize_typename), Distributed.ClusterSerializer{Sockets.TCPSocket}, Core.TypeName}) +precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Array{Symbol, 1}}) +precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Core.TypeName}) +precompile(Tuple{typeof(Serialization.serialize_cycle_header), Distributed.ClusterSerializer{Sockets.TCPSocket}, Type{Union{Tuple{Any, Int64}, Tuple{Tuple{}, Any, Bool}}}}) +precompile(Tuple{typeof(Serialization.serialize_any), Distributed.ClusterSerializer{Sockets.TCPSocket}, Type{Union{Tuple{Any, Int64}, Tuple{Tuple{}, Any, Bool}}}}) precompile(Tuple{typeof(Distributed.send_msg_), Distributed.Worker, Distributed.MsgHeader, Distributed.ResultMsg, Bool}) precompile(Tuple{typeof(Distributed.send_msg_now), Distributed.Worker, Distributed.MsgHeader, Distributed.ResultMsg}) precompile(Tuple{Type{Core.Compiler.Generator{I, F} where F where I}, Type{Core.Compiler.Const}, Tuple{Int64, typeof(Distributed.rmprocs)}}) @@ -158,12 +158,12 @@ precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Int64, typeof(Distributed precompile(Tuple{typeof(Core.Compiler.start), Tuple{typeof(Distributed.rmprocs), Int64}}) precompile(Tuple{typeof(Core.Compiler.indexed_next), Tuple{typeof(Distributed.rmprocs), Int64}, Int64, Int64}) precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Distributed.rmprocs), Int64}, Int64}) -precompile(Tuple{typeof(Serialization.deserialize), Distributed.ClusterSerializer{Base.TCPSocket}}) -precompile(Tuple{typeof(Serialization.deserialize_cycle), Distributed.ClusterSerializer{Base.TCPSocket}, Expr}) -precompile(Tuple{typeof(Serialization.handle_deserialize), Distributed.ClusterSerializer{Base.TCPSocket}, Int32}) -precompile(Tuple{typeof(Serialization.deserialize_array), Distributed.ClusterSerializer{Base.TCPSocket}}) -precompile(Tuple{typeof(Serialization.deserialize_datatype), Distributed.ClusterSerializer{Base.TCPSocket}}) -precompile(Tuple{typeof(Serialization.deserialize_expr), Distributed.ClusterSerializer{Base.TCPSocket}, Int64}) +precompile(Tuple{typeof(Serialization.deserialize), Distributed.ClusterSerializer{Sockets.TCPSocket}}) +precompile(Tuple{typeof(Serialization.deserialize_cycle), Distributed.ClusterSerializer{Sockets.TCPSocket}, Expr}) +precompile(Tuple{typeof(Serialization.handle_deserialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Int32}) +precompile(Tuple{typeof(Serialization.deserialize_array), Distributed.ClusterSerializer{Sockets.TCPSocket}}) +precompile(Tuple{typeof(Serialization.deserialize_datatype), Distributed.ClusterSerializer{Sockets.TCPSocket}}) +precompile(Tuple{typeof(Serialization.deserialize_expr), Distributed.ClusterSerializer{Sockets.TCPSocket}, Int64}) precompile(Tuple{typeof(Core.Compiler.isbits), Tuple{Int64, typeof(Distributed.rmprocs)}}) precompile(Tuple{Type{Core.Compiler.Generator{I, F} where F where I}, Type{QuoteNode}, Tuple{Int64, typeof(Distributed.rmprocs)}}) precompile(Tuple{Type{Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{QuoteNode}}}, Type{QuoteNode}, Tuple{Int64, typeof(Distributed.rmprocs)}}) @@ -180,43 +180,43 @@ precompile(Tuple{getfield(Distributed, Symbol("#kw##remote_do")), Array{Any, 1}, precompile(Tuple{getfield(Distributed, Symbol("#kw##remote_do")), Array{Any, 1}, typeof(Distributed.remote_do), typeof(Distributed.rmprocs), Distributed.LocalProcess, Int64}) precompile(Tuple{Type{Distributed.ResultMsg}, Distributed.RemoteException}) precompile(Tuple{Type{Distributed.ResultMsg}, Symbol}) -precompile(Tuple{typeof(Distributed.send_msg_now), Base.TCPSocket, Distributed.MsgHeader, Distributed.ResultMsg}) +precompile(Tuple{typeof(Distributed.send_msg_now), Sockets.TCPSocket, Distributed.MsgHeader, Distributed.ResultMsg}) precompile(Tuple{typeof(Base.notify), Base.Condition, Distributed.ProcessExitedException, Bool, Bool}) precompile(Tuple{typeof(Base.pop!), Base.Dict{Int64, Union{Distributed.Worker, Distributed.LocalProcess}}, Int64, Nothing}) precompile(Tuple{typeof(Distributed.deregister_worker), Distributed.ProcessGroup, Int64}) -precompile(Tuple{typeof(Distributed.process_hdr), Base.TCPSocket, Bool}) +precompile(Tuple{typeof(Distributed.process_hdr), Sockets.TCPSocket, Bool}) precompile(Tuple{typeof(Distributed.null_id), Distributed.RRID}) -precompile(Tuple{typeof(Distributed.deliver_result), Base.TCPSocket, Symbol, Distributed.RRID, Distributed.RemoteException}) -precompile(Tuple{typeof(Distributed.disable_nagle), Base.TCPSocket}) -precompile(Tuple{typeof(Distributed.message_handler_loop), Base.TCPSocket, Base.TCPSocket, Bool}) -precompile(Tuple{typeof(Distributed.process_tcp_streams), Base.TCPSocket, Base.TCPSocket, Bool}) -precompile(Tuple{typeof(Serialization.deserialize), Distributed.ClusterSerializer{Base.TCPSocket}, Type{Union}}) -precompile(Tuple{typeof(Serialization.deserialize), Distributed.ClusterSerializer{Base.TCPSocket}, Type{Module}}) -precompile(Tuple{typeof(Serialization.deserialize), Distributed.ClusterSerializer{Base.TCPSocket}, Type{Core.SimpleVector}}) +precompile(Tuple{typeof(Distributed.deliver_result), Sockets.TCPSocket, Symbol, Distributed.RRID, Distributed.RemoteException}) +precompile(Tuple{typeof(Distributed.disable_nagle), Sockets.TCPSocket}) +precompile(Tuple{typeof(Distributed.message_handler_loop), Sockets.TCPSocket, Sockets.TCPSocket, Bool}) +precompile(Tuple{typeof(Distributed.process_tcp_streams), Sockets.TCPSocket, Sockets.TCPSocket, Bool}) +precompile(Tuple{typeof(Serialization.deserialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Type{Union}}) +precompile(Tuple{typeof(Serialization.deserialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Type{Module}}) +precompile(Tuple{typeof(Serialization.deserialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Type{Core.SimpleVector}}) precompile(Tuple{Type{Distributed.JoinPGRPMsg}, Int64, Array{Union{Tuple{Any, Int64}, Tuple{Tuple{}, Any, Bool}}, 1}, Symbol, Bool}) -precompile(Tuple{typeof(Distributed.handle_msg), Distributed.JoinPGRPMsg, Distributed.MsgHeader, Base.TCPSocket, Base.TCPSocket, Base.VersionNumber}) +precompile(Tuple{typeof(Distributed.handle_msg), Distributed.JoinPGRPMsg, Distributed.MsgHeader, Sockets.TCPSocket, Sockets.TCPSocket, Base.VersionNumber}) precompile(Tuple{Type{Distributed.WorkerConfig}}) precompile(Tuple{typeof(Distributed.send_msg_), Distributed.Worker, Distributed.MsgHeader, Distributed.JoinCompleteMsg, Bool}) precompile(Tuple{typeof(Distributed.send_msg_now), Distributed.Worker, Distributed.MsgHeader, Distributed.JoinCompleteMsg}) -precompile(Tuple{getfield(Core, Symbol("#kw#Type")), Array{Any, 1}, Type{Distributed.Worker}, Int64, Base.TCPSocket, Base.TCPSocket, Distributed.DefaultClusterManager}) +precompile(Tuple{getfield(Core, Symbol("#kw#Type")), Array{Any, 1}, Type{Distributed.Worker}, Int64, Sockets.TCPSocket, Sockets.TCPSocket, Distributed.DefaultClusterManager}) precompile(Tuple{typeof(Distributed.register_worker_streams), Distributed.Worker}) precompile(Tuple{typeof(Distributed.register_worker_streams), Distributed.LocalProcess}) -precompile(Tuple{typeof(Base.convert), Type{Distributed.ClusterSerializer{I} where I<:IO}, Distributed.ClusterSerializer{Base.TCPSocket}}) +precompile(Tuple{typeof(Base.convert), Type{Distributed.ClusterSerializer{I} where I<:IO}, Distributed.ClusterSerializer{Sockets.TCPSocket}}) precompile(Tuple{typeof(Base.convert), Type{Distributed.ClusterManager}, Distributed.DefaultClusterManager}) precompile(Tuple{typeof(Base.convert), Type{Distributed.WorkerConfig}, Distributed.WorkerConfig}) precompile(Tuple{typeof(Distributed.send_connection_hdr), Distributed.Worker, Bool}) precompile(Tuple{typeof(Distributed.manage), Distributed.LocalManager, Int64, Distributed.WorkerConfig, Symbol}) -precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Base.TCPSocket}, Distributed.JoinCompleteMsg}) -precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Base.TCPSocket}, Int64}) -precompile(Tuple{typeof(Serialization.deserialize), Distributed.ClusterSerializer{Base.TCPSocket}}) -precompile(Tuple{typeof(Serialization.deserialize_cycle), Distributed.ClusterSerializer{Base.TCPSocket}, Expr}) -precompile(Tuple{typeof(Serialization.handle_deserialize), Distributed.ClusterSerializer{Base.TCPSocket}, Int32}) -precompile(Tuple{typeof(Serialization.deserialize_array), Distributed.ClusterSerializer{Base.TCPSocket}}) -precompile(Tuple{typeof(Serialization.deserialize_datatype), Distributed.ClusterSerializer{Base.TCPSocket}}) -precompile(Tuple{typeof(Serialization.deserialize_expr), Distributed.ClusterSerializer{Base.TCPSocket}, Int64}) -precompile(Tuple{typeof(Serialization.deserialize), Distributed.ClusterSerializer{Base.TCPSocket}, Type{Int64}}) +precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Distributed.JoinCompleteMsg}) +precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Int64}) +precompile(Tuple{typeof(Serialization.deserialize), Distributed.ClusterSerializer{Sockets.TCPSocket}}) +precompile(Tuple{typeof(Serialization.deserialize_cycle), Distributed.ClusterSerializer{Sockets.TCPSocket}, Expr}) +precompile(Tuple{typeof(Serialization.handle_deserialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Int32}) +precompile(Tuple{typeof(Serialization.deserialize_array), Distributed.ClusterSerializer{Sockets.TCPSocket}}) +precompile(Tuple{typeof(Serialization.deserialize_datatype), Distributed.ClusterSerializer{Sockets.TCPSocket}}) +precompile(Tuple{typeof(Serialization.deserialize_expr), Distributed.ClusterSerializer{Sockets.TCPSocket}, Int64}) +precompile(Tuple{typeof(Serialization.deserialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Type{Int64}}) precompile(Tuple{Type{Distributed.JoinCompleteMsg}, Int64, Int64}) -precompile(Tuple{typeof(Distributed.handle_msg), Distributed.JoinCompleteMsg, Distributed.MsgHeader, Base.TCPSocket, Base.TCPSocket, Base.VersionNumber}) +precompile(Tuple{typeof(Distributed.handle_msg), Distributed.JoinCompleteMsg, Distributed.MsgHeader, Sockets.TCPSocket, Sockets.TCPSocket, Base.VersionNumber}) precompile(Tuple{typeof(Base.hash), Distributed.RemoteChannel{Base.Channel{Any}}, UInt64}) precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{WeakRef, Nothing}, Distributed.RemoteChannel{Base.Channel{Any}}}) precompile(Tuple{typeof(Distributed.remotecall_fetch), typeof(Distributed.put_ref), Distributed.Worker, Distributed.RRID, Distributed.WorkerPool}) @@ -235,18 +235,18 @@ precompile(Tuple{typeof(Base.put!), Base.Channel{Any}, Distributed.WorkerPool}) precompile(Tuple{typeof(Base.put_buffered), Base.Channel{Any}, Distributed.WorkerPool}) precompile(Tuple{typeof(Base.put_unbuffered), Base.Channel{Any}, Distributed.WorkerPool}) precompile(Tuple{typeof(Base.push!), Distributed.WorkerPool, Int64}) -precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Base.TCPSocket}, Distributed.RemoteDoMsg}) -precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Base.TCPSocket}, typeof(Distributed.set_valid_processes)}) -precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Base.TCPSocket}, Tuple{Array{Int64, 1}}}) -precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Base.TCPSocket}, Array{Int64, 1}}) -precompile(Tuple{typeof(Serialization.deserialize), Distributed.ClusterSerializer{Base.TCPSocket}, Type{typeof(Distributed.set_valid_processes)}}) -precompile(Tuple{typeof(Distributed.handle_msg), Distributed.RemoteDoMsg, Distributed.MsgHeader, Base.TCPSocket, Base.TCPSocket, Base.VersionNumber}) +precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Distributed.RemoteDoMsg}) +precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, typeof(Distributed.set_valid_processes)}) +precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Tuple{Array{Int64, 1}}}) +precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Array{Int64, 1}}) +precompile(Tuple{typeof(Serialization.deserialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Type{typeof(Distributed.set_valid_processes)}}) +precompile(Tuple{typeof(Distributed.handle_msg), Distributed.RemoteDoMsg, Distributed.MsgHeader, Sockets.TCPSocket, Sockets.TCPSocket, Base.VersionNumber}) precompile(Tuple{typeof(Distributed.set_valid_processes), Array{Int64, 1}}) precompile(Tuple{typeof(Distributed._rmprocs), Array{Int64, 1}, Float64}) precompile(Tuple{typeof(Base.kill), Distributed.LocalManager, Int64, Distributed.WorkerConfig}) -precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Base.TCPSocket}, typeof(Base.exit)}) -precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Base.TCPSocket}, Tuple{}}) -precompile(Tuple{typeof(Serialization.deserialize), Distributed.ClusterSerializer{Base.TCPSocket}, Type{typeof(Base.exit)}}) +precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, typeof(Base.exit)}) +precompile(Tuple{typeof(Serialization.serialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Tuple{}}) +precompile(Tuple{typeof(Serialization.deserialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Type{typeof(Base.exit)}}) precompile(Tuple{typeof(Distributed.finalize_ref), Distributed.RemoteChannel{Base.Channel{Any}}}) precompile(Tuple{typeof(Distributed.send_del_client), Distributed.RemoteChannel{Base.Channel{Any}}}) precompile(Tuple{typeof(Base.:(==)), Distributed.RemoteChannel{Base.Channel{Any}}, Distributed.RemoteChannel{Base.Channel{Any}}}) diff --git a/stdlib/Distributed/test/distributed_exec.jl b/stdlib/Distributed/test/distributed_exec.jl index 331c883d3671c..a4cb9b34d10d2 100644 --- a/stdlib/Distributed/test/distributed_exec.jl +++ b/stdlib/Distributed/test/distributed_exec.jl @@ -1,6 +1,6 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -using Test, Distributed, Random, Serialization +using Test, Distributed, Random, Serialization, Sockets import Distributed: launch, manage include(joinpath(Sys.BINDIR, "..", "share", "julia", "test", "testenv.jl")) @@ -1460,7 +1460,7 @@ function reuseport_tests() ports_higher = [] # ports of pids higher than myid() for w in Distributed.PGRP.workers w.id == myid() && continue - port = Base._sockname(w.r_stream, true)[2] + port = Sockets._sockname(w.r_stream, true)[2] if (w.id == 1) # master connects to workers push!(ports_higher, port) diff --git a/stdlib/Serialization/src/precompile.jl b/stdlib/Serialization/src/precompile.jl index d25f4945b1c9c..7bbc18a44c29f 100644 --- a/stdlib/Serialization/src/precompile.jl +++ b/stdlib/Serialization/src/precompile.jl @@ -1,8 +1,6 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -precompile(Tuple{typeof(Serialization.write_as_tag), Base.TCPSocket, Int32}) precompile(Tuple{typeof(Serialization.object_number), Core.TypeName}) -precompile(Tuple{typeof(Serialization.serialize_array_data), Base.TCPSocket, Array{Int64, 1}}) precompile(Tuple{typeof(Serialization.deserialize_array), Serialization.Serializer{Base.PipeEndpoint}}) precompile(Tuple{typeof(Serialization.deserialize), Base.PipeEndpoint}) precompile(Tuple{typeof(Serialization.deserialize), Serialization.Serializer{Base.PipeEndpoint}}) diff --git a/stdlib/Sockets/Project.toml b/stdlib/Sockets/Project.toml new file mode 100644 index 0000000000000..11d6cb0dd320c --- /dev/null +++ b/stdlib/Sockets/Project.toml @@ -0,0 +1,2 @@ +name = "Sockets" +uuid = "6462fe0b-24de-5631-8697-dd941f90decc" diff --git a/stdlib/Sockets/docs/src/index.md b/stdlib/Sockets/docs/src/index.md new file mode 100644 index 0000000000000..d457da9dfbeb9 --- /dev/null +++ b/stdlib/Sockets/docs/src/index.md @@ -0,0 +1,25 @@ +## Sockets + +```@docs +Sockets.connect(::TCPSocket, ::Integer) +Sockets.connect(::AbstractString) +Sockets.listen(::Any) +Sockets.listen(::AbstractString) +Sockets.getaddrinfo +Sockets.getipaddr +Sockets.getalladdrinfo +Sockets.getnameinfo +Sockets.getsockname +Sockets.getpeername +Sockets.IPv4 +Sockets.IPv6 +Sockets.TCPSocket +Sockets.UDPSocket +Sockets.accept +Sockets.listenany +Sockets.bind +Sockets.send +Sockets.recv +Sockets.recvfrom +Sockets.setopt +``` diff --git a/stdlib/Sockets/src/IPAddr.jl b/stdlib/Sockets/src/IPAddr.jl new file mode 100644 index 0000000000000..529956197dc1c --- /dev/null +++ b/stdlib/Sockets/src/IPAddr.jl @@ -0,0 +1,253 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + +abstract type IPAddr end + +Base.isless(a::T, b::T) where {T<:IPAddr} = isless(a.host, b.host) +(dt::Type{<:Integer})(ip::IPAddr) = dt(ip.host)::dt + +struct IPv4 <: IPAddr + host::UInt32 + IPv4(host::UInt32) = new(host) + IPv4(a::UInt8,b::UInt8,c::UInt8,d::UInt8) = new(UInt32(a)<<24| + UInt32(b)<<16| + UInt32(c)<<8| + d) + function IPv4(a::Integer,b::Integer,c::Integer,d::Integer) + if !(0<=a<=255 && 0<=b<=255 && 0<=c<=255 && 0<=d<=255) + throw(ArgumentError("IPv4 field out of range (must be 0-255)")) + end + IPv4(UInt8(a),UInt8(b),UInt8(c),UInt8(d)) + end +end + +""" + IPv4(host::Integer) -> IPv4 + +Returns an IPv4 object from ip address `host` formatted as an [`Integer`](@ref). + +```jldoctest +julia> IPv4(3223256218) +ip"192.30.252.154" +``` +""" +function IPv4(host::Integer) + if host < 0 + throw(ArgumentError("IPv4 address must be positive")) + elseif typemax(typeof(host)) > typemax(UInt32) && host > typemax(UInt32) + throw(ArgumentError("IPv4 address must fit within 32 bits")) + else + return IPv4(UInt32(host)) + end +end + +# constructor: ("1.2.3.4") +IPv4(str::AbstractString) = parse(IPv4, str) + +show(io::IO,ip::IPv4) = print(io,"ip\"",ip,"\"") +print(io::IO,ip::IPv4) = print(io,dec((ip.host&(0xFF000000))>>24),".", + dec((ip.host&(0xFF0000))>>16),".", + dec((ip.host&(0xFF00))>>8),".", + dec(ip.host&0xFF)) + +struct IPv6 <: IPAddr + host::UInt128 + IPv6(host::UInt128) = new(host) + IPv6(a::UInt16,b::UInt16,c::UInt16,d::UInt16, + e::UInt16,f::UInt16,g::UInt16,h::UInt16) = new(UInt128(a)<<(7*16)| + UInt128(b)<<(6*16)| + UInt128(c)<<(5*16)| + UInt128(d)<<(4*16)| + UInt128(e)<<(3*16)| + UInt128(f)<<(2*16)| + UInt128(g)<<(1*16)| + h) + function IPv6(a::Integer,b::Integer,c::Integer,d::Integer, + e::Integer,f::Integer,g::Integer,h::Integer) + if !(0<=a<=0xFFFF && 0<=b<=0xFFFF && 0<=c<=0xFFFF && 0<=d<=0xFFFF && + 0<=e<=0xFFFF && 0<=f<=0xFFFF && 0<=g<=0xFFFF && 0<=h<=0xFFFF) + throw(ArgumentError("IPv6 field out of range (must be 0-65535)")) + end + IPv6(UInt16(a),UInt16(b),UInt16(c),UInt16(d), + UInt16(e),UInt16(f),UInt16(g),UInt16(h)) + end +end + +""" + IPv6(host::Integer) -> IPv6 + +Returns an IPv6 object from ip address `host` formatted as an [`Integer`](@ref). + +```jldoctest +julia> IPv6(3223256218) +ip"::c01e:fc9a" +``` +""" +function IPv6(host::Integer) + if host < 0 + throw(ArgumentError("IPv6 address must be positive")) + # We allow passing bigger integer types, but need to be careful to avoid overflow + # Let's hope promotion rules are sensible + elseif typemax(typeof(host)) > typemax(UInt128) && host > typemax(UInt128) + throw(ArgumentError("IPv6 address must fit within 128 bits")) + else + return IPv6(UInt128(host)) + end +end + +IPv6(str::AbstractString) = parse(IPv6, str) + +# Suppress leading '0's and "0x" +print_ipv6_field(io,field::UInt16) = print(io,hex(field)) + +print_ipv6_field(io,ip,i) = print_ipv6_field(io,ipv6_field(ip,i)) +function ipv6_field(ip::IPv6,i) + if i < 0 || i > 7 + throw(BoundsError()) + end + UInt16(ip.host&(UInt128(0xFFFF)<<(i*16))>>(i*16)) +end + +show(io::IO, ip::IPv6) = print(io,"ip\"",ip,"\"") +# RFC 5952 compliant show function +# http://tools.ietf.org/html/rfc5952 +function print(io::IO,ip::IPv6) + i = 8 + m = 0 + longest_sub_i = -1 + while i!=0 + i-=1 + field = ipv6_field(ip,i) + if field == 0 && longest_sub_i == -1 + # Find longest subsequence of 0 + longest_sub_i,j,m,c = i,i,1,1 + while j != 0 + j-=1 + if ipv6_field(ip,j) == 0 + c += 1 + else + c = 0 + end + if c > m + if j+c != longest_sub_i+1 + longest_sub_i = j+c-1 + end + m = c + end + end + # Prevent single 0 from contracting to :: as required + if m == 1 + longest_sub_i = 9 + end + end + if i == longest_sub_i + print(io,":") + i -= m-1 + if i == 0 + print(io,":") + break + end + else + if i != 7 + print(io,":") + end + print_ipv6_field(io,field) + end + end +end + +# Parsing + +const ipv4_leading_zero_error = """ +Leading zeros in IPv4 addresses are disallowed due to ambiguity. +If the address is in octal or hexadecimal, convert it to decimal, otherwise remove the leading zero. +""" + +function parse(::Type{IPv4}, str::AbstractString) + fields = split(str,'.') + i = 1 + ret = 0 + for f in fields + if isempty(f) + throw(ArgumentError("empty field in IPv4 address")) + end + if length(f) > 1 && f[1] == '0' + throw(ArgumentError(ipv4_leading_zero_error)) + else + r = parse(Int, f, base = 10) + end + if i != length(fields) + if r < 0 || r > 255 + throw(ArgumentError("IPv4 field out of range (must be 0-255)")) + end + ret |= UInt32(r) << ((4-i)*8) + else + if r > ((UInt64(1)<<((5-length(fields))*8))-1) + throw(ArgumentError("IPv4 field too large")) + end + ret |= r + end + i+=1 + end + IPv4(ret) +end + +function parseipv6fields(fields,num_fields) + if length(fields) > num_fields + throw(ArgumentError("too many fields in IPv6 address")) + end + cf = 7 + ret = UInt128(0) + for f in fields + if isempty(f) + # ::abc:... and ..:abc:: + if cf != 7 && cf != 0 + cf -= num_fields-length(fields) + end + cf -= 1 + continue + end + ret |= UInt128(parse(Int, f, base = 16))<<(cf*16) + cf -= 1 + end + ret +end +parseipv6fields(fields) = parseipv6fields(fields,8) + +function parse(::Type{IPv6}, str::AbstractString) + fields = split(str,':') + if length(fields) > 8 + throw(ArgumentError("too many fields in IPv6 address")) + elseif length(fields) == 8 + return IPv6(parseipv6fields(fields)) + elseif in('.',fields[end]) + return IPv6((parseipv6fields(fields[1:(end-1)],6)) + | parse(IPv4, fields[end]).host ) + else + return IPv6(parseipv6fields(fields)) + end +end + +# +# This support IPv4 addresses in the common dot (IPv4) or colon (IPv6) +# separated formats. Most other common formats use a standard integer encoding +# of the appropriate size and should use the appropriate constructor +# + +function parse(::Type{IPAddr}, str::AbstractString) + if ':' in str + return parse(IPv6, str) + else + return parse(IPv4, str) + end +end + +macro ip_str(str) + return parse(IPAddr, str) +end + +struct InetAddr{T<:IPAddr} + host::T + port::UInt16 +end + +InetAddr(ip::IPAddr, port) = InetAddr{typeof(ip)}(ip, port) diff --git a/stdlib/Sockets/src/PipeServer.jl b/stdlib/Sockets/src/PipeServer.jl new file mode 100644 index 0000000000000..92c99efdc05eb --- /dev/null +++ b/stdlib/Sockets/src/PipeServer.jl @@ -0,0 +1,93 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + +mutable struct PipeServer <: LibuvServer + handle::Ptr{Cvoid} + status::Int + connectnotify::Condition + closenotify::Condition + function PipeServer(handle::Ptr{Cvoid}, status) + p = new(handle, + status, + Condition(), + Condition()) + associate_julia_struct(p.handle, p) + finalizer(uvfinalize, p) + return p + end +end + +function PipeServer() + pipe = PipeServer(Libc.malloc(Base._sizeof_uv_named_pipe), StatusUninit) + err = ccall(:uv_pipe_init, Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Cint), eventloop(), pipe.handle, 0) + uv_error("failed to create pipe server", err) + pipe.status = StatusInit + return pipe +end + +## server functions ## + +accept(server::PipeServer) = accept(server, PipeEndpoint()) + +function accept_nonblock(server::PipeServer, client::PipeEndpoint) + if client.status != StatusInit + error("client is already in use or has been closed") + end + err = ccall(:uv_accept, Int32, (Ptr{Cvoid}, Ptr{Cvoid}), server.handle, client.handle) + if err == 0 + client.status = StatusOpen + end + return err +end + +function accept_nonblock(server::PipeServer) + client = PipeEndpoint() + uv_error("accept", accept_nonblock(server, client) != 0) + return client +end + +function bind(server::PipeServer, name::AbstractString) + @assert server.status == StatusInit + err = ccall(:uv_pipe_bind, Int32, (Ptr{Cvoid}, Cstring), + server, name) + if err != 0 + if err != UV_EADDRINUSE && err != UV_EACCES + #TODO: this codepath is currently not tested + throw(UVError("bind",err)) + else + return false + end + end + server.status = StatusOpen + return true +end + +""" + listen(path::AbstractString) -> PipeServer + +Create and listen on a named pipe / UNIX domain socket. +""" +function listen(path::AbstractString) + sock = PipeServer() + bind(sock, path) || throw(ArgumentError("could not listen on path $path")) + return listen(sock) +end + +function connect!(sock::PipeEndpoint, path::AbstractString) + @assert sock.status == StatusInit + req = Libc.malloc(Base._sizeof_uv_connect) + uv_req_set_data(req, C_NULL) + ccall(:uv_pipe_connect, Cvoid, (Ptr{Cvoid}, Ptr{Cvoid}, Cstring, Ptr{Cvoid}), req, sock.handle, path, + uv_jl_connectcb::Ptr{Cvoid}) + sock.status = StatusConnecting + return sock +end + +# Libuv will internally reset read/writability, which is uses to +# mark that this is an invalid pipe. + +""" + connect(path::AbstractString) -> PipeEndpoint + +Connect to the named pipe / UNIX domain socket at `path`. +""" +connect(path::AbstractString) = connect(PipeEndpoint(), path) diff --git a/base/socket.jl b/stdlib/Sockets/src/Sockets.jl similarity index 52% rename from base/socket.jl rename to stdlib/Sockets/src/Sockets.jl index 8916ccbb5b715..ec7876a9170af 100644 --- a/base/socket.jl +++ b/stdlib/Sockets/src/Sockets.jl @@ -1,259 +1,45 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -## IP ADDRESS HANDLING ## -abstract type IPAddr end - -Base.isless(a::T, b::T) where {T<:IPAddr} = isless(a.host, b.host) -(dt::Type{<:Integer})(ip::IPAddr) = dt(ip.host)::dt - -struct IPv4 <: IPAddr - host::UInt32 - IPv4(host::UInt32) = new(host) - IPv4(a::UInt8,b::UInt8,c::UInt8,d::UInt8) = new(UInt32(a)<<24| - UInt32(b)<<16| - UInt32(c)<<8| - d) - function IPv4(a::Integer,b::Integer,c::Integer,d::Integer) - if !(0<=a<=255 && 0<=b<=255 && 0<=c<=255 && 0<=d<=255) - throw(ArgumentError("IPv4 field out of range (must be 0-255)")) - end - IPv4(UInt8(a),UInt8(b),UInt8(c),UInt8(d)) - end -end - -""" - IPv4(host::Integer) -> IPv4 - -Returns an IPv4 object from ip address `host` formatted as an [`Integer`](@ref). - -```jldoctest -julia> IPv4(3223256218) -ip"192.30.252.154" -``` -""" -function IPv4(host::Integer) - if host < 0 - throw(ArgumentError("IPv4 address must be positive")) - elseif typemax(typeof(host)) > typemax(UInt32) && host > typemax(UInt32) - throw(ArgumentError("IPv4 address must fit within 32 bits")) - else - return IPv4(UInt32(host)) - end -end - -# constructor: ("1.2.3.4") -IPv4(str::AbstractString) = parse(IPv4, str) - -show(io::IO,ip::IPv4) = print(io,"ip\"",ip,"\"") -print(io::IO,ip::IPv4) = print(io,dec((ip.host&(0xFF000000))>>24),".", - dec((ip.host&(0xFF0000))>>16),".", - dec((ip.host&(0xFF00))>>8),".", - dec(ip.host&0xFF)) - -struct IPv6 <: IPAddr - host::UInt128 - IPv6(host::UInt128) = new(host) - IPv6(a::UInt16,b::UInt16,c::UInt16,d::UInt16, - e::UInt16,f::UInt16,g::UInt16,h::UInt16) = new(UInt128(a)<<(7*16)| - UInt128(b)<<(6*16)| - UInt128(c)<<(5*16)| - UInt128(d)<<(4*16)| - UInt128(e)<<(3*16)| - UInt128(f)<<(2*16)| - UInt128(g)<<(1*16)| - h) - function IPv6(a::Integer,b::Integer,c::Integer,d::Integer, - e::Integer,f::Integer,g::Integer,h::Integer) - if !(0<=a<=0xFFFF && 0<=b<=0xFFFF && 0<=c<=0xFFFF && 0<=d<=0xFFFF && - 0<=e<=0xFFFF && 0<=f<=0xFFFF && 0<=g<=0xFFFF && 0<=h<=0xFFFF) - throw(ArgumentError("IPv6 field out of range (must be 0-65535)")) - end - IPv6(UInt16(a),UInt16(b),UInt16(c),UInt16(d), - UInt16(e),UInt16(f),UInt16(g),UInt16(h)) - end -end - -""" - IPv6(host::Integer) -> IPv6 - -Returns an IPv6 object from ip address `host` formatted as an [`Integer`](@ref). - -```jldoctest -julia> IPv6(3223256218) -ip"::c01e:fc9a" -``` -""" -function IPv6(host::Integer) - if host < 0 - throw(ArgumentError("IPv6 address must be positive")) - # We allow passing bigger integer types, but need to be careful to avoid overflow - # Let's hope promotion rules are sensible - elseif typemax(typeof(host)) > typemax(UInt128) && host > typemax(UInt128) - throw(ArgumentError("IPv6 address must fit within 128 bits")) - else - return IPv6(UInt128(host)) - end -end - -IPv6(str::AbstractString) = parse(IPv6, str) - -# Suppress leading '0's and "0x" -print_ipv6_field(io,field::UInt16) = print(io,hex(field)) - -print_ipv6_field(io,ip,i) = print_ipv6_field(io,ipv6_field(ip,i)) -function ipv6_field(ip::IPv6,i) - if i < 0 || i > 7 - throw(BoundsError()) - end - UInt16(ip.host&(UInt128(0xFFFF)<<(i*16))>>(i*16)) -end - -show(io::IO, ip::IPv6) = print(io,"ip\"",ip,"\"") -# RFC 5952 compliant show function -# http://tools.ietf.org/html/rfc5952 -function print(io::IO,ip::IPv6) - i = 8 - m = 0 - longest_sub_i = -1 - while i!=0 - i-=1 - field = ipv6_field(ip,i) - if field == 0 && longest_sub_i == -1 - # Find longest subsequence of 0 - longest_sub_i,j,m,c = i,i,1,1 - while j != 0 - j-=1 - if ipv6_field(ip,j) == 0 - c += 1 - else - c = 0 - end - if c > m - if j+c != longest_sub_i+1 - longest_sub_i = j+c-1 - end - m = c - end - end - # Prevent single 0 from contracting to :: as required - if m == 1 - longest_sub_i = 9 - end - end - if i == longest_sub_i - print(io,":") - i -= m-1 - if i == 0 - print(io,":") - break - end - else - if i != 7 - print(io,":") - end - print_ipv6_field(io,field) - end - end -end - -# Parsing - -const ipv4_leading_zero_error = """ -Leading zeros in IPv4 addresses are disallowed due to ambiguity. -If the address is in octal or hexadecimal, convert it to decimal, otherwise remove the leading zero. -""" - -function parse(::Type{IPv4}, str::AbstractString) - fields = split(str,'.') - i = 1 - ret = 0 - for f in fields - if isempty(f) - throw(ArgumentError("empty field in IPv4 address")) - end - if length(f) > 1 && f[1] == '0' - throw(ArgumentError(ipv4_leading_zero_error)) - else - r = parse(Int, f, base = 10) - end - if i != length(fields) - if r < 0 || r > 255 - throw(ArgumentError("IPv4 field out of range (must be 0-255)")) - end - ret |= UInt32(r) << ((4-i)*8) - else - if r > ((UInt64(1)<<((5-length(fields))*8))-1) - throw(ArgumentError("IPv4 field too large")) - end - ret |= r - end - i+=1 - end - IPv4(ret) -end - -function parseipv6fields(fields,num_fields) - if length(fields) > num_fields - throw(ArgumentError("too many fields in IPv6 address")) - end - cf = 7 - ret = UInt128(0) - for f in fields - if isempty(f) - # ::abc:... and ..:abc:: - if cf != 7 && cf != 0 - cf -= num_fields-length(fields) - end - cf -= 1 - continue - end - ret |= UInt128(parse(Int, f, base = 16))<<(cf*16) - cf -= 1 - end - ret -end -parseipv6fields(fields) = parseipv6fields(fields,8) - -function parse(::Type{IPv6}, str::AbstractString) - fields = split(str,':') - if length(fields) > 8 - throw(ArgumentError("too many fields in IPv6 address")) - elseif length(fields) == 8 - return IPv6(parseipv6fields(fields)) - elseif in('.',fields[end]) - return IPv6((parseipv6fields(fields[1:(end-1)],6)) - | parse(IPv4, fields[end]).host ) - else - return IPv6(parseipv6fields(fields)) - end -end - -# -# This support IPv4 addresses in the common dot (IPv4) or colon (IPv6) -# separated formats. Most other common formats use a standard integer encoding -# of the appropriate size and should use the appropriate constructor -# - -function parse(::Type{IPAddr}, str::AbstractString) - if ':' in str - return parse(IPv6, str) - else - return parse(IPv4, str) - end -end +module Sockets + +export + accept, + bind, + connect, + getaddrinfo, + getalladdrinfo, + getnameinfo, + getipaddr, + getpeername, + getsockname, + listen, + listenany, + recv, + recvfrom, + send, + TCPSocket, + UDPSocket, + @ip_str, + IPAddr, + IPv4, + IPv6 + +import Base: isless, show, print, parse, bind, convert, isreadable, iswritable, alloc_buf_hook, _uv_hook_close + +using Base: LibuvStream, LibuvServer, PipeEndpoint, @handle_as, uv_error, associate_julia_struct, uvfinalize, + notify_error, stream_wait, uv_req_data, uv_req_set_data, preserve_handle, unpreserve_handle, UVError, + eventloop, StatusUninit, StatusInit, StatusConnecting, StatusOpen, StatusClosing, StatusClosed, StatusActive, + uv_status_string, check_open, wait_connected, + UV_EINVAL, UV_ENOMEM, UV_ENOBUFS, UV_EAGAIN, UV_ECONNABORTED, UV_EADDRINUSE, UV_EACCES, UV_EADDRNOTAVAIL, + UV_EAI_ADDRFAMILY, UV_EAI_AGAIN, UV_EAI_BADFLAGS, + UV_EAI_BADHINTS, UV_EAI_CANCELED, UV_EAI_FAIL, + UV_EAI_FAMILY, UV_EAI_NODATA, UV_EAI_NONAME, + UV_EAI_OVERFLOW, UV_EAI_PROTOCOL, UV_EAI_SERVICE, + UV_EAI_SOCKTYPE, UV_EAI_MEMORY + +include("IPAddr.jl") +include("addrinfo.jl") -macro ip_str(str) - return parse(IPAddr, str) -end - -struct InetAddr{T<:IPAddr} - host::T - port::UInt16 -end - -InetAddr(ip::IPAddr, port) = InetAddr{typeof(ip)}(ip, port) - -## SOCKETS ## """ TCPSocket(; delay=true) @@ -282,7 +68,7 @@ mutable struct TCPSocket <: LibuvStream Condition(), nothing, ReentrantLock(), - DEFAULT_READ_BUFFER_SZ) + Base.DEFAULT_READ_BUFFER_SZ) associate_julia_struct(tcp.handle, tcp) finalizer(uvfinalize, tcp) return tcp @@ -291,7 +77,7 @@ end # kw arg "delay": if true, libuv delays creation of the socket fd till the first bind call function TCPSocket(; delay=true) - tcp = TCPSocket(Libc.malloc(_sizeof_uv_tcp), StatusUninit) + tcp = TCPSocket(Libc.malloc(Base._sizeof_uv_tcp), StatusUninit) af_spec = delay ? 0 : 2 # AF_UNSPEC is 0, AF_INET is 2 err = ccall(:uv_tcp_init_ex, Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Cuint), eventloop(), tcp.handle, af_spec) @@ -322,7 +108,7 @@ end # It can be set to false if there is a need to set socket options before # further calls to `bind` and `listen`, e.g. `SO_REUSEPORT`. function TCPServer(; delay=true) - tcp = TCPServer(Libc.malloc(_sizeof_uv_tcp), StatusUninit) + tcp = TCPServer(Libc.malloc(Base._sizeof_uv_tcp), StatusUninit) af_spec = delay ? 0 : 2 # AF_UNSPEC is 0, AF_INET is 2 err = ccall(:uv_tcp_init_ex, Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Cuint), eventloop(), tcp.handle, af_spec) @@ -334,15 +120,6 @@ end isreadable(io::TCPSocket) = isopen(io) || bytesavailable(io) > 0 iswritable(io::TCPSocket) = isopen(io) && io.status != StatusClosing -## VARIOUS METHODS TO BE MOVED TO BETTER LOCATION - -_jl_connect_raw(sock::TCPSocket, sockaddr::Ptr{Cvoid}) = - ccall(:jl_connect_raw, Int32, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), sock.handle, sockaddr, uv_jl_connectcb::Ptr{Cvoid}) -_jl_sockaddr_from_addrinfo(addrinfo::Ptr{Cvoid}) = - ccall(:jl_sockaddr_from_addrinfo, Ptr{Cvoid}, (Ptr{Cvoid},), addrinfo) -_jl_sockaddr_set_port(ptr::Ptr{Cvoid}, port::UInt16) = - ccall(:jl_sockaddr_set_port, Cvoid, (Ptr{Cvoid}, UInt16), ptr, port) - """ accept(server[,client]) @@ -351,7 +128,6 @@ uninitialized client stream may be provided, in which case it will be used inste creating a new stream. """ accept(server::TCPServer) = accept(server, TCPSocket()) -accept(server::PipeServer) = accept(server, PipeEndpoint()) # UDP """ @@ -380,7 +156,7 @@ mutable struct UDPSocket <: LibuvStream end end function UDPSocket() - this = UDPSocket(Libc.malloc(_sizeof_uv_udp), StatusUninit) + this = UDPSocket(Libc.malloc(Base._sizeof_uv_udp), StatusUninit) err = ccall(:uv_udp_init, Cint, (Ptr{Cvoid}, Ptr{Cvoid}), eventloop(), this.handle) uv_error("failed to create udp socket", err) @@ -517,7 +293,7 @@ function recvfrom(sock::UDPSocket) end if ccall(:uv_is_active, Cint, (Ptr{Cvoid},), sock.handle) == 0 uv_error("recv_start", ccall(:uv_udp_recv_start, Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), - sock.handle, uv_jl_alloc_buf::Ptr{Cvoid}, uv_jl_recvcb::Ptr{Cvoid})) + sock.handle, Base.uv_jl_alloc_buf::Ptr{Cvoid}, uv_jl_recvcb::Ptr{Cvoid})) end sock.status = StatusActive return stream_wait(sock, sock.recvnotify)::Tuple{Union{IPv4, IPv6}, Vector{UInt8}} @@ -590,244 +366,24 @@ function uv_sendcb(handle::Ptr{Cvoid}, status::Cint) nothing end -## -struct DNSError <: Exception - host::String - code::Int32 -end - -function show(io::IO, err::DNSError) - print(io, "DNSError: ", err.host, ", ", struverror(err.code), - " (", uverrorname(err.code), ")") -end - -function uv_getaddrinfocb(req::Ptr{Cvoid}, status::Cint, addrinfo::Ptr{Cvoid}) - data = uv_req_data(req) - if data != C_NULL - t = unsafe_pointer_to_objref(data)::Task - uv_req_set_data(req, C_NULL) - if status != 0 || addrinfo == C_NULL - schedule(t, UVError("getaddrinfocb", status)) - else - freeaddrinfo = addrinfo - addrs = IPAddr[] - while addrinfo != C_NULL - sockaddr = ccall(:jl_sockaddr_from_addrinfo, Ptr{Cvoid}, (Ptr{Cvoid},), addrinfo) - if ccall(:jl_sockaddr_is_ip4, Int32, (Ptr{Cvoid},), sockaddr) == 1 - ip4addr = ccall(:jl_sockaddr_host4, UInt32, (Ptr{Cvoid},), sockaddr) - push!(addrs, IPv4(ntoh(ip4addr))) - elseif ccall(:jl_sockaddr_is_ip6, Int32, (Ptr{Cvoid},), sockaddr) == 1 - ip6addr = Ref{UInt128}() - scope_id = ccall(:jl_sockaddr_host6, UInt32, (Ptr{Cvoid}, Ptr{UInt128}), sockaddr, ip6addr) - push!(addrs, IPv6(ntoh(ip6addr[]))) - end - addrinfo = ccall(:jl_next_from_addrinfo, Ptr{Cvoid}, (Ptr{Cvoid},), addrinfo) - end - ccall(:uv_freeaddrinfo, Cvoid, (Ptr{Cvoid},), freeaddrinfo) - schedule(t, addrs) - end +#from `connect` +function uv_connectcb(conn::Ptr{Cvoid}, status::Cint) + hand = ccall(:jl_uv_connect_handle, Ptr{Cvoid}, (Ptr{Cvoid},), conn) + sock = @handle_as hand LibuvStream + @assert sock.status == StatusConnecting + if status >= 0 + sock.status = StatusOpen + notify(sock.connectnotify) else - # no owner for this req, safe to just free it - Libc.free(req) + sock.status = StatusInit + err = UVError("connect", status) + notify_error(sock.connectnotify, err) end + Libc.free(conn) nothing end -""" - getalladdrinfo(host::AbstractString) -> Vector{IPAddr} - -Gets all of the IP addresses of the `host`. -Uses the operating system's underlying getaddrinfo implementation, which may do a DNS lookup. -""" -function getalladdrinfo(host::String) - isascii(host) || error("non-ASCII hostname: $host") - req = Libc.malloc(_sizeof_uv_getaddrinfo) - uv_req_set_data(req, C_NULL) # in case we get interrupted before arriving at the wait call - status = ccall(:jl_getaddrinfo, Int32, (Ptr{Cvoid}, Ptr{Cvoid}, Cstring, Ptr{Cvoid}, Ptr{Cvoid}), - eventloop(), req, host, #=service=#C_NULL, uv_jl_getaddrinfocb::Ptr{Cvoid}) - if status < 0 - Libc.free(req) - if status == UV_EINVAL - throw(ArgumentError("Invalid getaddrinfo argument")) - elseif status == UV_ENOMEM || status == UV_ENOBUFS - throw(OutOfMemoryError()) - end - uv_error("getaddrinfo", status) - end - ct = current_task() - preserve_handle(ct) - r = try - uv_req_set_data(req, ct) - wait() - finally - if uv_req_data(req) != C_NULL - # req is still alive, - # so make sure we don't get spurious notifications later - uv_req_set_data(req, C_NULL) - ccall(:uv_cancel, Int32, (Ptr{Cvoid},), req) # try to let libuv know we don't care anymore - else - # done with req - Libc.free(req) - end - unpreserve_handle(ct) - end - if isa(r, UVError) - code = r.code - if code in (UV_EAI_ADDRFAMILY, UV_EAI_AGAIN, UV_EAI_BADFLAGS, - UV_EAI_BADHINTS, UV_EAI_CANCELED, UV_EAI_FAIL, - UV_EAI_FAMILY, UV_EAI_NODATA, UV_EAI_NONAME, - UV_EAI_OVERFLOW, UV_EAI_PROTOCOL, UV_EAI_SERVICE, - UV_EAI_SOCKTYPE) - throw(DNSError(host, code)) - elseif code == UV_EAI_MEMORY - throw(OutOfMemoryError()) - else - throw(UVError("getaddrinfo", code)) - end - end - return r::Vector{IPAddr} -end -getalladdrinfo(host::AbstractString) = getalladdrinfo(String(host)) - -""" - getalladdrinfo(host::AbstractString, IPAddr=IPv4) -> IPAddr - -Gets the first IP address of the `host` of the specified `IPAddr` type. -Uses the operating system's underlying getaddrinfo implementation, which may do a DNS lookup. -""" -function getaddrinfo(host::String, T::Type{<:IPAddr}) - addrs = getalladdrinfo(host) - for addr in addrs - if addr isa T - return addr - end - end - throw(DNSError(host, UV_EAI_NONAME)) -end -getaddrinfo(host::AbstractString, T::Type{<:IPAddr}) = getaddrinfo(String(host), T) -getaddrinfo(host::AbstractString) = getaddrinfo(String(host), IPv4) - -function uv_getnameinfocb(req::Ptr{Cvoid}, status::Cint, hostname::Cstring, service::Cstring) - data = uv_req_data(req) - if data != C_NULL - t = unsafe_pointer_to_objref(data)::Task - uv_req_set_data(req, C_NULL) - if status != 0 - schedule(t, UVError("getnameinfocb", status)) - else - schedule(t, unsafe_string(hostname)) - end - else - # no owner for this req, safe to just free it - Libc.free(req) - end - nothing -end - -""" - getnameinfo(host::IPAddr) -> String - -Performs a reverse-lookup for IP address to return a hostname and service -using the operating system's underlying getnameinfo implementation. -""" -function getnameinfo(address::Union{IPv4, IPv6}) - req = Libc.malloc(_sizeof_uv_getnameinfo) - uv_req_set_data(req, C_NULL) # in case we get interrupted before arriving at the wait call - ev = eventloop() - port = hton(UInt16(0)) - flags = 0 - uvcb = uv_jl_getnameinfocb::Ptr{Cvoid} - status = UV_EINVAL - if address isa IPv4 - status = ccall(:jl_getnameinfo, Int32, (Ptr{Cvoid}, Ptr{Cvoid}, UInt32, UInt16, Cint, Ptr{Cvoid}), - ev, req, hton(address.host), port, flags, uvcb) - elseif address isa IPv6 - status = ccall(:jl_getnameinfo6, Int32, (Ptr{Cvoid}, Ptr{Cvoid}, Ref{UInt128}, UInt16, Cint, Ptr{Cvoid}), - ev, req, hton(address.host), port, flags, uvcb) - end - if status < 0 - Libc.free(req) - if status == UV_EINVAL - throw(ArgumentError("Invalid getnameinfo argument")) - elseif status == UV_ENOMEM || status == UV_ENOBUFS - throw(OutOfMemoryError()) - end - uv_error("getnameinfo", status) - end - ct = current_task() - preserve_handle(ct) - r = try - uv_req_set_data(req, ct) - wait() - finally - if uv_req_data(req) != C_NULL - # req is still alive, - # so make sure we don't get spurious notifications later - uv_req_set_data(req, C_NULL) - ccall(:uv_cancel, Int32, (Ptr{Cvoid},), req) # try to let libuv know we don't care anymore - else - # done with req - Libc.free(req) - end - unpreserve_handle(ct) - end - if isa(r, UVError) - code = r.code - if code in (UV_EAI_ADDRFAMILY, UV_EAI_AGAIN, UV_EAI_BADFLAGS, - UV_EAI_BADHINTS, UV_EAI_CANCELED, UV_EAI_FAIL, - UV_EAI_FAMILY, UV_EAI_NODATA, UV_EAI_NONAME, - UV_EAI_OVERFLOW, UV_EAI_PROTOCOL, UV_EAI_SERVICE, - UV_EAI_SOCKTYPE) - throw(DNSError(repr(address), code)) - elseif code == UV_EAI_MEMORY - throw(OutOfMemoryError()) - else - throw(UVError("getnameinfo", code)) - end - end - return r::String -end - - -const _sizeof_uv_interface_address = ccall(:jl_uv_sizeof_interface_address,Int32,()) - -""" - getipaddr() -> IPAddr - -Get the IP address of the local machine. -""" -function getipaddr() - addr_ref = Ref{Ptr{UInt8}}(C_NULL) - count_ref = Ref{Int32}(1) - lo_present = false - err = ccall(:jl_uv_interface_addresses, Int32, (Ref{Ptr{UInt8}}, Ref{Int32}), addr_ref, count_ref) - uv_error("getlocalip", err) - addr, count = addr_ref[], count_ref[] - for i = 0:(count-1) - current_addr = addr + i*_sizeof_uv_interface_address - if 1 == ccall(:jl_uv_interface_address_is_internal, Int32, (Ptr{UInt8},), current_addr) - lo_present = true - continue - end - sockaddr = ccall(:jl_uv_interface_address_sockaddr, Ptr{Cvoid}, (Ptr{UInt8},), current_addr) - if ccall(:jl_sockaddr_in_is_ip4, Int32, (Ptr{Cvoid},), sockaddr) == 1 - rv = IPv4(ntoh(ccall(:jl_sockaddr_host4, UInt32, (Ptr{Cvoid},), sockaddr))) - ccall(:uv_free_interface_addresses, Cvoid, (Ptr{UInt8}, Int32), addr, count) - return rv - # Uncomment to enbable IPv6 - #elseif ccall(:jl_sockaddr_in_is_ip6, Int32, (Ptr{Cvoid},), sockaddr) == 1 - # host = Vector{UInt128}(uninitialized, 1) - # ccall(:jl_sockaddr_host6, UInt32, (Ptr{Cvoid}, Ptr{UInt128}), sockaddrr, host) - # return IPv6(ntoh(host[1])) - end - end - ccall(:uv_free_interface_addresses, Cvoid, (Ptr{UInt8}, Int32), addr, count) - return lo_present ? localhost : error("No networking interface available") -end - -## - function connect!(sock::TCPSocket, host::IPv4, port::Integer) if sock.status != StatusInit error("TCPSocket is not in initialization state") @@ -871,8 +427,6 @@ connect(host::AbstractString, port::Integer) = connect(TCPSocket(), host, port) connect(addr::IPAddr, port::Integer) = connect(TCPSocket(), addr, port) connect(addr::InetAddr) = connect(TCPSocket(), addr) -default_connectcb(sock, status) = nothing - function connect!(sock::TCPSocket, host::AbstractString, port::Integer) if sock.status != StatusInit error("TCPSocket is not in initialization state") @@ -884,8 +438,16 @@ function connect!(sock::TCPSocket, host::AbstractString, port::Integer) return sock end +function connect(sock::LibuvStream, args...) + connect!(sock, args...) + wait_connected(sock) + return sock +end + ## +const BACKLOG_DEFAULT = 511 + """ listen([addr, ]port::Integer; backlog::Integer=BACKLOG_DEFAULT) -> TCPServer @@ -923,6 +485,31 @@ function listen(callback, server::Union{TCPSocket, UDPSocket}) return sock end +function listen(sock::LibuvServer; backlog::Integer=BACKLOG_DEFAULT) + uv_error("listen", trylisten(sock)) + return sock +end + +# from `listen` +function uv_connectioncb(stream::Ptr{Cvoid}, status::Cint) + sock = @handle_as stream LibuvServer + if status >= 0 + notify(sock.connectnotify) + else + err = UVError("connection", status) + notify_error(sock.connectnotify, err) + end + nothing +end + +function trylisten(sock::LibuvServer; backlog::Integer=BACKLOG_DEFAULT) + check_open(sock) + err = ccall(:uv_listen, Cint, (Ptr{Cvoid}, Cint, Ptr{Cvoid}), + sock, backlog, uv_jl_connectioncb::Ptr{Cvoid}) + sock.status = StatusActive + return err +end + ## function accept_nonblock(server::TCPServer, client::TCPSocket) @@ -942,6 +529,22 @@ function accept_nonblock(server::TCPServer) return client end +function accept(server::LibuvServer, client::LibuvStream) + if server.status != StatusActive + throw(ArgumentError("server not connected, make sure \"listen\" has been called")) + end + while isopen(server) + err = accept_nonblock(server, client) + if err == 0 + return client + elseif err != UV_EAGAIN + uv_error("accept", err) + end + stream_wait(server, server.connectnotify) + end + uv_error("accept", UV_ECONNABORTED) +end + ## Utility functions const localhost = ip"127.0.0.1" @@ -1033,3 +636,33 @@ function _sockname(sock, self=true) end return addr, port end + +# domain sockets + +include("PipeServer.jl") + +# libuv callback handles + +function __init__() + global uv_jl_getaddrinfocb = cfunction(uv_getaddrinfocb, Cvoid, Tuple{Ptr{Cvoid}, Cint, Ptr{Cvoid}}) + global uv_jl_getnameinfocb = cfunction(uv_getnameinfocb, Cvoid, Tuple{Ptr{Cvoid}, Cint, Cstring, Cstring}) + global uv_jl_recvcb = cfunction(uv_recvcb, Cvoid, Tuple{Ptr{Cvoid}, Cssize_t, Ptr{Cvoid}, Ptr{Cvoid}, Cuint}) + global uv_jl_sendcb = cfunction(uv_sendcb, Cvoid, Tuple{Ptr{Cvoid}, Cint}) + global uv_jl_connectioncb = cfunction(uv_connectioncb, Cvoid, Tuple{Ptr{Cvoid}, Cint}) + global uv_jl_connectcb = cfunction(uv_connectcb, Cvoid, Tuple{Ptr{Cvoid}, Cint}) +end + +# deprecations + +@deprecate convert(dt::Type{<:Integer}, ip::IPAddr) dt(ip) + +@noinline function getaddrinfo(callback::Function, host::AbstractString) + Base.depwarn("`getaddrinfo` with a callback function is deprecated, wrap code in `@async` instead for deferred execution.", :getaddrinfo) + @async begin + r = getaddrinfo(host) + callback(r) + end + nothing +end + +end diff --git a/stdlib/Sockets/src/addrinfo.jl b/stdlib/Sockets/src/addrinfo.jl new file mode 100644 index 0000000000000..ccd607618ba02 --- /dev/null +++ b/stdlib/Sockets/src/addrinfo.jl @@ -0,0 +1,234 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + +struct DNSError <: Exception + host::String + code::Int32 +end + +function show(io::IO, err::DNSError) + print(io, "DNSError: ", err.host, ", ", struverror(err.code), + " (", uverrorname(err.code), ")") +end + +function uv_getaddrinfocb(req::Ptr{Cvoid}, status::Cint, addrinfo::Ptr{Cvoid}) + data = uv_req_data(req) + if data != C_NULL + t = unsafe_pointer_to_objref(data)::Task + uv_req_set_data(req, C_NULL) + if status != 0 || addrinfo == C_NULL + schedule(t, UVError("getaddrinfocb", status)) + else + freeaddrinfo = addrinfo + addrs = IPAddr[] + while addrinfo != C_NULL + sockaddr = ccall(:jl_sockaddr_from_addrinfo, Ptr{Cvoid}, (Ptr{Cvoid},), addrinfo) + if ccall(:jl_sockaddr_is_ip4, Int32, (Ptr{Cvoid},), sockaddr) == 1 + ip4addr = ccall(:jl_sockaddr_host4, UInt32, (Ptr{Cvoid},), sockaddr) + push!(addrs, IPv4(ntoh(ip4addr))) + elseif ccall(:jl_sockaddr_is_ip6, Int32, (Ptr{Cvoid},), sockaddr) == 1 + ip6addr = Ref{UInt128}() + scope_id = ccall(:jl_sockaddr_host6, UInt32, (Ptr{Cvoid}, Ptr{UInt128}), sockaddr, ip6addr) + push!(addrs, IPv6(ntoh(ip6addr[]))) + end + addrinfo = ccall(:jl_next_from_addrinfo, Ptr{Cvoid}, (Ptr{Cvoid},), addrinfo) + end + ccall(:uv_freeaddrinfo, Cvoid, (Ptr{Cvoid},), freeaddrinfo) + schedule(t, addrs) + end + else + # no owner for this req, safe to just free it + Libc.free(req) + end + nothing +end + +""" + getalladdrinfo(host::AbstractString) -> Vector{IPAddr} + +Gets all of the IP addresses of the `host`. +Uses the operating system's underlying getaddrinfo implementation, which may do a DNS lookup. +""" +function getalladdrinfo(host::String) + isascii(host) || error("non-ASCII hostname: $host") + req = Libc.malloc(Base._sizeof_uv_getaddrinfo) + uv_req_set_data(req, C_NULL) # in case we get interrupted before arriving at the wait call + status = ccall(:jl_getaddrinfo, Int32, (Ptr{Cvoid}, Ptr{Cvoid}, Cstring, Ptr{Cvoid}, Ptr{Cvoid}), + eventloop(), req, host, #=service=#C_NULL, uv_jl_getaddrinfocb::Ptr{Cvoid}) + if status < 0 + Libc.free(req) + if status == UV_EINVAL + throw(ArgumentError("Invalid getaddrinfo argument")) + elseif status == UV_ENOMEM || status == UV_ENOBUFS + throw(OutOfMemoryError()) + end + uv_error("getaddrinfo", status) + end + ct = current_task() + preserve_handle(ct) + r = try + uv_req_set_data(req, ct) + wait() + finally + if uv_req_data(req) != C_NULL + # req is still alive, + # so make sure we don't get spurious notifications later + uv_req_set_data(req, C_NULL) + ccall(:uv_cancel, Int32, (Ptr{Cvoid},), req) # try to let libuv know we don't care anymore + else + # done with req + Libc.free(req) + end + unpreserve_handle(ct) + end + if isa(r, UVError) + code = r.code + if code in (UV_EAI_ADDRFAMILY, UV_EAI_AGAIN, UV_EAI_BADFLAGS, + UV_EAI_BADHINTS, UV_EAI_CANCELED, UV_EAI_FAIL, + UV_EAI_FAMILY, UV_EAI_NODATA, UV_EAI_NONAME, + UV_EAI_OVERFLOW, UV_EAI_PROTOCOL, UV_EAI_SERVICE, + UV_EAI_SOCKTYPE) + throw(DNSError(host, code)) + elseif code == UV_EAI_MEMORY + throw(OutOfMemoryError()) + else + throw(UVError("getaddrinfo", code)) + end + end + return r::Vector{IPAddr} +end +getalladdrinfo(host::AbstractString) = getalladdrinfo(String(host)) + +""" + getalladdrinfo(host::AbstractString, IPAddr=IPv4) -> IPAddr + +Gets the first IP address of the `host` of the specified `IPAddr` type. +Uses the operating system's underlying getaddrinfo implementation, which may do a DNS lookup. +""" +function getaddrinfo(host::String, T::Type{<:IPAddr}) + addrs = getalladdrinfo(host) + for addr in addrs + if addr isa T + return addr + end + end + throw(DNSError(host, UV_EAI_NONAME)) +end +getaddrinfo(host::AbstractString, T::Type{<:IPAddr}) = getaddrinfo(String(host), T) +getaddrinfo(host::AbstractString) = getaddrinfo(String(host), IPv4) + +function uv_getnameinfocb(req::Ptr{Cvoid}, status::Cint, hostname::Cstring, service::Cstring) + data = uv_req_data(req) + if data != C_NULL + t = unsafe_pointer_to_objref(data)::Task + uv_req_set_data(req, C_NULL) + if status != 0 + schedule(t, UVError("getnameinfocb", status)) + else + schedule(t, unsafe_string(hostname)) + end + else + # no owner for this req, safe to just free it + Libc.free(req) + end + nothing +end + +""" + getnameinfo(host::IPAddr) -> String + +Performs a reverse-lookup for IP address to return a hostname and service +using the operating system's underlying getnameinfo implementation. +""" +function getnameinfo(address::Union{IPv4, IPv6}) + req = Libc.malloc(Base._sizeof_uv_getnameinfo) + uv_req_set_data(req, C_NULL) # in case we get interrupted before arriving at the wait call + ev = eventloop() + port = hton(UInt16(0)) + flags = 0 + uvcb = uv_jl_getnameinfocb::Ptr{Cvoid} + status = UV_EINVAL + if address isa IPv4 + status = ccall(:jl_getnameinfo, Int32, (Ptr{Cvoid}, Ptr{Cvoid}, UInt32, UInt16, Cint, Ptr{Cvoid}), + ev, req, hton(address.host), port, flags, uvcb) + elseif address isa IPv6 + status = ccall(:jl_getnameinfo6, Int32, (Ptr{Cvoid}, Ptr{Cvoid}, Ref{UInt128}, UInt16, Cint, Ptr{Cvoid}), + ev, req, hton(address.host), port, flags, uvcb) + end + if status < 0 + Libc.free(req) + if status == UV_EINVAL + throw(ArgumentError("Invalid getnameinfo argument")) + elseif status == UV_ENOMEM || status == UV_ENOBUFS + throw(OutOfMemoryError()) + end + uv_error("getnameinfo", status) + end + ct = current_task() + preserve_handle(ct) + r = try + uv_req_set_data(req, ct) + wait() + finally + if uv_req_data(req) != C_NULL + # req is still alive, + # so make sure we don't get spurious notifications later + uv_req_set_data(req, C_NULL) + ccall(:uv_cancel, Int32, (Ptr{Cvoid},), req) # try to let libuv know we don't care anymore + else + # done with req + Libc.free(req) + end + unpreserve_handle(ct) + end + if isa(r, UVError) + code = r.code + if code in (UV_EAI_ADDRFAMILY, UV_EAI_AGAIN, UV_EAI_BADFLAGS, + UV_EAI_BADHINTS, UV_EAI_CANCELED, UV_EAI_FAIL, + UV_EAI_FAMILY, UV_EAI_NODATA, UV_EAI_NONAME, + UV_EAI_OVERFLOW, UV_EAI_PROTOCOL, UV_EAI_SERVICE, + UV_EAI_SOCKTYPE) + throw(DNSError(repr(address), code)) + elseif code == UV_EAI_MEMORY + throw(OutOfMemoryError()) + else + throw(UVError("getnameinfo", code)) + end + end + return r::String +end + +const _sizeof_uv_interface_address = ccall(:jl_uv_sizeof_interface_address,Int32,()) + +""" + getipaddr() -> IPAddr + +Get the IP address of the local machine. +""" +function getipaddr() + addr_ref = Ref{Ptr{UInt8}}(C_NULL) + count_ref = Ref{Int32}(1) + lo_present = false + err = ccall(:jl_uv_interface_addresses, Int32, (Ref{Ptr{UInt8}}, Ref{Int32}), addr_ref, count_ref) + uv_error("getlocalip", err) + addr, count = addr_ref[], count_ref[] + for i = 0:(count-1) + current_addr = addr + i*_sizeof_uv_interface_address + if 1 == ccall(:jl_uv_interface_address_is_internal, Int32, (Ptr{UInt8},), current_addr) + lo_present = true + continue + end + sockaddr = ccall(:jl_uv_interface_address_sockaddr, Ptr{Cvoid}, (Ptr{UInt8},), current_addr) + if ccall(:jl_sockaddr_in_is_ip4, Int32, (Ptr{Cvoid},), sockaddr) == 1 + rv = IPv4(ntoh(ccall(:jl_sockaddr_host4, UInt32, (Ptr{Cvoid},), sockaddr))) + ccall(:uv_free_interface_addresses, Cvoid, (Ptr{UInt8}, Int32), addr, count) + return rv + # Uncomment to enbable IPv6 + #elseif ccall(:jl_sockaddr_in_is_ip6, Int32, (Ptr{Cvoid},), sockaddr) == 1 + # host = Vector{UInt128}(uninitialized, 1) + # ccall(:jl_sockaddr_host6, UInt32, (Ptr{Cvoid}, Ptr{UInt128}), sockaddrr, host) + # return IPv6(ntoh(host[1])) + end + end + ccall(:uv_free_interface_addresses, Cvoid, (Ptr{UInt8}, Int32), addr, count) + return lo_present ? localhost : error("No networking interface available") +end diff --git a/test/netload/nettest.jl b/stdlib/Sockets/test/nettest.jl similarity index 99% rename from test/netload/nettest.jl rename to stdlib/Sockets/test/nettest.jl index 0f7394def95c8..568efb3869953 100644 --- a/test/netload/nettest.jl +++ b/stdlib/Sockets/test/nettest.jl @@ -1,5 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +using Distributed, Sockets + # Run various networking tests checking to see how we perform under large loads addprocs(1) diff --git a/test/socket.jl b/stdlib/Sockets/test/runtests.jl similarity index 91% rename from test/socket.jl rename to stdlib/Sockets/test/runtests.jl index 501e9814d0f0c..74f7e3157f3dd 100644 --- a/test/socket.jl +++ b/stdlib/Sockets/test/runtests.jl @@ -1,6 +1,6 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -using Random +using Sockets, Random @testset "parsing" begin @test ip"127.0.0.1" == IPv4(127,0,0,1) @@ -56,25 +56,25 @@ using Random @test IPv6(UInt16(1), UInt16(1), UInt16(1), UInt16(1), UInt16(1), UInt16(1), UInt16(1), UInt16(1)) == IPv6(1,1,1,1,1,1,1,1) - @test_throws BoundsError Base.ipv6_field(IPv6(0xffff7f000001), -1) - @test_throws BoundsError Base.ipv6_field(IPv6(0xffff7f000001), 9) + @test_throws BoundsError Sockets.ipv6_field(IPv6(0xffff7f000001), -1) + @test_throws BoundsError Sockets.ipv6_field(IPv6(0xffff7f000001), 9) end @testset "InetAddr constructor" begin - inet = Base.InetAddr(IPv4(127,0,0,1), 1024) + inet = Sockets.InetAddr(IPv4(127,0,0,1), 1024) @test inet.host == ip"127.0.0.1" @test inet.port == 1024 end @testset "InetAddr invalid port" begin - @test_throws InexactError Base.InetAddr(IPv4(127,0,0,1), -1) - @test_throws InexactError Base.InetAddr(IPv4(127,0,0,1), typemax(UInt16)+1) + @test_throws InexactError Sockets.InetAddr(IPv4(127,0,0,1), -1) + @test_throws InexactError Sockets.InetAddr(IPv4(127,0,0,1), typemax(UInt16)+1) end @testset "isless and comparisons" begin @test ip"1.2.3.4" < ip"1.2.3.7" < ip"2.3.4.5" @test ip"1.2.3.4" >= ip"1.2.3.4" >= ip"1.2.3.1" @test isless(ip"1.2.3.4", ip"1.2.3.5") - @test_throws MethodError sort[ip"2.3.4.5", ip"1.2.3.4", ip"2001:1:2::1"] + @test_throws MethodError sort([ip"2.3.4.5", ip"1.2.3.4", ip"2001:1:2::1"]) end @testset "RFC 5952 Compliance" begin @@ -92,13 +92,13 @@ defaultport = rand(2000:4000) tsk = @async begin local (p, s) = listenany(testport) @test p != 0 - @test getsockname(s) == (Base.localhost, p) + @test getsockname(s) == (Sockets.localhost, p) put!(port, p) for i in 1:3 sock = accept(s) - @test getsockname(sock) == (Base.localhost, p) + @test getsockname(sock) == (Sockets.localhost, p) let peer = getpeername(sock)::Tuple{IPAddr, UInt16} - @test peer[1] == Base.localhost + @test peer[1] == Sockets.localhost @test 0 != peer[2] != p end # test write call @@ -117,16 +117,16 @@ defaultport = rand(2000:4000) wait(port) let p = fetch(port) otherip = getipaddr() - if otherip != Base.localhost + if otherip != Sockets.localhost @test_throws Base.UVError("connect", Base.UV_ECONNREFUSED) connect(otherip, p) end for i in 1:3 client = connect(p) let name = getsockname(client)::Tuple{IPAddr, UInt16} - @test name[1] == Base.localhost + @test name[1] == Sockets.localhost @test 0 != name[2] != p end - @test getpeername(client) == (Base.localhost, p) + @test getpeername(client) == (Sockets.localhost, p) @test read(client, String) == "Hello World\n" * ("a1\n"^100) end end @@ -135,10 +135,10 @@ defaultport = rand(2000:4000) mktempdir() do tmpdir socketname = Sys.iswindows() ? ("\\\\.\\pipe\\uv-test-" * randstring(6)) : joinpath(tmpdir, "socket") - c = Base.Condition() + c = Condition() tsk = @async begin s = listen(socketname) - Base.notify(c) + notify(c) sock = accept(s) write(sock,"Hello World\n") close(s) @@ -180,10 +180,10 @@ end @test try getaddrinfo(localhost, IPv6)::IPv6 != ip"::" catch ex - isa(ex, Base.DNSError) && ex.code == Base.UV_EAI_NONAME && ex.host == localhost + isa(ex, Sockets.DNSError) && ex.code == Base.UV_EAI_NONAME && ex.host == localhost end end - @test_throws Base.DNSError getaddrinfo(".invalid") + @test_throws Sockets.DNSError getaddrinfo(".invalid") @test_throws ArgumentError getaddrinfo("localhost\0") # issue #10994 @test_throws Base.UVError("connect", Base.UV_ECONNREFUSED) connect(ip"127.0.0.1", 21452) end @@ -221,11 +221,11 @@ let localhost = getaddrinfo("localhost") close(server2) end -@test_throws Base.DNSError connect(".invalid", 80) +@test_throws Sockets.DNSError connect(".invalid", 80) @testset "UDPSocket" begin # test show() function for UDPSocket() - @test repr(UDPSocket()) == "UDPSocket(init)" + @test endswith(repr(UDPSocket()), "UDPSocket(init)") a = UDPSocket() b = UDPSocket() bind(a, ip"127.0.0.1", randport) @@ -393,10 +393,10 @@ end end @testset "connect!" begin - # test the method matching connect!(::TCPSocket, ::Base.InetAddr{T<:Base.IPAddr}) - let addr = Base.InetAddr(ip"127.0.0.1", 4444) + # test the method matching connect!(::TCPSocket, ::Sockets.InetAddr{T<:Base.IPAddr}) + let addr = Sockets.InetAddr(ip"127.0.0.1", 4444) - function test_connect(addr::Base.InetAddr) + function test_connect(addr::Sockets.InetAddr) srv = listen(addr) @async try c = accept(srv); close(c) catch end @@ -423,7 +423,7 @@ end end @testset "TCPServer constructor" begin - s = Base.TCPServer(; delay=false) + s = Sockets.TCPServer(; delay=false) if ccall(:jl_has_so_reuseport, Int32, ()) == 1 @test 0 == ccall(:jl_tcp_reuseport, Int32, (Ptr{Cvoid},), s.handle) end diff --git a/test/choosetests.jl b/test/choosetests.jl index 8d5a4afd5c11c..c3044693373bc 100644 --- a/test/choosetests.jl +++ b/test/choosetests.jl @@ -1,6 +1,6 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -using Random +using Random, Sockets const STDLIB_DIR = joinpath(Sys.BINDIR, "..", "share", "julia", "site", "v$(VERSION.major).$(VERSION.minor)") const STDLIBS = readdir(STDLIB_DIR) @@ -43,7 +43,7 @@ function choosetests(choices = []) "operators", "path", "ccall", "parse", "loading", "bigint", "bigfloat", "sorting", "statistics", "spawn", "backtrace", "file", "read", "version", "namedtuple", - "mpfr", "broadcast", "complex", "socket", + "mpfr", "broadcast", "complex", "floatapprox", "stdlib", "reflection", "regex", "float16", "combinatorics", "sysinfo", "env", "rounding", "ranges", "mod2pi", "euler", "show", @@ -164,7 +164,7 @@ function choosetests(choices = []) filter!(x -> (x != "Profile"), tests) end - net_required_for = ["socket", "LibGit2"] + net_required_for = ["Sockets", "LibGit2"] net_on = true try ipa = getipaddr() diff --git a/test/compile.jl b/test/compile.jl index ee6722590801c..da4b8853bce54 100644 --- a/test/compile.jl +++ b/test/compile.jl @@ -219,7 +219,7 @@ try [:Base64, :CRC32c, :Dates, :DelimitedFiles, :Distributed, :FileWatching, :Markdown, :Future, :IterativeEigensolvers, :Libdl, :LinearAlgebra, :Logging, :Mmap, :Printf, :Profile, :Random, :Serialization, :SharedArrays, :SparseArrays, :SuiteSparse, :Test, - :Unicode, :REPL, :InteractiveUtils, :Pkg, :Pkg3, :LibGit2, :SHA, :UUIDs])) + :Unicode, :REPL, :InteractiveUtils, :Pkg, :Pkg3, :LibGit2, :SHA, :UUIDs, :Sockets])) @test discard_module.(deps) == deps1 @test current_task()(0x01, 0x4000, 0x30031234) == 2 diff --git a/test/read.jl b/test/read.jl index 7f43509ce5cad..a88308d957087 100644 --- a/test/read.jl +++ b/test/read.jl @@ -1,7 +1,6 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -using DelimitedFiles -using Random +using DelimitedFiles, Random, Sockets mktempdir() do dir diff --git a/test/spawn.jl b/test/spawn.jl index a64b5fdda0d6e..9a1e573770ba0 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -4,7 +4,7 @@ # Cross Platform tests for spawn. # ################################### -using Random +using Random, Sockets valgrind_off = ccall(:jl_running_on_valgrind, Cint, ()) == 0 From 7055d4c94b2ff73b3838be3fb4e44f65828f83e8 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 1 Mar 2018 16:53:13 -0500 Subject: [PATCH 07/28] codegen: emit archive files (#26240) This is intended to give us more flexibility in the future to emit more files to build up the output in more incremental pieces. --- Makefile | 13 ++- src/jitlayers.cpp | 197 ++++++++++++++++++++--------------- src/llvm-multiversioning.cpp | 3 + 3 files changed, 122 insertions(+), 91 deletions(-) diff --git a/Makefile b/Makefile index 8d3073dda27b0..8eec035867f68 100644 --- a/Makefile +++ b/Makefile @@ -164,8 +164,9 @@ $(build_sysconfdir)/julia/startup.jl: $(JULIAHOME)/etc/startup.jl | $(build_sysc $(build_datarootdir)/julia/julia-config.jl : $(JULIAHOME)/contrib/julia-config.jl | $(build_datarootdir)/julia $(INSTALL_M) $< $(dir $@) -$(build_private_libdir)/%.$(SHLIB_EXT): $(build_private_libdir)/%.o - @$(call PRINT_LINK, $(CXX) $(LDFLAGS) -shared $(fPIC) -L$(build_private_libdir) -L$(build_libdir) -L$(build_shlibdir) -o $@ $< \ +$(build_private_libdir)/%.$(SHLIB_EXT): $(build_private_libdir)/%-o.a + @$(call PRINT_LINK, $(CXX) $(LDFLAGS) -shared $(fPIC) -L$(build_private_libdir) -L$(build_libdir) -L$(build_shlibdir) -o $@ \ + $(WHOLE_ARCHIVE) $< $(NO_WHOLE_ARCHIVE) \ $(if $(findstring -debug,$(notdir $@)),-ljulia-debug,-ljulia) \ $$([ $(OS) = WINNT ] && echo '' -lssp)) @$(INSTALL_NAME_CMD)$(notdir $@) $@ @@ -214,15 +215,13 @@ $(build_private_libdir)/basecompiler.ji: $(CORE_SRCS) $(COMPILER_SRCS) | $(build RELBUILDROOT := $(shell $(JULIAHOME)/contrib/relative_path.sh "$(JULIAHOME)/base" "$(BUILDROOT)/base/") COMMA:=, define sysimg_builder -$$(build_private_libdir)/sys$1.o: $$(build_private_libdir)/basecompiler.ji $$(JULIAHOME)/VERSION $$(BASE_SRCS) $$(STDLIB_SRCS) +$$(build_private_libdir)/sys$1-o.a: $$(build_private_libdir)/basecompiler.ji $$(JULIAHOME)/VERSION $$(BASE_SRCS) $$(STDLIB_SRCS) @$$(call PRINT_JULIA, cd $$(JULIAHOME)/base && \ - if $$(call spawn,$3) $2 -C "$$(JULIA_CPU_TARGET)" --output-o $$(call cygpath_w,$$@).tmp $$(JULIA_SYSIMG_BUILD_FLAGS) \ + if ! $$(call spawn,$3) $2 -C "$$(JULIA_CPU_TARGET)" --output-o $$(call cygpath_w,$$@) $$(JULIA_SYSIMG_BUILD_FLAGS) \ --startup-file=no --warn-overwrite=yes --sysimage $$(call cygpath_w,$$<) sysimg.jl $$(RELBUILDROOT); then \ - mv $$@.tmp $$@; \ - else \ echo '*** This error is usually fixed by running `make clean`. If the error persists$$(COMMA) try `make cleanall`. ***' && false; \ fi ) -.SECONDARY: $(build_private_libdir)/sys$1.o +.SECONDARY: $(build_private_libdir)/sys$1-o.a endef $(eval $(call sysimg_builder,,-O3,$(JULIA_EXECUTABLE_release))) $(eval $(call sysimg_builder,-debug,-O0,$(JULIA_EXECUTABLE_debug))) diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 1228d76d462ae..4b4b82869d3e9 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -46,6 +46,7 @@ namespace llvm { #include #include #include +#include "llvm/Object/ArchiveWriter.h" // target support #include @@ -1019,39 +1020,41 @@ static void emit_offset_table(Module *mod, const std::vector &vars name); } - -static void jl_gen_llvm_globaldata(Module *mod, const char *sysimg_data, size_t sysimg_len) +static void emit_result(std::vector &Archive, SmallVectorImpl &OS, + StringRef Name, std::vector &outputs) { - emit_offset_table(mod, jl_sysimg_gvars, "jl_sysimg_gvars"); - emit_offset_table(mod, jl_sysimg_fvars, "jl_sysimg_fvars"); - addComdat(new GlobalVariable(*mod, - T_size, - true, - GlobalVariable::ExternalLinkage, - ConstantInt::get(T_size, globalUnique+1), - "jl_globalUnique")); + outputs.push_back({ OS.data(), OS.size() }); + Archive.push_back(NewArchiveMember(MemoryBufferRef(outputs.back(), Name))); + OS.clear(); +} - // reflect the address of the jl_RTLD_DEFAULT_handle variable - // back to the caller, so that we can check for consistency issues - GlobalValue *jlRTLD_DEFAULT_var = mod->getNamedValue("jl_RTLD_DEFAULT_handle"); - addComdat(new GlobalVariable(*mod, - jlRTLD_DEFAULT_var->getType(), - true, - GlobalVariable::ExternalLinkage, - jlRTLD_DEFAULT_var, - "jl_RTLD_DEFAULT_handle_pointer")); +static object::Archive::Kind getDefaultForHost(Triple &triple) { + if (triple.isOSDarwin()) +#if JL_LLVM_VERSION >= 50000 + return object::Archive::K_DARWIN; +#else + return object::Archive::K_BSD; +#endif + return object::Archive::K_GNU; +} - if (sysimg_data) { - Constant *data = ConstantDataArray::get(jl_LLVMContext, - ArrayRef((const unsigned char*)sysimg_data, sysimg_len)); - addComdat(new GlobalVariable(*mod, data->getType(), false, - GlobalVariable::ExternalLinkage, - data, "jl_system_image_data"))->setAlignment(64); - Constant *len = ConstantInt::get(T_size, sysimg_len); - addComdat(new GlobalVariable(*mod, len->getType(), true, - GlobalVariable::ExternalLinkage, - len, "jl_system_image_size")); - } +#if JL_LLVM_VERSION >= 60000 +typedef Error ArchiveWriterError; +#else +typedef std::pair ArchiveWriterError; +template +static void handleAllErrors(ArchiveWriterError E, HandlerT Handler) { + if (E.second) + Handler(E); +} +#endif +static void reportWriterError(ArchiveWriterError E) { + std::string ContextStr = E.first.str(); + std::string err; + if (!ContextStr.empty()) + err += ContextStr + ": "; + err += E.second.message(); + jl_safe_printf("ERROR: failed to emit output file %s\n", err.c_str()); } // takes the running content that has collected in the shadow module and dump it to disk @@ -1096,59 +1099,26 @@ void jl_dump_native(const char *bc_fname, const char *unopt_bc_fname, const char addTargetPasses(&PM, TM.get()); // set up optimization passes - std::unique_ptr unopt_bc_OS; - std::unique_ptr bc_OS; - std::unique_ptr obj_OS; - - if (unopt_bc_fname) { - // call output handler directly to avoid special case handling of `-` filename - int FD; - std::error_code EC = sys::fs::openFileForWrite(unopt_bc_fname, FD, sys::fs::F_None); - unopt_bc_OS.reset(new raw_fd_ostream(FD, true)); - std::string err; - if (EC) - err = "ERROR: failed to open --output-unopt-bc file '" + std::string(unopt_bc_fname) + "': " + EC.message(); - if (!err.empty()) - jl_safe_printf("%s\n", err.c_str()); - else { - PM.add(createBitcodeWriterPass(*unopt_bc_OS.get())); - } - } - + SmallVector bc_Buffer; + SmallVector obj_Buffer; + SmallVector unopt_bc_Buffer; + raw_svector_ostream bc_OS(bc_Buffer); + raw_svector_ostream obj_OS(obj_Buffer); + raw_svector_ostream unopt_bc_OS(unopt_bc_Buffer); + std::vector bc_Archive; + std::vector obj_Archive; + std::vector unopt_bc_Archive; + std::vector outputs; + + if (unopt_bc_fname) + PM.add(createBitcodeWriterPass(unopt_bc_OS)); if (bc_fname || obj_fname) addOptimizationPasses(&PM, jl_options.opt_level, true); - - if (bc_fname) { - // call output handler directly to avoid special case handling of `-` filename - int FD; - std::error_code EC = sys::fs::openFileForWrite(bc_fname, FD, sys::fs::F_None); - bc_OS.reset(new raw_fd_ostream(FD, true)); - std::string err; - if (EC) - err = "ERROR: failed to open --output-bc file '" + std::string(bc_fname) + "': " + EC.message(); - if (!err.empty()) - jl_safe_printf("%s\n", err.c_str()); - else { - PM.add(createBitcodeWriterPass(*bc_OS.get())); - } - } - - if (obj_fname) { - // call output handler directly to avoid special case handling of `-` filename - int FD; - std::error_code EC = sys::fs::openFileForWrite(obj_fname, FD, sys::fs::F_None); - obj_OS.reset(new raw_fd_ostream(FD, true)); - std::string err; - if (EC) - err = "ERROR: failed to open --output-o file '" + std::string(obj_fname) + "': " + EC.message(); - if (!err.empty()) - jl_safe_printf("%s\n", err.c_str()); - else { - if (TM->addPassesToEmitFile(PM, *obj_OS.get(), TargetMachine::CGFT_ObjectFile, false)) { - jl_safe_printf("ERROR: target does not support generation of object files\n"); - } - } - } + if (bc_fname) + PM.add(createBitcodeWriterPass(bc_OS)); + if (obj_fname) + if (TM->addPassesToEmitFile(PM, obj_OS, TargetMachine::CGFT_ObjectFile, false)) + jl_safe_printf("ERROR: target does not support generation of object files\n"); // Reset the target triple to make sure it matches the new target machine shadow_output->setTargetTriple(TM->getTargetTriple().str()); @@ -1161,11 +1131,70 @@ void jl_dump_native(const char *bc_fname, const char *unopt_bc_fname, const char #endif // add metadata information - if (imaging_mode) - jl_gen_llvm_globaldata(shadow_output, sysimg_data, sysimg_len); + if (imaging_mode) { + emit_offset_table(shadow_output, jl_sysimg_gvars, "jl_sysimg_gvars"); + emit_offset_table(shadow_output, jl_sysimg_fvars, "jl_sysimg_fvars"); + + // reflect the address of the jl_RTLD_DEFAULT_handle variable + // back to the caller, so that we can check for consistency issues + GlobalValue *jlRTLD_DEFAULT_var = shadow_output->getNamedValue("jl_RTLD_DEFAULT_handle"); + addComdat(new GlobalVariable(*shadow_output, + jlRTLD_DEFAULT_var->getType(), + true, + GlobalVariable::ExternalLinkage, + jlRTLD_DEFAULT_var, + "jl_RTLD_DEFAULT_handle_pointer")); + } // do the actual work - PM.run(*shadow_output); + auto add_output = [&] (Module &M, StringRef unopt_bc_Name, StringRef bc_Name, StringRef obj_Name) { + PM.run(M); + if (unopt_bc_fname) + emit_result(unopt_bc_Archive, unopt_bc_Buffer, unopt_bc_Name, outputs); + if (bc_fname) + emit_result(bc_Archive, bc_Buffer, bc_Name, outputs); + if (obj_fname) + emit_result(obj_Archive, obj_Buffer, obj_Name, outputs); + }; + + add_output(*shadow_output, "unopt.bc", "text.bc", "text.o"); + + LLVMContext &Context = shadow_output->getContext(); + std::unique_ptr sysimage(new Module("sysimage", Context)); + sysimage->setTargetTriple(shadow_output->getTargetTriple()); + sysimage->setDataLayout(shadow_output->getDataLayout()); + + addComdat(new GlobalVariable(*sysimage, + T_size, + true, + GlobalVariable::ExternalLinkage, + ConstantInt::get(T_size, globalUnique + 1), + "jl_globalUnique")); + + if (sysimg_data) { + Constant *data = ConstantDataArray::get(Context, + ArrayRef((const unsigned char*)sysimg_data, sysimg_len)); + addComdat(new GlobalVariable(*sysimage, data->getType(), false, + GlobalVariable::ExternalLinkage, + data, "jl_system_image_data"))->setAlignment(64); + Constant *len = ConstantInt::get(T_size, sysimg_len); + addComdat(new GlobalVariable(*sysimage, len->getType(), true, + GlobalVariable::ExternalLinkage, + len, "jl_system_image_size")); + } + add_output(*sysimage, "data.bc", "data.bc", "data.o"); + + object::Archive::Kind Kind = getDefaultForHost(TheTriple); + if (unopt_bc_fname) + handleAllErrors(writeArchive(unopt_bc_fname, unopt_bc_Archive, true, + Kind, true, false), reportWriterError); + if (bc_fname) + handleAllErrors(writeArchive(bc_fname, bc_Archive, true, + Kind, true, false), reportWriterError); + if (obj_fname) + handleAllErrors(writeArchive(obj_fname, obj_Archive, true, + Kind, true, false), reportWriterError); + imaging_mode = false; } diff --git a/src/llvm-multiversioning.cpp b/src/llvm-multiversioning.cpp index 1121a05eb3d23..a4457fbea5ec9 100644 --- a/src/llvm-multiversioning.cpp +++ b/src/llvm-multiversioning.cpp @@ -1025,6 +1025,9 @@ bool MultiVersioning::runOnModule(Module &M) // * Cloned function -> Original function (add as we clone functions) // * Original function -> Base function (target specific and updated by LLVM) // * ID -> relocation slots (const). + if (M.getName() == "sysimage") + return false; + CloneCtx clone(this, M); // Collect a list of original functions and clone base functions From 718830513910d8313a758199840e63ec2a5a79be Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 1 Mar 2018 17:19:59 -0500 Subject: [PATCH 08/28] store exceptions and backtraces as strings in test `Error` results (#26279) fixes #25297 --- stdlib/Test/src/Test.jl | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/stdlib/Test/src/Test.jl b/stdlib/Test/src/Test.jl index f636d93e6e261..eb546b614b88b 100644 --- a/stdlib/Test/src/Test.jl +++ b/stdlib/Test/src/Test.jl @@ -132,6 +132,18 @@ mutable struct Error <: Result value backtrace source::LineNumberNode + + function Error(test_type, orig_expr, value, bt, source) + if test_type === :test_error + bt = scrub_backtrace(bt) + end + if test_type === :test_error || test_type === :nontest_error + bt_str = sprint(showerror, value, bt) + else + bt_str = "" + end + new(test_type, orig_expr, repr(value), bt_str, source) + end end function Base.show(io::IO, t::Error) if t.test_type == :test_interrupted @@ -146,12 +158,11 @@ function Base.show(io::IO, t::Error) println(io, " Expression: ", t.orig_expr) print( io, " Value: ", t.value) elseif t.test_type == :test_error - println(io, " Test threw an exception of type ", typeof(t.value)) + println(io, " Test threw exception ", t.value) println(io, " Expression: ", t.orig_expr) # Capture error message and indent to match - errmsg = sprint(showerror, t.value, scrub_backtrace(t.backtrace)) print(io, join(map(line->string(" ",line), - split(errmsg, "\n")), "\n")) + split(t.backtrace, "\n")), "\n")) elseif t.test_type == :test_unbroken # A test that was expected to fail did not println(io, " Unexpected Pass") @@ -159,11 +170,10 @@ function Base.show(io::IO, t::Error) println(io, " Got correct result, please change to @test if no longer broken.") elseif t.test_type == :nontest_error # we had an error outside of a @test - println(io, " Got an exception of type $(typeof(t.value)) outside of a @test") + println(io, " Got exception $(t.value) outside of a @test") # Capture error message and indent to match - errmsg = sprint(showerror, t.value, t.backtrace) print(io, join(map(line->string(" ",line), - split(errmsg, "\n")), "\n")) + split(t.backtrace, "\n")), "\n")) end end From ea62c00ebd2c0b287c90db70706b2a8ca592449a Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 1 Mar 2018 19:17:49 -0500 Subject: [PATCH 09/28] deprecate `spawn(cmd)` to `run(cmd, wait=false)` (#26130) add `read` and `write` keyword arguments to `open` for processes fixes #25965 --- base/deprecated.jl | 3 + base/exports.jl | 1 - base/precompile.jl | 2 - base/process.jl | 103 ++++++++++++++---------- base/stream.jl | 2 +- doc/src/base/base.md | 1 - stdlib/InteractiveUtils/src/editless.jl | 2 +- stdlib/LibGit2/test/libgit2.jl | 4 +- stdlib/REPL/test/repl.jl | 2 +- test/cmdlineargs.jl | 6 +- test/embedding/embedding-test.jl | 2 +- test/spawn.jl | 21 ++--- 12 files changed, 81 insertions(+), 68 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 1889ad3426668..5ffaeab35a8e7 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1448,6 +1448,9 @@ end @deprecate round(x, digits, base) round(x, digits, base = base) @deprecate signif(x, digits, base) signif(x, digits, base = base) +# issue #25965 +@deprecate spawn(cmds::AbstractCmd) run(cmds, wait = false) + # Remember to delete the module when removing this @eval Base.Math module JuliaLibm Base.@deprecate log Base.log diff --git a/base/exports.jl b/base/exports.jl index 156bd0a87dd02..d5f68d99eb436 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -928,7 +928,6 @@ export process_running, run, setenv, - spawn, success, withenv, diff --git a/base/precompile.jl b/base/precompile.jl index 55ee6fd024163..a9b3d8e177560 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -133,7 +133,6 @@ precompile(Tuple{getfield(Base, Symbol("#kw##printstyled")), NamedTuple{(:bold, precompile(Tuple{getfield(Base, Symbol("#kw##printstyled")), NamedTuple{(:bold, :color), Tuple{Bool, Symbol}}, typeof(Base.printstyled), REPL.Terminals.TTYTerminal, String}) precompile(Tuple{getfield(Base, Symbol("#kw##printstyled")), NamedTuple{(:color,), Tuple{Symbol}}, typeof(Base.printstyled), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, String}) precompile(Tuple{getfield(Base, Symbol("#kw##show_trace_entry")), NamedTuple{(:prefix,), Tuple{String}}, typeof(Base.show_trace_entry), Base.IOContext{REPL.Terminals.TTYTerminal}, Base.StackTraces.StackFrame, Int64}) -precompile(Tuple{getfield(Base, Symbol("#kw##spawn")), NamedTuple{(:chain,), Tuple{Nothing}}, typeof(Base.spawn), Base.Cmd, Tuple{Base.Pipe, Base.TTY, Base.IOStream}}) precompile(Tuple{getfield(Base, Symbol("#kw##unindent")), NamedTuple{(:tabwidth,), Tuple{Int64}}, typeof(Base.unindent), String, Int64}) precompile(Tuple{getfield(Base, Symbol("#kw##with_output_color")), NamedTuple{(:bold,), Tuple{Bool}}, typeof(Base.with_output_color), typeof(Base.print), Symbol, Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, String}) precompile(Tuple{getfield(Base, Symbol("#kw##with_output_color")), NamedTuple{(:bold,), Tuple{Bool}}, typeof(Base.with_output_color), typeof(Base.print), Symbol, REPL.Terminals.TTYTerminal, String}) @@ -579,7 +578,6 @@ precompile(Tuple{typeof(Base.similar), Array{Float64, 1}}) precompile(Tuple{typeof(Base.sort!), Array{Int64, 1}, Base.Sort.QuickSortAlg, Base.Order.Perm{Base.Order.ForwardOrdering, Array{Tuple{Float64, Int64}, 1}}}) precompile(Tuple{typeof(Base.sort!), Array{Int64, 1}, Base.Sort.QuickSortAlg, Base.Order.Perm{Base.Order.ForwardOrdering, Array{Tuple{Int64, Float64}, 1}}}) precompile(Tuple{typeof(Base.sort), Array{Float64, 1}}) -precompile(Tuple{typeof(Base.spawn), Base.CmdRedirect, Tuple{Base.Pipe, Base.TTY, Base.IOStream}}) precompile(Tuple{typeof(Base.start), Array{AbstractString, 1}}) precompile(Tuple{typeof(Base.start), Array{Expr, 1}}) precompile(Tuple{typeof(Base.start), Array{Function, 1}}) diff --git a/base/process.jl b/base/process.jl index e9a76b1a10f7f..77a04997bcb07 100644 --- a/base/process.jl +++ b/base/process.jl @@ -397,22 +397,22 @@ function _uv_hook_close(proc::Process) notify(proc.closenotify) end -function spawn(redirect::CmdRedirect, stdios::StdIOSet; chain::Union{ProcessChain, Nothing}=nothing) - spawn(redirect.cmd, - (redirect.stream_no == STDIN_NO ? redirect.handle : stdios[1], - redirect.stream_no == STDOUT_NO ? redirect.handle : stdios[2], - redirect.stream_no == STDERR_NO ? redirect.handle : stdios[3]), +function _spawn(redirect::CmdRedirect, stdios::StdIOSet; chain::Union{ProcessChain, Nothing}=nothing) + _spawn(redirect.cmd, + (redirect.stream_no == STDIN_NO ? redirect.handle : stdios[1], + redirect.stream_no == STDOUT_NO ? redirect.handle : stdios[2], + redirect.stream_no == STDERR_NO ? redirect.handle : stdios[3]), chain=chain) end -function spawn(cmds::OrCmds, stdios::StdIOSet; chain::Union{ProcessChain, Nothing}=nothing) +function _spawn(cmds::OrCmds, stdios::StdIOSet; chain::Union{ProcessChain, Nothing}=nothing) if chain === nothing chain = ProcessChain(stdios) end in_pipe, out_pipe = link_pipe(false, false) try - spawn(cmds.a, (stdios[1], out_pipe, stdios[3]), chain=chain) - spawn(cmds.b, (in_pipe, stdios[2], stdios[3]), chain=chain) + _spawn(cmds.a, (stdios[1], out_pipe, stdios[3]), chain=chain) + _spawn(cmds.b, (in_pipe, stdios[2], stdios[3]), chain=chain) finally close_pipe_sync(out_pipe) close_pipe_sync(in_pipe) @@ -420,14 +420,14 @@ function spawn(cmds::OrCmds, stdios::StdIOSet; chain::Union{ProcessChain, Nothin return chain end -function spawn(cmds::ErrOrCmds, stdios::StdIOSet; chain::Union{ProcessChain, Nothing}=nothing) +function _spawn(cmds::ErrOrCmds, stdios::StdIOSet; chain::Union{ProcessChain, Nothing}=nothing) if chain === nothing chain = ProcessChain(stdios) end in_pipe, out_pipe = link_pipe(false, false) try - spawn(cmds.a, (stdios[1], stdios[2], out_pipe), chain=chain) - spawn(cmds.b, (in_pipe, stdios[2], stdios[3]), chain=chain) + _spawn(cmds.a, (stdios[1], stdios[2], out_pipe), chain=chain) + _spawn(cmds.b, (in_pipe, stdios[2], stdios[3]), chain=chain) finally close_pipe_sync(out_pipe) close_pipe_sync(in_pipe) @@ -503,7 +503,7 @@ function setup_stdio(anon::Function, stdio::StdIOSet) nothing end -function spawn(cmd::Cmd, stdios::StdIOSet; chain::Union{ProcessChain, Nothing}=nothing) +function _spawn(cmd::Cmd, stdios::StdIOSet; chain::Union{ProcessChain, Nothing}=nothing) if isempty(cmd.exec) throw(ArgumentError("cannot spawn empty command")) end @@ -519,13 +519,13 @@ function spawn(cmd::Cmd, stdios::StdIOSet; chain::Union{ProcessChain, Nothing}=n return pp end -function spawn(cmds::AndCmds, stdios::StdIOSet; chain::Union{ProcessChain, Nothing}=nothing) +function _spawn(cmds::AndCmds, stdios::StdIOSet; chain::Union{ProcessChain, Nothing}=nothing) if chain === nothing chain = ProcessChain(stdios) end setup_stdio(stdios) do stdios - spawn(cmds.a, stdios, chain=chain) - spawn(cmds.b, stdios, chain=chain) + _spawn(cmds.a, stdios, chain=chain) + _spawn(cmds.b, stdios, chain=chain) end return chain end @@ -548,13 +548,8 @@ spawn_opts_inherit(stdios::StdIOSet) = (stdios,) spawn_opts_inherit(in::Redirectable=RawFD(0), out::Redirectable=RawFD(1), err::Redirectable=RawFD(2), args...) = ((in, out, err), args...) -""" - spawn(command) - -Run a command object asynchronously, returning the resulting `Process` object. -""" -spawn(cmds::AbstractCmd, args...; chain::Union{ProcessChain, Nothing}=nothing) = - spawn(cmds, spawn_opts_swallow(args...)...; chain=chain) +_spawn(cmds::AbstractCmd, args...; chain::Union{ProcessChain, Nothing}=nothing) = + _spawn(cmds, spawn_opts_swallow(args...)...; chain=chain) function eachline(cmd::AbstractCmd; chomp=nothing, keep::Bool=false) if chomp !== nothing @@ -562,7 +557,7 @@ function eachline(cmd::AbstractCmd; chomp=nothing, keep::Bool=false) depwarn("The `chomp=$chomp` argument to `eachline` is deprecated in favor of `keep=$keep`.", :eachline) end _stdout = Pipe() - processes = spawn(cmd, (devnull, _stdout, stderr)) + processes = _spawn(cmd, (devnull, _stdout, stderr)) close(_stdout.in) out = _stdout.out # implicitly close after reading lines, since we opened @@ -570,38 +565,50 @@ function eachline(cmd::AbstractCmd; chomp=nothing, keep::Bool=false) ondone=()->(close(out); success(processes) || pipeline_error(processes)))::EachLine end +function open(cmds::AbstractCmd, mode::AbstractString, other::Redirectable=devnull) + if mode == "r+" || mode == "w+" + return open(cmds, other, read = true, write = true) + elseif mode == "r" + return open(cmds, other) + elseif mode == "w" + return open(cmds, other, write = true) + else + throw(ArgumentError("mode must be \"r\" or \"w\", not \"$mode\"")) + end +end + # return a Process object to read-to/write-from the pipeline """ - open(command, mode::AbstractString="r", stdio=devnull) + open(command, stdio=devnull; write::Bool = false, read::Bool = !write) -Start running `command` asynchronously, and return a tuple `(stream,process)`. If `mode` is -`"r"`, then `stream` reads from the process's standard output and `stdio` optionally -specifies the process's standard input stream. If `mode` is `"w"`, then `stream` writes to +Start running `command` asynchronously, and return a tuple `(stream,process)`. If `read` is +true, then `stream` reads from the process's standard output and `stdio` optionally +specifies the process's standard input stream. If `write` is true, then `stream` writes to the process's standard input and `stdio` optionally specifies the process's standard output stream. """ -function open(cmds::AbstractCmd, mode::AbstractString="r", other::Redirectable=devnull) - if mode == "r+" || mode == "w+" - other === devnull || throw(ArgumentError("no other stream for mode rw+")) +function open(cmds::AbstractCmd, other::Redirectable=devnull; write::Bool = false, read::Bool = !write) + if read && write + other === devnull || throw(ArgumentError("no other stream can be specified in read-write mode")) in = Pipe() out = Pipe() - processes = spawn(cmds, (in,out,stderr)) + processes = _spawn(cmds, (in,out,stderr)) close(in.out) close(out.in) - elseif mode == "r" + elseif read in = other out = Pipe() - processes = spawn(cmds, (in,out,stderr)) + processes = _spawn(cmds, (in,out,stderr)) close(out.in) if isa(processes, ProcessChain) # for open(cmd) deprecation processes = ProcessChain(processes, :out) else processes.openstream = :out end - elseif mode == "w" + elseif write in = Pipe() out = other - processes = spawn(cmds, (in,out,stderr)) + processes = _spawn(cmds, (in,out,stderr)) close(in.out) if isa(processes, ProcessChain) # for open(cmd) deprecation processes = ProcessChain(processes, :in) @@ -609,7 +616,7 @@ function open(cmds::AbstractCmd, mode::AbstractString="r", other::Redirectable=d processes.openstream = :in end else - throw(ArgumentError("mode must be \"r\" or \"w\", not \"$mode\"")) + processes = _spawn(cmds) end return processes end @@ -645,14 +652,26 @@ end read(cmd::AbstractCmd, ::Type{String}) = String(read(cmd)) """ - run(command, args...) + run(command, args...; wait::Bool = true) Run a command object, constructed with backticks. Throws an error if anything goes wrong, -including the process exiting with a non-zero status. +including the process exiting with a non-zero status (when `wait` is true). + +If `wait` is false, the process runs asynchronously. You can later wait for it and check +its exit status by calling `success` on the returned process object. + +When `wait` is false, the process' I/O streams are directed to `devnull`. +When `wait` is true, I/O streams are shared with the parent process. +Use [`pipeline`](@ref) to control I/O redirection. """ -function run(cmds::AbstractCmd, args...) - ps = spawn(cmds, spawn_opts_inherit(args...)...) - success(ps) ? nothing : pipeline_error(ps) +function run(cmds::AbstractCmd, args...; wait::Bool = true) + if wait + ps = _spawn(cmds, spawn_opts_inherit(args...)...) + success(ps) || pipeline_error(ps) + else + ps = _spawn(cmds, spawn_opts_swallow(args...)...) + end + return ps end # some common signal numbers that are usually available on all platforms @@ -686,7 +705,7 @@ success(procs::ProcessChain) = success(procs.processes) Run a command object, constructed with backticks, and tell whether it was successful (exited with a code of 0). An exception is raised if the process cannot be started. """ -success(cmd::AbstractCmd) = success(spawn(cmd)) +success(cmd::AbstractCmd) = success(_spawn(cmd)) function pipeline_error(proc::Process) if !proc.cmd.ignorestatus diff --git a/base/stream.jl b/base/stream.jl index 93e9db949ac56..789297918b7e7 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -554,7 +554,7 @@ julia> err = Pipe() # After this `err` will be initialized and you may read `foo`'s # stderr from the `err` pipe. -julia> spawn(pipeline(pipeline(`foo`, stderr=err), `cat`)) +julia> run(pipeline(pipeline(`foo`, stderr=err), `cat`), wait=false) ``` """ Pipe() = Pipe(PipeEndpoint(), PipeEndpoint()) diff --git a/doc/src/base/base.md b/doc/src/base/base.md index 254dc03b019ca..2c1db70c5d291 100644 --- a/doc/src/base/base.md +++ b/doc/src/base/base.md @@ -229,7 +229,6 @@ Base.skipmissing ```@docs Base.run -Base.spawn Base.devnull Base.success Base.process_running diff --git a/stdlib/InteractiveUtils/src/editless.jl b/stdlib/InteractiveUtils/src/editless.jl index fd920b413fa58..d3b4b70b197e7 100644 --- a/stdlib/InteractiveUtils/src/editless.jl +++ b/stdlib/InteractiveUtils/src/editless.jl @@ -73,7 +73,7 @@ function edit(path::AbstractString, line::Integer=0) (Ptr{Cvoid}, Cwstring, Cwstring, Ptr{Cvoid}, Ptr{Cvoid}, Cint), C_NULL, "open", path, C_NULL, C_NULL, 10) ≤ 32) elseif background - spawn(pipeline(cmd, stderr=stderr)) + run(pipeline(cmd, stderr=stderr), wait=false) else run(cmd) end diff --git a/stdlib/LibGit2/test/libgit2.jl b/stdlib/LibGit2/test/libgit2.jl index 62b34cdc9bc41..4fda8e6dc5cfd 100644 --- a/stdlib/LibGit2/test/libgit2.jl +++ b/stdlib/LibGit2/test/libgit2.jl @@ -43,7 +43,7 @@ function challenge_prompt(cmd::Cmd, challenges; timeout::Integer=10, debug::Bool end out = IOBuffer() with_fake_pty() do slave, master - p = spawn(detach(cmd), slave, slave, slave) + p = run(detach(cmd), slave, slave, slave, wait=false) # Kill the process if it takes too long. Typically occurs when process is waiting # for input. @@ -2703,7 +2703,7 @@ mktempdir() do dir # certificate. The minimal server can't actually serve a Git repository. mkdir(joinpath(root, "Example.jl")) pobj = cd(root) do - spawn(`openssl s_server -key $key -cert $cert -WWW -accept $port`) + run(`openssl s_server -key $key -cert $cert -WWW -accept $port`, wait=false) end errfile = joinpath(root, "error") diff --git a/stdlib/REPL/test/repl.jl b/stdlib/REPL/test/repl.jl index c1ecb40c82ad8..01383edde1805 100644 --- a/stdlib/REPL/test/repl.jl +++ b/stdlib/REPL/test/repl.jl @@ -669,7 +669,7 @@ let exename = Base.julia_cmd() TestHelpers.with_fake_pty() do slave, master nENV = copy(ENV) nENV["TERM"] = "dumb" - p = spawn(setenv(`$exename --startup-file=no -q`,nENV),slave,slave,slave) + p = run(setenv(`$exename --startup-file=no -q`,nENV),slave,slave,slave,wait=false) output = readuntil(master,"julia> ",keep=true) if ccall(:jl_running_on_valgrind,Cint,()) == 0 # If --trace-children=yes is passed to valgrind, we will get a diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index 55f644c25a49a..92688887e02a3 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -18,7 +18,7 @@ end function readchomperrors(exename::Cmd) out = Base.PipeEndpoint() err = Base.PipeEndpoint() - p = spawn(exename, devnull, out, err) + p = run(exename, devnull, out, err, wait=false) o = @async(readchomp(out)) e = @async(readchomp(err)) return (success(p), fetch(o), fetch(e)) @@ -390,7 +390,7 @@ let exename = joinpath(Sys.BINDIR, Base.julia_exename()), "$sysname.nonexistent", ) let err = Pipe(), - p = spawn(pipeline(`$exename --sysimage=$nonexist_image`, stderr=err)) + p = run(pipeline(`$exename --sysimage=$nonexist_image`, stderr=err), wait=false) close(err.in) let s = read(err, String) @test contains(s, "ERROR: could not load library \"$nonexist_image\"\n") @@ -403,7 +403,7 @@ let exename = joinpath(Sys.BINDIR, Base.julia_exename()), end end let err = Pipe(), - p = spawn(pipeline(`$exename --sysimage=$libjulia`, stderr=err)) + p = run(pipeline(`$exename --sysimage=$libjulia`, stderr=err), wait=false) close(err.in) let s = read(err, String) @test s == "ERROR: System image file failed consistency check: maybe opened the wrong version?\n" diff --git a/test/embedding/embedding-test.jl b/test/embedding/embedding-test.jl index 4303162b5e278..2be2842ac8967 100644 --- a/test/embedding/embedding-test.jl +++ b/test/embedding/embedding-test.jl @@ -12,7 +12,7 @@ end @testset "embedding example" begin out = Pipe() err = Pipe() - p = spawn(pipeline(Cmd(ARGS), stdin=devnull, stdout=out, stderr=err)) + p = run(pipeline(Cmd(ARGS), stdin=devnull, stdout=out, stderr=err), wait=false) close(out.in) close(err.in) out_task = @async readlines(out) diff --git a/test/spawn.jl b/test/spawn.jl index 9a1e573770ba0..a468df6741de5 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -45,7 +45,7 @@ end @test read(`$echocmd hello \| sort`, String) == "hello | sort\n" @test read(pipeline(`$echocmd hello`, sortcmd), String) == "hello\n" -@test length(spawn(pipeline(`$echocmd hello`, sortcmd)).processes) == 2 +@test length(run(pipeline(`$echocmd hello`, sortcmd), wait=false).processes) == 2 out = read(`$echocmd hello` & `$echocmd world`, String) @test contains(out,"world") @@ -60,7 +60,7 @@ Sys.isunix() && run(pipeline(yescmd, `head`, devnull)) let a, p a = Base.Condition() @schedule begin - p = spawn(pipeline(yescmd,devnull)) + p = run(pipeline(yescmd,devnull), wait=false) Base.notify(a,p) @test !success(p) end @@ -166,7 +166,7 @@ let r, t try wait(r) end - p = spawn(`$sleepcmd 1`); wait(p) + p = run(`$sleepcmd 1`, wait=false); wait(p) @test p.exitcode == 0 return true end @@ -217,21 +217,21 @@ if valgrind_off # valgrind banner here, not "Hello World\n". @test read(pipeline(`$exename --startup-file=no -e 'println(stderr,"Hello World")'`, stderr=catcmd), String) == "Hello World\n" out = Pipe() - proc = spawn(pipeline(`$exename --startup-file=no -e 'println(stderr,"Hello World")'`, stderr = out)) + proc = run(pipeline(`$exename --startup-file=no -e 'println(stderr,"Hello World")'`, stderr = out), wait=false) close(out.in) @test read(out, String) == "Hello World\n" @test success(proc) end # setup_stdio for AbstractPipe -let out = Pipe(), proc = spawn(pipeline(`$echocmd "Hello World"`, stdout=IOContext(out,stdout))) +let out = Pipe(), proc = run(pipeline(`$echocmd "Hello World"`, stdout=IOContext(out,stdout)), wait=false) close(out.in) @test read(out, String) == "Hello World\n" @test success(proc) end # issue #5904 -@test run(pipeline(ignorestatus(falsecmd), truecmd)) === nothing +@test run(pipeline(ignorestatus(falsecmd), truecmd)) isa Base.AbstractPipe @testset "redirect_*" begin let OLD_STDOUT = stdout, @@ -445,11 +445,6 @@ end @test_throws ArgumentError run(Base.AndCmds(``, `$truecmd`)) @test_throws ArgumentError run(Base.AndCmds(`$truecmd`, ``)) -@test_throws ArgumentError spawn(Base.Cmd(``)) -@test_throws ArgumentError spawn(Base.AndCmds(``, ``)) -@test_throws ArgumentError spawn(Base.AndCmds(``, `$echocmd test`)) -@test_throws ArgumentError spawn(Base.AndCmds(`$echocmd test`, ``)) - # tests for reducing over collection of Cmd @test_throws ArgumentError reduce(&, Base.AbstractCmd[]) @test_throws ArgumentError reduce(&, Base.Cmd[]) @@ -507,7 +502,7 @@ end #let out = Pipe(), inpt = Pipe() # Base.link_pipe!(out, reader_supports_async=true) # Base.link_pipe!(inpt, writer_supports_async=true) -# p = spawn(pipeline(catcmd, stdin=inpt, stdout=out, stderr=devnull)) +# p = run(pipeline(catcmd, stdin=inpt, stdout=out, stderr=devnull), wait=false) # @async begin # feed cat with 2 MB of data (zeros) # write(inpt, zeros(UInt8, 1048576 * 2)) # close(inpt) @@ -519,7 +514,7 @@ end #end # `kill` error conditions -let p = spawn(`$sleepcmd 100`) +let p = run(`$sleepcmd 100`, wait=false) # Should throw on invalid signals @test_throws Base.UVError kill(p, typemax(Cint)) kill(p) From d480d1be3e00b5587ec8cef4bcf54ba6ce7a3015 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 1 Mar 2018 23:53:45 -0500 Subject: [PATCH 10/28] deprecate bin, oct, dec, hex, and base in favor of `string` and keyword args (#25804) * deprecate bin, oct, dec, hex, and base in favor of `string` and keyword args * Work around inference problem in `div(::UInt128, ::UInt128)` --- base/char.jl | 2 +- base/deprecated.jl | 23 +- base/exports.jl | 5 - base/gmp.jl | 23 +- base/grisu/grisu.jl | 4 +- base/int.jl | 6 +- base/intfuncs.jl | 116 +++------- base/logging.jl | 2 +- base/operators.jl | 15 +- base/printf.jl | 2 +- base/show.jl | 10 +- base/stat.jl | 2 +- base/strings/io.jl | 10 +- base/strings/util.jl | 4 +- base/task.jl | 2 +- base/util.jl | 2 +- doc/src/base/numbers.md | 5 - doc/src/manual/unicode-input.md | 2 +- stdlib/Dates/src/io.jl | 10 +- stdlib/Distributed/src/cluster.jl | 2 +- stdlib/LibGit2/src/blob.jl | 2 +- stdlib/LibGit2/src/deprecated.jl | 5 +- stdlib/LibGit2/src/oid.jl | 10 +- stdlib/LibGit2/src/types.jl | 2 +- stdlib/LibGit2/test/libgit2.jl | 8 +- stdlib/Profile/src/Profile.jl | 2 +- stdlib/Random/src/DSFMT.jl | 2 +- stdlib/Serialization/src/Serialization.jl | 2 +- stdlib/Sockets/src/IPAddr.jl | 10 +- test/bigint.jl | 54 ++--- test/intfuncs.jl | 28 +-- test/numbers.jl | 262 +++++++++++----------- test/operators.jl | 2 +- test/perf/micro/perf.jl | 2 +- test/perf/micro/perf.py | 4 +- test/runtests.jl | 2 +- test/strings/basic.jl | 2 +- test/strings/io.jl | 18 +- 38 files changed, 303 insertions(+), 361 deletions(-) diff --git a/base/char.jl b/base/char.jl index be185b4c55581..4d994d690a726 100644 --- a/base/char.jl +++ b/base/char.jl @@ -165,7 +165,7 @@ function show(io::IO, ::MIME"text/plain", c::Char) else u = UInt32(c) end - h = hex(u, u ≤ 0xffff ? 4 : 6) + h = string(u, base = 16, pad = u ≤ 0xffff ? 4 : 6) print(io, (isascii(c) ? "ASCII/" : ""), "Unicode U+", h) else print(io, ": Malformed UTF-8") diff --git a/base/deprecated.jl b/base/deprecated.jl index 5ffaeab35a8e7..7196f1f4bddbe 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -419,8 +419,8 @@ function hex2num(s::AbstractString) end export hex2num -@deprecate num2hex(x::Union{Float16,Float32,Float64}) hex(reinterpret(Unsigned, x), sizeof(x)*2) -@deprecate num2hex(n::Integer) hex(n, sizeof(n)*2) +@deprecate num2hex(x::Union{Float16,Float32,Float64}) string(reinterpret(Unsigned, x), base = 16, pad = sizeof(x)*2) +@deprecate num2hex(n::Integer) string(n, base = 16, pad = sizeof(n)*2) # PR #22742: change in isapprox semantics @deprecate rtoldefault(x,y) rtoldefault(x,y,0) false @@ -1394,6 +1394,25 @@ end @deprecate print_with_color(color, args...; kwargs...) printstyled(args...; kwargs..., color=color) +@deprecate base(b, n) string(n, base = b) +@deprecate base(b, n, pad) string(n, base = b, pad = pad) +@deprecate bin(n) string(n, base = 2) +@deprecate bin(n, pad) string(n, base = 2, pad = pad) +@deprecate oct(n) string(n, base = 8) +@deprecate oct(n, pad) string(n, base = 8, pad = pad) +@deprecate dec(n) string(n) +@deprecate dec(n, pad) string(n, pad = pad) +@deprecate hex(n) string(n, base = 16) +@deprecate hex(n, pad) string(n, base = 16, pad = pad) +@deprecate bin(n::Char) string(UInt32(n), base = 2) +@deprecate bin(n::Char, pad) string(UInt32(n), base = 2, pad = pad) +@deprecate oct(n::Char) string(UInt32(n), base = 8) +@deprecate oct(n::Char, pad) string(UInt32(n), base = 8, pad = pad) +@deprecate dec(n::Char) string(UInt32(n)) +@deprecate dec(n::Char, pad) string(UInt32(n), pad = pad) +@deprecate hex(n::Char) string(UInt32(n), base = 16) +@deprecate hex(n::Char, pad) string(UInt32(n), base = 16, pad = pad) + @deprecate which(s::Symbol) which(Main, s) @deprecate IOBuffer(data::AbstractVector{UInt8}, read::Bool, write::Bool=false, maxsize::Integer=typemax(Int)) IOBuffer(data, read=read, write=write, maxsize=maxsize) diff --git a/base/exports.jl b/base/exports.jl index d5f68d99eb436..b7d3241a7eeba 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -559,19 +559,15 @@ export # strings ascii, - base, - bin, bitstring, bytes2hex, chomp, chop, codeunit, codeunits, - dec, digits, digits!, escape_string, - hex, hex2bytes, hex2bytes!, isalpha, @@ -594,7 +590,6 @@ export ncodeunits, ndigits, nextind, - oct, prevind, repeat, replace, diff --git a/base/gmp.jl b/base/gmp.jl index 62a4fe0dacb8c..cd53081e6024b 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -7,7 +7,7 @@ export BigInt import .Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, (~), (&), (|), xor, binomial, cmp, convert, div, divrem, factorial, fld, gcd, gcdx, lcm, mod, ndigits, promote_rule, rem, show, isqrt, string, powermod, - sum, trailing_zeros, trailing_ones, count_ones, base, tryparse_internal, + sum, trailing_zeros, trailing_ones, count_ones, tryparse_internal, bin, oct, dec, hex, isequal, invmod, prevpow2, nextpow2, ndigits0zpb, widen, signed, unsafe_trunc, trunc, iszero, isone, big, flipsign, signbit, hastypemax @@ -593,27 +593,16 @@ flipsign( x::BigInt, y::Integer) = signbit(y) ? -x : x flipsign( x::BigInt, y::BigInt) = signbit(y) ? -x : x # above method to resolving ambiguities with flipsign(::T, ::T) where T<:Signed -string(x::BigInt) = dec(x) show(io::IO, x::BigInt) = print(io, string(x)) -bin(n::BigInt) = base( 2, n) -oct(n::BigInt) = base( 8, n) -dec(n::BigInt) = base(10, n) -hex(n::BigInt) = base(16, n) - -bin(n::BigInt, pad::Int) = base( 2, n, pad) -oct(n::BigInt, pad::Int) = base( 8, n, pad) -dec(n::BigInt, pad::Int) = base(10, n, pad) -hex(n::BigInt, pad::Int) = base(16, n, pad) - -function base(b::Integer, n::BigInt, pad::Integer=1) - b < 0 && return base(Int(b), n, pad, (b>0) & (n.size<0)) - 2 <= b <= 62 || throw(ArgumentError("base must be 2 ≤ base ≤ 62, got $b")) +function string(n::BigInt; base::Integer = 10, pad::Integer = 1) + base < 0 && return Base._base(Int(base), n, pad, (base>0) & (n.size<0)) + 2 <= base <= 62 || throw(ArgumentError("base must be 2 ≤ base ≤ 62, got $base")) iszero(n) && pad < 1 && return "" - nd1 = ndigits(n, b) + nd1 = ndigits(n, base) nd = max(nd1, pad) sv = Base.StringVector(nd + isneg(n)) - GC.@preserve sv MPZ.get_str!(pointer(sv) + nd - nd1, b, n) + GC.@preserve sv MPZ.get_str!(pointer(sv) + nd - nd1, base, n) @inbounds for i = (1:nd-nd1) .+ isneg(n) sv[i] = '0' % UInt8 end diff --git a/base/grisu/grisu.jl b/base/grisu/grisu.jl index 953b386514106..8c4ce7f52d586 100644 --- a/base/grisu/grisu.jl +++ b/base/grisu/grisu.jl @@ -85,7 +85,7 @@ function _show(io::IO, x::AbstractFloat, mode, n::Int, typed, compact) write(io, '0') end write(io, (typed && isa(x,Float32)) ? 'f' : 'e') - write(io, dec(pt-1)) + write(io, string(pt - 1)) typed && isa(x,Float16) && write(io, ")") return elseif pt <= 0 @@ -160,7 +160,7 @@ function _print_shortest(io::IO, x::AbstractFloat, dot::Bool, mode, n::Int) # => ########e### unsafe_write(io, pdigits+0, len) write(io, 'e') - write(io, dec(e)) + write(io, string(e)) return elseif pt <= 0 # => 0.000######## diff --git a/base/int.jl b/base/int.jl index 85ab5eda73b2c..51af020a7fc2e 100644 --- a/base/int.jl +++ b/base/int.jl @@ -330,10 +330,10 @@ julia> a = bswap(4) julia> bswap(a) 4 -julia> bin(1) +julia> string(1, base = 2) "1" -julia> bin(bswap(1)) +julia> string(bswap(1), base = 2) "100000000000000000000000000000000000000000000000000000000" ``` """ @@ -717,7 +717,7 @@ if Core.sizeof(Int) == 4 return Int128(div(BigInt(x), BigInt(y))) end function div(x::UInt128, y::UInt128) - return UInt128(div(BigInt(x), BigInt(y))) + return UInt128(div(BigInt(x), BigInt(y)))::UInt128 end function rem(x::Int128, y::Int128) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 198e3417526b7..fd565cb7a9e0a 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -558,7 +558,7 @@ julia> ndigits(12345) julia> ndigits(1022, 16) 3 -julia> base(16, 1022) +julia> string(1022, base = 16) "3fe" ``` """ @@ -566,8 +566,6 @@ ndigits(x::Integer, b::Integer, pad::Int=1) = max(pad, ndigits0z(x, b)) ## integer to string functions ## -string(x::Union{Int8,Int16,Int32,Int64,Int128}) = dec(x) - function bin(x::Unsigned, pad::Int, neg::Bool) i = neg + max(pad,sizeof(x)<<3-leading_zeros(x)) a = StringVector(i) @@ -620,8 +618,7 @@ end const base36digits = ['0':'9';'a':'z'] const base62digits = ['0':'9';'A':'Z';'a':'z'] - -function base(b::Int, x::Integer, pad::Int, neg::Bool) +function _base(b::Int, x::Integer, pad::Int, neg::Bool) (x >= 0) | (b < 0) || throw(DomainError(x, "For negative `x`, `b` must be negative.")) 2 <= abs(b) <= 62 || throw(ArgumentError("base must satisfy 2 ≤ abs(base) ≤ 62, got $b")) digits = abs(b) <= 36 ? base36digits : base62digits @@ -641,97 +638,42 @@ function base(b::Int, x::Integer, pad::Int, neg::Bool) String(a) end +split_sign(n::Integer) = unsigned(abs(n)), n < 0 +split_sign(n::Unsigned) = n, false + """ - base(base::Integer, n::Integer, pad::Integer=1) + string(n::Integer; base::Integer = 10, pad::Integer = 1) Convert an integer `n` to a string in the given `base`, optionally specifying a number of digits to pad to. ```jldoctest -julia> base(13,5,4) +julia> string(5, base = 13, pad = 4) "0005" -julia> base(5,13,4) +julia> string(13, base = 5, pad = 4) "0023" ``` """ -base(b::Integer, n::Integer, pad::Integer=1) = - base(Int(b), b > 0 ? unsigned(abs(n)) : convert(Signed, n), Int(pad), (b>0) & (n<0)) - -for sym in (:bin, :oct, :dec, :hex) - @eval begin - ($sym)(x::Unsigned, p::Int) = ($sym)(x,p,false) - ($sym)(x::Unsigned) = ($sym)(x,1,false) - ($sym)(x::Char, p::Int) = ($sym)(UInt32(x),p,false) - ($sym)(x::Char) = ($sym)(UInt32(x),1,false) - ($sym)(x::Integer, p::Int) = ($sym)(unsigned(abs(x)),p,x<0) - ($sym)(x::Integer) = ($sym)(unsigned(abs(x)),1,x<0) +function string(n::Integer; base::Integer = 10, pad::Integer = 1) + if base == 2 + (n_positive, neg) = split_sign(n) + bin(n_positive, pad, neg) + elseif base == 8 + (n_positive, neg) = split_sign(n) + oct(n_positive, pad, neg) + elseif base == 10 + (n_positive, neg) = split_sign(n) + dec(n_positive, pad, neg) + elseif base == 16 + (n_positive, neg) = split_sign(n) + hex(n_positive, pad, neg) + else + _base(Int(base), base > 0 ? unsigned(abs(n)) : convert(Signed, n), Int(pad), (base>0) & (n<0)) end end -""" - bin(n, pad::Int=1) - -Convert an integer to a binary string, optionally specifying a number of digits to pad to. - -```jldoctest -julia> bin(10,2) -"1010" - -julia> bin(10,8) -"00001010" -``` -""" -bin - -""" - hex(n, pad::Int=1) - -Convert an integer to a hexadecimal string, optionally specifying a number of -digits to pad to. - -```jldoctest -julia> hex(20) -"14" - -julia> hex(20, 3) -"014" -``` -""" -hex - -""" - oct(n, pad::Int=1) - -Convert an integer to an octal string, optionally specifying a number of digits -to pad to. - -```jldoctest -julia> oct(20) -"24" - -julia> oct(20, 3) -"024" -``` -""" -oct - -""" - dec(n, pad::Int=1) - -Convert an integer to a decimal string, optionally specifying a number of digits -to pad to. - -# Examples -```jldoctest -julia> dec(20) -"20" - -julia> dec(20, 3) -"020" -``` -""" -dec +string(b::Bool) = b ? "true" : "false" """ bitstring(n) @@ -749,11 +691,11 @@ julia> bitstring(2.2) """ function bitstring end -bitstring(x::Union{Bool,Int8,UInt8}) = bin(reinterpret(UInt8,x),8) -bitstring(x::Union{Int16,UInt16,Float16}) = bin(reinterpret(UInt16,x),16) -bitstring(x::Union{Char,Int32,UInt32,Float32}) = bin(reinterpret(UInt32,x),32) -bitstring(x::Union{Int64,UInt64,Float64}) = bin(reinterpret(UInt64,x),64) -bitstring(x::Union{Int128,UInt128}) = bin(reinterpret(UInt128,x),128) +bitstring(x::Union{Bool,Int8,UInt8}) = string(reinterpret(UInt8,x), pad = 8, base = 2) +bitstring(x::Union{Int16,UInt16,Float16}) = string(reinterpret(UInt16,x), pad = 16, base = 2) +bitstring(x::Union{Char,Int32,UInt32,Float32}) = string(reinterpret(UInt32,x), pad = 32, base = 2) +bitstring(x::Union{Int64,UInt64,Float64}) = string(reinterpret(UInt64,x), pad = 64, base = 2) +bitstring(x::Union{Int128,UInt128}) = string(reinterpret(UInt128,x), pad = 128, base = 2) """ digits([T<:Integer], n::Integer; base::T = 10, pad::Integer = 1) diff --git a/base/logging.jl b/base/logging.jl index 6bcb82cdf6156..976825ed646c3 100644 --- a/base/logging.jl +++ b/base/logging.jl @@ -237,7 +237,7 @@ function log_record_id(_module, level, message_ex) # as we increment h to resolve any collisions. h = hash(string(modname, level, message_ex)) % (1<<31) while true - id = Symbol(modname, '_', hex(h, 8)) + id = Symbol(modname, '_', string(h, base = 16, pad = 8)) # _log_record_ids is a registry of log record ids for use during # compilation, to ensure uniqueness of ids. Note that this state will # only persist during module compilation so it will be empty when a diff --git a/base/operators.jl b/base/operators.jl index 1ec7d76bad003..ff6e233d0f163 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -782,14 +782,11 @@ entered in the Julia REPL (and most editors, appropriately configured) by typing # Examples ```jldoctest -julia> map(uppercase∘hex, 250:255) -6-element Array{String,1}: - "FA" - "FB" - "FC" - "FD" - "FE" - "FF" +julia> map(uppercase∘first, ["apple", "banana", "carrot"]) +3-element Array{Char,1}: + 'A' + 'B' + 'C' ``` """ ∘(f, g) = (x...)->f(g(x...)) @@ -874,4 +871,4 @@ julia> map(splat(+), zip(1:3,4:6)) 9 ``` """ -splat(f) = args->f(args...) \ No newline at end of file +splat(f) = args->f(args...) diff --git a/base/printf.jl b/base/printf.jl index 223695889a757..9b62a635bdd4d 100644 --- a/base/printf.jl +++ b/base/printf.jl @@ -695,7 +695,7 @@ function gen_p(flags::String, width::Int, precision::Int, c::Char) end push!(blk.args, :(write(out, '0'))) push!(blk.args, :(write(out, 'x'))) - push!(blk.args, :(write(out, String(hex(unsigned($x), $ptrwidth))))) + push!(blk.args, :(write(out, String(string(unsigned($x), pad = $ptrwidth, base = 16))))) if width > 0 && '-' in flags push!(blk.args, pad(width, width, ' ')) end diff --git a/base/show.jl b/base/show.jl index 2208427a7ec58..5341d26e4d51e 100644 --- a/base/show.jl +++ b/base/show.jl @@ -341,7 +341,7 @@ function show_default(io::IO, @nospecialize(x)) GC.@preserve r begin p = unsafe_convert(Ptr{Cvoid}, r) for i in (nb - 1):-1:0 - print(io, hex(unsafe_load(convert(Ptr{UInt8}, p + i)), 2)) + print(io, string(unsafe_load(convert(Ptr{UInt8}, p + i)), base = 16, pad = 2)) end end end @@ -552,11 +552,11 @@ end show(io::IO, ::Nothing) = print(io, "nothing") show(io::IO, b::Bool) = print(io, b ? "true" : "false") -show(io::IO, n::Signed) = (write(io, dec(n)); nothing) -show(io::IO, n::Unsigned) = print(io, "0x", hex(n,sizeof(n)<<1)) -print(io::IO, n::Unsigned) = print(io, dec(n)) +show(io::IO, n::Signed) = (write(io, string(n)); nothing) +show(io::IO, n::Unsigned) = print(io, "0x", string(n, pad = sizeof(n)<<1, base = 16)) +print(io::IO, n::Unsigned) = print(io, string(n)) -show(io::IO, p::Ptr) = print(io, typeof(p), " @0x$(hex(UInt(p), Sys.WORD_SIZE>>2))") +show(io::IO, p::Ptr) = print(io, typeof(p), " @0x$(string(UInt(p), base = 16, pad = Sys.WORD_SIZE>>2))") has_tight_type(p::Pair) = typeof(p.first) == typeof(p).parameters[1] && diff --git a/base/stat.jl b/base/stat.jl index 945d8ef3d92dc..fc1e3c399c7f2 100644 --- a/base/stat.jl +++ b/base/stat.jl @@ -57,7 +57,7 @@ StatStruct(buf::Union{Vector{UInt8},Ptr{UInt8}}) = StatStruct( ccall(:jl_stat_ctime, Float64, (Ptr{UInt8},), buf), ) -show(io::IO, st::StatStruct) = print(io, "StatStruct(mode=0o$(oct(filemode(st),6)), size=$(filesize(st)))") +show(io::IO, st::StatStruct) = print(io, "StatStruct(mode=0o$(string(filemode(st), base = 8, pad = 6)), size=$(filesize(st)))") # stat & lstat functions diff --git a/base/strings/io.jl b/base/strings/io.jl index a2968fdaef19d..5601fd49c03d0 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -271,16 +271,16 @@ function escape_string(io, s::AbstractString, esc::AbstractString="") c in esc ? print(io, '\\', c) : '\a' <= c <= '\r' ? print(io, '\\', "abtnvfr"[Int(c)-6]) : isprint(c) ? print(io, c) : - print(io, "\\x", hex(c, 2)) + print(io, "\\x", string(UInt32(c), base = 16, pad = 2)) elseif !isoverlong(c) && !ismalformed(c) isprint(c) ? print(io, c) : - c <= '\x7f' ? print(io, "\\x", hex(c, 2)) : - c <= '\uffff' ? print(io, "\\u", hex(c, need_full_hex(peek(a)) ? 4 : 2)) : - print(io, "\\U", hex(c, need_full_hex(peek(a)) ? 8 : 4)) + c <= '\x7f' ? print(io, "\\x", string(UInt32(c), base = 16, pad = 2)) : + c <= '\uffff' ? print(io, "\\u", string(UInt32(c), base = 16, pad = need_full_hex(peek(a)) ? 4 : 2)) : + print(io, "\\U", string(UInt32(c), base = 16, pad = need_full_hex(peek(a)) ? 8 : 4)) else # malformed or overlong u = bswap(reinterpret(UInt32, c)) while true - print(io, "\\x", hex(u % UInt8, 2)) + print(io, "\\x", string(u % UInt8, base = 16, pad = 2)) (u >>= 8) == 0 && break end end diff --git a/base/strings/util.jl b/base/strings/util.jl index c20ed86fb7aee..397613e57f271 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -446,7 +446,7 @@ See also [`hex2bytes!`](@ref) for an in-place version, and [`bytes2hex`](@ref) f # Examples ```jldoctest -julia> s = hex(12345) +julia> s = string(12345, base = 16) "3039" julia> hex2bytes(s) @@ -512,7 +512,7 @@ Convert an array of bytes to its hexadecimal representation. All characters are in lower-case. # Examples ```jldoctest -julia> a = hex(12345) +julia> a = string(12345, base = 16) "3039" julia> b = hex2bytes(a) diff --git a/base/task.jl b/base/task.jl index 79da4c4e07959..9c89a78165c3a 100644 --- a/base/task.jl +++ b/base/task.jl @@ -51,7 +51,7 @@ function showerror(io::IO, ex::CompositeException) end function show(io::IO, t::Task) - print(io, "Task ($(t.state)) @0x$(hex(convert(UInt, pointer_from_objref(t)), Sys.WORD_SIZE>>2))") + print(io, "Task ($(t.state)) @0x$(string(convert(UInt, pointer_from_objref(t)), base = 16, pad = Sys.WORD_SIZE>>2))") end """ diff --git a/base/util.jl b/base/util.jl index 6eb83e6cb7f50..b8e4094cc9add 100644 --- a/base/util.jl +++ b/base/util.jl @@ -675,7 +675,7 @@ function runtests(tests = ["all"]; ncores = ceil(Int, Sys.CPU_CORES / 2), tests = split(tests) end exit_on_error && push!(tests, "--exit-on-error") - seed != nothing && push!(tests, "--seed=0x$(hex(seed % UInt128))") # cast to UInt128 to avoid a minus sign + seed != nothing && push!(tests, "--seed=0x$(string(seed % UInt128, base=16))") # cast to UInt128 to avoid a minus sign ENV2 = copy(ENV) ENV2["JULIA_CPU_CORES"] = "$ncores" try diff --git a/doc/src/base/numbers.md b/doc/src/base/numbers.md index 033590a69c0f6..deea1c2746ea1 100644 --- a/doc/src/base/numbers.md +++ b/doc/src/base/numbers.md @@ -41,11 +41,6 @@ Base.Irrational ## Data Formats ```@docs -Base.bin -Base.hex -Base.dec -Base.oct -Base.base Base.digits Base.digits! Base.bitstring diff --git a/doc/src/manual/unicode-input.md b/doc/src/manual/unicode-input.md index b95130160478c..e7dd6532a3c94 100644 --- a/doc/src/manual/unicode-input.md +++ b/doc/src/manual/unicode-input.md @@ -61,7 +61,7 @@ function table_entries(completions, unicode_dict) for (chars, inputs) in sort!(collect(completions), by = first) code_points, unicode_names, characters = String[], String[], String[] for char in chars - push!(code_points, "U+$(uppercase(hex(char, 5)))") + push!(code_points, "U+$(uppercase(string(UInt32(char), base = 16, pad = 5)))") push!(unicode_names, get(unicode_dict, UInt32(char), "(No Unicode name)")) push!(characters, isempty(characters) ? fix_combining_chars(char) : "$char") end diff --git a/stdlib/Dates/src/io.jl b/stdlib/Dates/src/io.jl index 0efef534b7510..ffcde456ddf49 100644 --- a/stdlib/Dates/src/io.jl +++ b/stdlib/Dates/src/io.jl @@ -131,7 +131,7 @@ end for (c, fn) in zip("YmdHMS", [year, month, day, hour, minute, second]) @eval function format(io, d::DatePart{$c}, dt) - write(io, dec($fn(dt), d.width)) + write(io, string($fn(dt), base = 10, pad = d.width)) end end @@ -153,7 +153,7 @@ end # the last n digits of y # will be 0 padded if y has less than n digits - str = dec(y, n) + str = string(y, base = 10, pad = n) l = lastindex(str) if l == n # fast path @@ -166,11 +166,11 @@ end function format(io, d::DatePart{'s'}, dt) ms = millisecond(dt) if ms % 100 == 0 - str = dec(div(ms, 100), 1) + str = string(div(ms, 100)) elseif ms % 10 == 0 - str = dec(div(ms, 10), 2) + str = string(div(ms, 10), pad = 2) else - str = dec(ms, 3) + str = string(ms, pad = 3) end write(io, rpad(str, d.width, '0')) diff --git a/stdlib/Distributed/src/cluster.jl b/stdlib/Distributed/src/cluster.jl index dd27fa6e62b8d..6b7545bed4f2a 100644 --- a/stdlib/Distributed/src/cluster.jl +++ b/stdlib/Distributed/src/cluster.jl @@ -206,7 +206,7 @@ function start_worker(out::IO, cookie::AbstractString=readline(stdin)) process_messages(client, client, true) end print(out, "julia_worker:") # print header - print(out, "$(dec(LPROC.bind_port))#") # print port + print(out, "$(string(LPROC.bind_port))#") # print port print(out, LPROC.bind_addr) print(out, '\n') flush(out) diff --git a/stdlib/LibGit2/src/blob.jl b/stdlib/LibGit2/src/blob.jl index d306ab96924bf..bbc69ef390bc9 100644 --- a/stdlib/LibGit2/src/blob.jl +++ b/stdlib/LibGit2/src/blob.jl @@ -56,7 +56,7 @@ Return the [`GitHash`](@ref) of the resulting blob. # Examples ```julia -hash_str = hex(commit_oid) +hash_str = string(commit_oid) blob_file = joinpath(repo_path, ".git", "objects", hash_str[1:2], hash_str[3:end]) id = LibGit2.addblob!(repo, blob_file) ``` diff --git a/stdlib/LibGit2/src/deprecated.jl b/stdlib/LibGit2/src/deprecated.jl index 5e92ffe733865..d5e880ec5af3d 100644 --- a/stdlib/LibGit2/src/deprecated.jl +++ b/stdlib/LibGit2/src/deprecated.jl @@ -58,4 +58,7 @@ end # PR #24594 @deprecate AbstractCredentials AbstractCredential false @deprecate UserPasswordCredentials UserPasswordCredential false -@deprecate SSHCredentials SSHCredential false \ No newline at end of file +@deprecate SSHCredentials SSHCredential false + +@deprecate hex(id::LibGit2.GitHash) string(id) +@deprecate hex(id::LibGit2.GitShortHash) string(id) diff --git a/stdlib/LibGit2/src/oid.jl b/stdlib/LibGit2/src/oid.jl index e54600adb25c3..904f845d1434f 100644 --- a/stdlib/LibGit2/src/oid.jl +++ b/stdlib/LibGit2/src/oid.jl @@ -157,9 +157,6 @@ function GitShortHash(obj::GitObject) return sid end -Base.hex(id::GitHash) = join([hex(i,2) for i in id.val]) -Base.hex(id::GitShortHash) = hex(id.hash)[1:id.len] - """ raw(id::GitHash) -> Vector{UInt8} @@ -167,7 +164,12 @@ Obtain the raw bytes of the [`GitHash`](@ref) as a vector of length $OID_RAWSZ. """ raw(id::GitHash) = collect(id.val) -Base.string(id::AbstractGitHash) = hex(id) +function Base.print(io::IO, id::GitHash) + for i in id.val + print(io, string(i, base = 16, pad = 2)) + end +end +Base.string(id::GitShortHash) = string(id.hash)[1:id.len] Base.show(io::IO, id::GitHash) = print(io, "GitHash(\"$(string(id))\")") Base.show(io::IO, id::GitShortHash) = print(io, "GitShortHash(\"$(string(id))\")") diff --git a/stdlib/LibGit2/src/types.jl b/stdlib/LibGit2/src/types.jl index 45981a7d5801d..46e5812da95e9 100644 --- a/stdlib/LibGit2/src/types.jl +++ b/stdlib/LibGit2/src/types.jl @@ -469,7 +469,7 @@ The fields represent: flags. The `i`th bit of this integer sets the `i`th flag. * `mode`: the [`stat`](@ref) mode for the item. * `id_abbrev`: only present in LibGit2 versions newer than or equal to `0.25.0`. - The length of the `id` field when converted using [`hex`](@ref). Usually equal to `OID_HEXSZ` ($OID_HEXSZ). + The length of the `id` field when converted using [`string`](@ref). Usually equal to `OID_HEXSZ` ($OID_HEXSZ). """ struct DiffFile id::GitHash diff --git a/stdlib/LibGit2/test/libgit2.jl b/stdlib/LibGit2/test/libgit2.jl index 4fda8e6dc5cfd..f12cb8cc4d027 100644 --- a/stdlib/LibGit2/test/libgit2.jl +++ b/stdlib/LibGit2/test/libgit2.jl @@ -778,7 +778,7 @@ mktempdir() do dir @test LibGit2.Consts.OBJECT(typeof(cmt)) == LibGit2.Consts.OBJ_COMMIT @test commit_oid1 == LibGit2.GitHash(cmt) short_oid1 = LibGit2.GitShortHash(string(commit_oid1)) - @test hex(commit_oid1) == hex(short_oid1) + @test string(commit_oid1) == string(short_oid1) @test cmp(commit_oid1, short_oid1) == 0 @test cmp(short_oid1, commit_oid1) == 0 @test !(short_oid1 < commit_oid1) @@ -787,7 +787,7 @@ mktempdir() do dir short_str = sprint(show, short_oid1) @test short_str == "GitShortHash(\"$(string(short_oid1))\")" short_oid2 = LibGit2.GitShortHash(cmt) - @test startswith(hex(commit_oid1), hex(short_oid2)) + @test startswith(string(commit_oid1), string(short_oid2)) LibGit2.with(LibGit2.GitCommit(repo, short_oid2)) do cmt2 @test commit_oid1 == LibGit2.GitHash(cmt2) @@ -985,7 +985,7 @@ mktempdir() do dir LibGit2.with(LibGit2.GitRepo(cache_repo)) do repo # this is slightly dubious, as it assumes the object has not been packed # could be replaced by another binary format - hash_string = hex(commit_oid1) + hash_string = string(commit_oid1) blob_file = joinpath(cache_repo,".git/objects", hash_string[1:2], hash_string[3:end]) id = LibGit2.addblob!(repo, blob_file) @@ -2764,4 +2764,4 @@ let cache = LibGit2.CachedCredentials() @test cache["foo"].pass == "\0\0\0" end -end # module \ No newline at end of file +end # module diff --git a/stdlib/Profile/src/Profile.jl b/stdlib/Profile/src/Profile.jl index 58287d4e4caa9..5b109d96d2105 100644 --- a/stdlib/Profile/src/Profile.jl +++ b/stdlib/Profile/src/Profile.jl @@ -489,7 +489,7 @@ function tree_format(lilist::Vector{StackFrame}, counts::Vector{Int}, level::Int rpad(string(counts[i]), ndigcounts, " "), " ", "unknown function (pointer: 0x", - hex(li.pointer,2*sizeof(Ptr{Cvoid})), + string(li.pointer, base = 16, pad = 2*sizeof(Ptr{Cvoid})), ")") else fname = string(li.func) diff --git a/stdlib/Random/src/DSFMT.jl b/stdlib/Random/src/DSFMT.jl index c9ab7d8ca25a2..28ff70fda8d62 100644 --- a/stdlib/Random/src/DSFMT.jl +++ b/stdlib/Random/src/DSFMT.jl @@ -106,7 +106,7 @@ struct GF2X end GF2X(s::AbstractString) = GF2X(parse(BigInt, reverse(s), base = 16)) -Base.string(f::GF2X) = reverse(base(16, f.z)) +Base.string(f::GF2X) = reverse(string(f.z, base = 16)) Base.:(==)(f::GF2X, g::GF2X) = f.z == g.z Base.copy(f::GF2X) = GF2X(MPZ.set(f.z)) diff --git a/stdlib/Serialization/src/Serialization.jl b/stdlib/Serialization/src/Serialization.jl index 42ec3cd38408b..6b2e423e9a8c6 100644 --- a/stdlib/Serialization/src/Serialization.jl +++ b/stdlib/Serialization/src/Serialization.jl @@ -307,7 +307,7 @@ end function serialize(s::AbstractSerializer, n::BigInt) serialize_type(s, BigInt) - serialize(s, base(62,n)) + serialize(s, string(n, base = 62)) end function serialize(s::AbstractSerializer, n::BigFloat) diff --git a/stdlib/Sockets/src/IPAddr.jl b/stdlib/Sockets/src/IPAddr.jl index 529956197dc1c..f024b1f94e7f3 100644 --- a/stdlib/Sockets/src/IPAddr.jl +++ b/stdlib/Sockets/src/IPAddr.jl @@ -44,10 +44,10 @@ end IPv4(str::AbstractString) = parse(IPv4, str) show(io::IO,ip::IPv4) = print(io,"ip\"",ip,"\"") -print(io::IO,ip::IPv4) = print(io,dec((ip.host&(0xFF000000))>>24),".", - dec((ip.host&(0xFF0000))>>16),".", - dec((ip.host&(0xFF00))>>8),".", - dec(ip.host&0xFF)) +print(io::IO,ip::IPv4) = print(io,string((ip.host&(0xFF000000))>>24),".", + string((ip.host&(0xFF0000))>>16),".", + string((ip.host&(0xFF00))>>8),".", + string(ip.host&0xFF)) struct IPv6 <: IPAddr host::UInt128 @@ -97,7 +97,7 @@ end IPv6(str::AbstractString) = parse(IPv6, str) # Suppress leading '0's and "0x" -print_ipv6_field(io,field::UInt16) = print(io,hex(field)) +print_ipv6_field(io,field::UInt16) = print(io,string(field, base = 16)) print_ipv6_field(io,ip,i) = print_ipv6_field(io,ipv6_field(ip,i)) function ipv6_field(ip::IPv6,i) diff --git a/test/bigint.jl b/test/bigint.jl index b4886df8220c2..c1372afea4f52 100644 --- a/test/bigint.jl +++ b/test/bigint.jl @@ -336,10 +336,10 @@ end @test_throws InexactError floor(BigInt,Inf) @test_throws InexactError ceil(BigInt,Inf) - @test bin(big(3)) == "11" - @test oct(big(9)) == "11" - @test oct(-big(9)) == "-11" - @test hex(big(12)) == "c" + @test string(big(3), base = 2) == "11" + @test string(big(9), base = 8) == "11" + @test string(-big(9), base = 8) == "-11" + @test string(big(12), base = 16) == "c" end @testset "Issue #18849" begin # bin, oct, dec, hex should not call sizeof on BigInts @@ -347,33 +347,33 @@ end padding = 4 low = big(4) high = big(2^20) - @test bin(low, padding) == "0100" - @test oct(low, padding) == "0004" - @test dec(low, padding) == "0004" - @test hex(low, padding) == "0004" - - @test bin(high, padding) == "100000000000000000000" - @test oct(high, padding) == "4000000" - @test dec(high, padding) == "1048576" - @test hex(high, padding) == "100000" - - @test bin(-low, padding) == "-0100" # handle negative numbers correctly - @test oct(-low, padding) == "-0004" - @test dec(-low, padding) == "-0004" - @test hex(-low, padding) == "-0004" - - @test bin(-high, padding) == "-100000000000000000000" - @test oct(-high, padding) == "-4000000" - @test dec(-high, padding) == "-1048576" - @test hex(-high, padding) == "-100000" + @test string(low, pad = padding, base = 2) == "0100" + @test string(low, pad = padding, base = 8) == "0004" + @test string(low, pad = padding, base = 10) == "0004" + @test string(low, pad = padding, base = 16) == "0004" + + @test string(high, pad = padding, base = 2) == "100000000000000000000" + @test string(high, pad = padding, base = 8) == "4000000" + @test string(high, pad = padding, base = 10) == "1048576" + @test string(high, pad = padding, base = 16) == "100000" + + @test string(-low, pad = padding, base = 2) == "-0100" # handle negative numbers correctly + @test string(-low, pad = padding, base = 8) == "-0004" + @test string(-low, pad = padding, base = 10) == "-0004" + @test string(-low, pad = padding, base = 16) == "-0004" + + @test string(-high, pad = padding, base = 2) == "-100000000000000000000" + @test string(-high, pad = padding, base = 8) == "-4000000" + @test string(-high, pad = padding, base = 10) == "-1048576" + @test string(-high, pad = padding, base = 16) == "-100000" end # respect 0-padding on big(0) -for f in (bin, oct, dec, hex) - local f - @test f(big(0), 0) == "" +for base in (2, 8, 10, 16) + local base + @test string(big(0), base=base, pad=0) == "" end -@test base(rand(2:62), big(0), 0) == "" +@test string(big(0), base = rand(2:62), pad = 0) == "" @test isqrt(big(4)) == 2 @test isqrt(big(5)) == 2 diff --git a/test/intfuncs.jl b/test/intfuncs.jl index dcf9653bbb380..484fd47c3cbad 100644 --- a/test/intfuncs.jl +++ b/test/intfuncs.jl @@ -142,23 +142,23 @@ end @test all(n -> n == 1, ndigits(x, b) for b in [-20:-2;2:20] for x in [true, false]) end @testset "bin/oct/dec/hex/bits" begin - @test bin('3') == "110011" - @test bin('3',7) == "0110011" - @test bin(3) == "11" - @test bin(3, 2) == "11" - @test bin(3, 3) == "011" - @test bin(-3) == "-11" - @test bin(-3, 3) == "-011" + @test string(UInt32('3'), base = 2) == "110011" + @test string(UInt32('3'), pad = 7, base = 2) == "0110011" + @test string(3, base = 2) == "11" + @test string(3, pad = 2, base = 2) == "11" + @test string(3, pad = 3, base = 2) == "011" + @test string(-3, base = 2) == "-11" + @test string(-3, pad = 3, base = 2) == "-011" - @test oct(9) == "11" - @test oct(-9) == "-11" + @test string(9, base = 8) == "11" + @test string(-9, base = 8) == "-11" - @test dec(121) == "121" + @test string(121, base = 10) == "121" - @test hex(12) == "c" - @test hex(-12, 3) == "-00c" + @test string(12, base = 16) == "c" + @test string(-12, pad = 3, base = 16) == "-00c" - @test base(2, 5, 7) == "0000101" + @test string(5, pad = 7, base = 2) == "0000101" @test bitstring(Int16(3)) == "0000000000000011" @test bitstring('3') == "00110011000000000000000000000000" @@ -177,7 +177,7 @@ end @test digits(T(-8163), base = -10) == [7, 7, 9, 9] end end - @test [base(b, n) + @test [string(n, base = b) for n = [-10^9, -10^5, -2^20, -2^10, -100, -83, -50, -34, -27, -16, -7, -3, -2, -1, 0, 1, 2, 3, 4, 7, 16, 27, 34, 50, 83, 100, 2^10, 2^20, 10^5, 10^9] for b = [-2, -3, -7, -10, -60]] == diff --git a/test/numbers.jl b/test/numbers.jl index ff87fa148ab50..fbff83d03c501 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -230,170 +230,170 @@ end @testset "bin/oct/dec/hex/base for extreme integers" begin # definition and printing of extreme integers - @test bin(typemin(UInt8)) == "0" - @test bin(typemax(UInt8)) == "1"^8 - @test oct(typemin(UInt8)) == "0" - @test oct(typemax(UInt8)) == "377" - @test dec(typemin(UInt8)) == "0" - @test dec(typemax(UInt8)) == "255" - @test hex(typemin(UInt8)) == "0" - @test hex(typemax(UInt8)) == "ff" + @test string(typemin(UInt8), base = 2) == "0" + @test string(typemax(UInt8), base = 2) == "1"^8 + @test string(typemin(UInt8), base = 8) == "0" + @test string(typemax(UInt8), base = 8) == "377" + @test string(typemin(UInt8), base = 10) == "0" + @test string(typemax(UInt8), base = 10) == "255" + @test string(typemin(UInt8), base = 16) == "0" + @test string(typemax(UInt8), base = 16) == "ff" @test repr(typemin(UInt8)) == "0x00" @test string(typemin(UInt8)) == "0" @test repr(typemax(UInt8)) == "0xff" @test string(typemax(UInt8)) == "255" - @test base(3,typemin(UInt8)) == "0" - @test base(3,typemax(UInt8)) == "100110" - @test base(12,typemin(UInt8)) == "0" - @test base(12,typemax(UInt8)) == "193" - - @test bin(typemin(UInt16)) == "0" - @test bin(typemax(UInt16)) == "1"^16 - @test oct(typemin(UInt16)) == "0" - @test oct(typemax(UInt16)) == "177777" - @test dec(typemin(UInt16)) == "0" - @test dec(typemax(UInt16)) == "65535" - @test hex(typemin(UInt16)) == "0" - @test hex(typemax(UInt16)) == "ffff" + @test string(typemin(UInt8), base = 3) == "0" + @test string(typemax(UInt8), base = 3) == "100110" + @test string(typemin(UInt8), base = 12) == "0" + @test string(typemax(UInt8), base = 12) == "193" + + @test string(typemin(UInt16), base = 2) == "0" + @test string(typemax(UInt16), base = 2) == "1"^16 + @test string(typemin(UInt16), base = 8) == "0" + @test string(typemax(UInt16), base = 8) == "177777" + @test string(typemin(UInt16), base = 10) == "0" + @test string(typemax(UInt16), base = 10) == "65535" + @test string(typemin(UInt16), base = 16) == "0" + @test string(typemax(UInt16), base = 16) == "ffff" @test repr(typemin(UInt16)) == "0x0000" @test string(typemin(UInt16)) == "0" @test repr(typemax(UInt16)) == "0xffff" @test string(typemax(UInt16)) == "65535" - @test base(3,typemin(UInt16)) == "0" - @test base(3,typemax(UInt16)) == "10022220020" - @test base(12,typemin(UInt16)) == "0" - @test base(12,typemax(UInt16)) == "31b13" - - @test bin(typemin(UInt32)) == "0" - @test bin(typemax(UInt32)) == "1"^32 - @test oct(typemin(UInt32)) == "0" - @test oct(typemax(UInt32)) == "37777777777" - @test dec(typemin(UInt32)) == "0" - @test dec(typemax(UInt32)) == "4294967295" - @test hex(typemin(UInt32)) == "0" - @test hex(typemax(UInt32)) == "ffffffff" + @test string(typemin(UInt16), base = 3) == "0" + @test string(typemax(UInt16), base = 3) == "10022220020" + @test string(typemin(UInt16), base = 12) == "0" + @test string(typemax(UInt16), base = 12) == "31b13" + + @test string(typemin(UInt32), base = 2) == "0" + @test string(typemax(UInt32), base = 2) == "1"^32 + @test string(typemin(UInt32), base = 8) == "0" + @test string(typemax(UInt32), base = 8) == "37777777777" + @test string(typemin(UInt32), base = 10) == "0" + @test string(typemax(UInt32), base = 10) == "4294967295" + @test string(typemin(UInt32), base = 16) == "0" + @test string(typemax(UInt32), base = 16) == "ffffffff" @test repr(typemin(UInt32)) == "0x00000000" @test string(typemin(UInt32)) == "0" @test repr(typemax(UInt32)) == "0xffffffff" @test string(typemax(UInt32)) == "4294967295" - @test base(3,typemin(UInt32)) == "0" - @test base(3,typemax(UInt32)) == "102002022201221111210" - @test base(12,typemin(UInt32)) == "0" - @test base(12,typemax(UInt32)) == "9ba461593" - - @test bin(typemin(UInt64)) == "0" - @test bin(typemax(UInt64)) == "1"^64 - @test oct(typemin(UInt64)) == "0" - @test oct(typemax(UInt64)) == "1777777777777777777777" - @test dec(typemin(UInt64)) == "0" - @test dec(typemax(UInt64)) == "18446744073709551615" - @test hex(typemin(UInt64)) == "0" - @test hex(typemax(UInt64)) == "ffffffffffffffff" + @test string(typemin(UInt32), base = 3) == "0" + @test string(typemax(UInt32), base = 3) == "102002022201221111210" + @test string(typemin(UInt32), base = 12) == "0" + @test string(typemax(UInt32), base = 12) == "9ba461593" + + @test string(typemin(UInt64), base = 2) == "0" + @test string(typemax(UInt64), base = 2) == "1"^64 + @test string(typemin(UInt64), base = 8) == "0" + @test string(typemax(UInt64), base = 8) == "1777777777777777777777" + @test string(typemin(UInt64), base = 10) == "0" + @test string(typemax(UInt64), base = 10) == "18446744073709551615" + @test string(typemin(UInt64), base = 16) == "0" + @test string(typemax(UInt64), base = 16) == "ffffffffffffffff" @test repr(typemin(UInt64)) == "0x0000000000000000" @test string(typemin(UInt64)) == "0" @test repr(typemax(UInt64)) == "0xffffffffffffffff" @test string(typemax(UInt64)) == "18446744073709551615" - @test base(3,typemin(UInt64)) == "0" - @test base(3,typemax(UInt64)) == "11112220022122120101211020120210210211220" - @test base(12,typemin(UInt64)) == "0" - @test base(12,typemax(UInt64)) == "839365134a2a240713" - - @test bin(typemin(UInt128)) == "0" - @test bin(typemax(UInt128)) == "1"^128 - @test oct(typemin(UInt128)) == "0" - @test oct(typemax(UInt128)) == "3777777777777777777777777777777777777777777" - @test hex(typemin(UInt128)) == "0" - @test hex(typemax(UInt128)) == "ffffffffffffffffffffffffffffffff" + @test string(typemin(UInt64), base = 3) == "0" + @test string(typemax(UInt64), base = 3) == "11112220022122120101211020120210210211220" + @test string(typemin(UInt64), base = 12) == "0" + @test string(typemax(UInt64), base = 12) == "839365134a2a240713" + + @test string(typemin(UInt128), base = 2) == "0" + @test string(typemax(UInt128), base = 2) == "1"^128 + @test string(typemin(UInt128), base = 8) == "0" + @test string(typemax(UInt128), base = 8) == "3777777777777777777777777777777777777777777" + @test string(typemin(UInt128), base = 16) == "0" + @test string(typemax(UInt128), base = 16) == "ffffffffffffffffffffffffffffffff" @test repr(typemin(UInt128)) == "0x00000000000000000000000000000000" @test string(typemin(UInt128)) == "0" @test repr(typemax(UInt128)) == "0xffffffffffffffffffffffffffffffff" @test string(typemax(UInt128)) == "340282366920938463463374607431768211455" - @test dec(typemin(UInt128)) == "0" - @test dec(typemax(UInt128)) == "340282366920938463463374607431768211455" - @test base(3,typemin(UInt128)) == "0" - @test base(3,typemax(UInt128)) == + @test string(typemin(UInt128), base = 10) == "0" + @test string(typemax(UInt128), base = 10) == "340282366920938463463374607431768211455" + @test string(typemin(UInt128), base = 3) == "0" + @test string(typemax(UInt128), base = 3) == "202201102121002021012000211012011021221022212021111001022110211020010021100121010" - @test base(12,typemin(UInt128)) == "0" - @test base(12,typemax(UInt128)) == "5916b64b41143526a777873841863a6a6993" - - @test bin(typemin(Int8)) == "-1"*"0"^7 - @test bin(typemax(Int8)) == "1"^7 - @test oct(typemin(Int8)) == "-200" - @test oct(typemax(Int8)) == "177" - @test dec(typemin(Int8)) == "-128" - @test dec(typemax(Int8)) == "127" - @test hex(typemin(Int8)) == "-80" - @test hex(typemax(Int8)) == "7f" + @test string(typemin(UInt128), base = 12) == "0" + @test string(typemax(UInt128), base = 12) == "5916b64b41143526a777873841863a6a6993" + + @test string(typemin(Int8), base = 2) == "-1"*"0"^7 + @test string(typemax(Int8), base = 2) == "1"^7 + @test string(typemin(Int8), base = 8) == "-200" + @test string(typemax(Int8), base = 8) == "177" + @test string(typemin(Int8), base = 10) == "-128" + @test string(typemax(Int8), base = 10) == "127" + @test string(typemin(Int8), base = 16) == "-80" + @test string(typemax(Int8), base = 16) == "7f" @test string(typemin(Int8)) == "-128" @test string(typemax(Int8)) == "127" - @test base(3,typemin(Int8)) == "-11202" - @test base(3,typemax(Int8)) == "11201" - @test base(12,typemin(Int8)) == "-a8" - @test base(12,typemax(Int8)) == "a7" - - @test bin(typemin(Int16)) == "-1"*"0"^15 - @test bin(typemax(Int16)) == "1"^15 - @test oct(typemin(Int16)) == "-100000" - @test oct(typemax(Int16)) == "77777" - @test dec(typemin(Int16)) == "-32768" - @test dec(typemax(Int16)) == "32767" - @test hex(typemin(Int16)) == "-8000" - @test hex(typemax(Int16)) == "7fff" + @test string(typemin(Int8), base = 3) == "-11202" + @test string(typemax(Int8), base = 3) == "11201" + @test string(typemin(Int8), base = 12) == "-a8" + @test string(typemax(Int8), base = 12) == "a7" + + @test string(typemin(Int16), base = 2) == "-1"*"0"^15 + @test string(typemax(Int16), base = 2) == "1"^15 + @test string(typemin(Int16), base = 8) == "-100000" + @test string(typemax(Int16), base = 8) == "77777" + @test string(typemin(Int16), base = 10) == "-32768" + @test string(typemax(Int16), base = 10) == "32767" + @test string(typemin(Int16), base = 16) == "-8000" + @test string(typemax(Int16), base = 16) == "7fff" @test string(typemin(Int16)) == "-32768" @test string(typemax(Int16)) == "32767" - @test base(3,typemin(Int16)) == "-1122221122" - @test base(3,typemax(Int16)) == "1122221121" - @test base(12,typemin(Int16)) == "-16b68" - @test base(12,typemax(Int16)) == "16b67" - - @test bin(typemin(Int32)) == "-1"*"0"^31 - @test bin(typemax(Int32)) == "1"^31 - @test oct(typemin(Int32)) == "-20000000000" - @test oct(typemax(Int32)) == "17777777777" - @test dec(typemin(Int32)) == "-2147483648" - @test dec(typemax(Int32)) == "2147483647" - @test hex(typemin(Int32)) == "-80000000" - @test hex(typemax(Int32)) == "7fffffff" + @test string(typemin(Int16), base = 3) == "-1122221122" + @test string(typemax(Int16), base = 3) == "1122221121" + @test string(typemin(Int16), base = 12) == "-16b68" + @test string(typemax(Int16), base = 12) == "16b67" + + @test string(typemin(Int32), base = 2) == "-1"*"0"^31 + @test string(typemax(Int32), base = 2) == "1"^31 + @test string(typemin(Int32), base = 8) == "-20000000000" + @test string(typemax(Int32), base = 8) == "17777777777" + @test string(typemin(Int32), base = 10) == "-2147483648" + @test string(typemax(Int32), base = 10) == "2147483647" + @test string(typemin(Int32), base = 16) == "-80000000" + @test string(typemax(Int32), base = 16) == "7fffffff" @test string(typemin(Int32)) == "-2147483648" @test string(typemax(Int32)) == "2147483647" - @test base(3,typemin(Int32)) == "-12112122212110202102" - @test base(3,typemax(Int32)) == "12112122212110202101" - @test base(12,typemin(Int32)) == "-4bb2308a8" - @test base(12,typemax(Int32)) == "4bb2308a7" - - @test bin(typemin(Int64)) == "-1"*"0"^63 - @test bin(typemax(Int64)) == "1"^63 - @test oct(typemin(Int64)) == "-1000000000000000000000" - @test oct(typemax(Int64)) == "777777777777777777777" - @test dec(typemin(Int64)) == "-9223372036854775808" - @test dec(typemax(Int64)) == "9223372036854775807" - @test hex(typemin(Int64)) == "-8000000000000000" - @test hex(typemax(Int64)) == "7fffffffffffffff" + @test string(typemin(Int32), base = 3) == "-12112122212110202102" + @test string(typemax(Int32), base = 3) == "12112122212110202101" + @test string(typemin(Int32), base = 12) == "-4bb2308a8" + @test string(typemax(Int32), base = 12) == "4bb2308a7" + + @test string(typemin(Int64), base = 2) == "-1"*"0"^63 + @test string(typemax(Int64), base = 2) == "1"^63 + @test string(typemin(Int64), base = 8) == "-1000000000000000000000" + @test string(typemax(Int64), base = 8) == "777777777777777777777" + @test string(typemin(Int64), base = 10) == "-9223372036854775808" + @test string(typemax(Int64), base = 10) == "9223372036854775807" + @test string(typemin(Int64), base = 16) == "-8000000000000000" + @test string(typemax(Int64), base = 16) == "7fffffffffffffff" @test string(typemin(Int64)) == "-9223372036854775808" @test string(typemax(Int64)) == "9223372036854775807" - @test base(3,typemin(Int64)) == "-2021110011022210012102010021220101220222" - @test base(3,typemax(Int64)) == "2021110011022210012102010021220101220221" - @test base(12,typemin(Int64)) == "-41a792678515120368" - @test base(12,typemax(Int64)) == "41a792678515120367" - - @test bin(typemin(Int128)) == "-1"*"0"^127 - @test bin(typemax(Int128)) == "1"^127 - @test oct(typemin(Int128)) == "-2000000000000000000000000000000000000000000" - @test oct(typemax(Int128)) == "1777777777777777777777777777777777777777777" - @test hex(typemin(Int128)) == "-80000000000000000000000000000000" - @test hex(typemax(Int128)) == "7fffffffffffffffffffffffffffffff" - - @test dec(typemin(Int128)) == "-170141183460469231731687303715884105728" - @test dec(typemax(Int128)) == "170141183460469231731687303715884105727" + @test string(typemin(Int64), base = 3) == "-2021110011022210012102010021220101220222" + @test string(typemax(Int64), base = 3) == "2021110011022210012102010021220101220221" + @test string(typemin(Int64), base = 12) == "-41a792678515120368" + @test string(typemax(Int64), base = 12) == "41a792678515120367" + + @test string(typemin(Int128), base = 2) == "-1"*"0"^127 + @test string(typemax(Int128), base = 2) == "1"^127 + @test string(typemin(Int128), base = 8) == "-2000000000000000000000000000000000000000000" + @test string(typemax(Int128), base = 8) == "1777777777777777777777777777777777777777777" + @test string(typemin(Int128), base = 16) == "-80000000000000000000000000000000" + @test string(typemax(Int128), base = 16) == "7fffffffffffffffffffffffffffffff" + + @test string(typemin(Int128), base = 10) == "-170141183460469231731687303715884105728" + @test string(typemax(Int128), base = 10) == "170141183460469231731687303715884105727" @test string(typemin(Int128)) == "-170141183460469231731687303715884105728" @test string(typemax(Int128)) == "170141183460469231731687303715884105727" - @test base(3,typemin(Int128)) == + @test string(typemin(Int128), base = 3) == "-101100201022001010121000102002120122110122221010202000122201220121120010200022002" - @test base(3,typemax(Int128)) == + @test string(typemax(Int128), base = 3) == "101100201022001010121000102002120122110122221010202000122201220121120010200022001" - @test base(12,typemin(Int128)) == "-2a695925806818735399a37a20a31b3534a8" - @test base(12,typemax(Int128)) == "2a695925806818735399a37a20a31b3534a7" + @test string(typemin(Int128), base = 12) == "-2a695925806818735399a37a20a31b3534a8" + @test string(typemax(Int128), base = 12) == "2a695925806818735399a37a20a31b3534a7" end @testset "floating-point printing" begin @test repr(1.0) == "1.0" @@ -1778,7 +1778,7 @@ end @test isinf(nextfloat(0x1.fffffffffffffp1023)) end @testset "issue #1308" begin - @test hex(~UInt128(0)) == "f"^32 + @test string(~UInt128(0), base = 16) == "f"^32 @test (~0)%UInt128 == ~UInt128(0) @test Int128(~0) == ~Int128(0) end diff --git a/test/operators.jl b/test/operators.jl index 5161a2977c69a..7cf493296e00b 100644 --- a/test/operators.jl +++ b/test/operators.jl @@ -101,7 +101,7 @@ Base.promote_rule(::Type{T19714}, ::Type{Int}) = T19714 # pr #17155 @testset "function composition" begin - @test (uppercase∘hex)(239487) == "3A77F" + @test (uppercase∘(x->string(x,base=16)))(239487) == "3A77F" end @testset "function negation" begin str = randstring(20) diff --git a/test/perf/micro/perf.jl b/test/perf/micro/perf.jl index 93ef57e124a75..2c10b22eaba63 100644 --- a/test/perf/micro/perf.jl +++ b/test/perf/micro/perf.jl @@ -20,7 +20,7 @@ function parseintperf(t) local n, m for i=1:t n = rand(UInt32) - s = hex(n) + s = string(n, base = 16) m = UInt32(parse(Int64,s, base = 16)) end @test m == n diff --git a/test/perf/micro/perf.py b/test/perf/micro/perf.py index 843da237e31d0..18d1edd0fd264 100644 --- a/test/perf/micro/perf.py +++ b/test/perf/micro/perf.py @@ -95,7 +95,7 @@ def pisum(): def parse_int(t): for i in range(1,t): n = random.randint(0,2**32-1) - s = hex(n) + s = string(n, base = 16) if s[-1]=='L': s = s[0:-1] m = int(s,16) @@ -107,7 +107,7 @@ def printfd(t): for i in range(1,t): f.write("{:d} {:d}\n".format(i, i+1)) f.close() - + def print_perf(name, time): print("python," + name + "," + str(time*1000)) diff --git a/test/runtests.jl b/test/runtests.jl index e1a36c521a26c..f4630e82b80b2 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -287,7 +287,7 @@ cd(dirname(@__FILE__)) do println(" \033[31;1mFAILURE\033[0m\n") skipped > 0 && println("$skipped test", skipped > 1 ? "s were" : " was", " skipped due to failure.") - println("The global RNG seed was 0x$(hex(seed)).\n") + println("The global RNG seed was 0x$(string(seed, base = 16)).\n") Test.print_test_errors(o_ts) throw(Test.FallbackTestSetException("Test run finished with errors")) end diff --git a/test/strings/basic.jl b/test/strings/basic.jl index 92273526fa442..a63d618c2633c 100644 --- a/test/strings/basic.jl +++ b/test/strings/basic.jl @@ -66,7 +66,7 @@ end b = 2:62, _ = 1:10 n = (T != BigInt) ? rand(T) : BigInt(rand(Int128)) - @test parse(T, base(b, n), base = b) == n + @test parse(T, string(n, base = b), base = b) == n end end end diff --git a/test/strings/io.jl b/test/strings/io.jl index 28f7d9bdf5e4b..cb928f65f001c 100644 --- a/test/strings/io.jl +++ b/test/strings/io.jl @@ -80,15 +80,15 @@ "\uFFFF","\U10000","\U10FFF","\U10FFFF"] c = Char(i) cp = string(c,p) - op = string(Char(div(i,8)), oct(i%8), p) - hp = string(Char(div(i,16)), hex(i%16), p) - @test string(unescape_string(string("\\",oct(i,1),p))) == cp - @test string(unescape_string(string("\\",oct(i,2),p))) == cp - @test string(unescape_string(string("\\",oct(i,3),p))) == cp - @test string(unescape_string(string("\\",oct(i,4),p))) == op - @test string(unescape_string(string("\\x",hex(i,1),p))) == cp - @test string(unescape_string(string("\\x",hex(i,2),p))) == cp - @test string(unescape_string(string("\\x",hex(i,3),p))) == hp + op = string(Char(div(i,8)), string(i%8, base = 8), p) + hp = string(Char(div(i,16)), string(i%16, base = 16), p) + @test string(unescape_string(string("\\",string(i,base=8,pad=1),p))) == cp + @test string(unescape_string(string("\\",string(i,base=8,pad=2),p))) == cp + @test string(unescape_string(string("\\",string(i,base=8,pad=3),p))) == cp + @test string(unescape_string(string("\\",string(i,base=8,pad=4),p))) == op + @test string(unescape_string(string("\\x",string(i,base=16,pad=1),p))) == cp + @test string(unescape_string(string("\\x",string(i,base=16,pad=2),p))) == cp + @test string(unescape_string(string("\\x",string(i,base=16,pad=3),p))) == hp end @testset "unescape_string" begin From d1aa8f72a9df140e6df706b3236ee918e1230682 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Fri, 2 Mar 2018 01:18:35 -0500 Subject: [PATCH 11/28] Use lowered form in logging macro (#26291) Macro hygiene sees pre-lowered forms, and as a result does not apply to syntactic forms like []. Use an explicit `getindex` to get the proper hygiene behavior. Fixes #26273 --- base/logging.jl | 2 +- test/logging.jl | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/base/logging.jl b/base/logging.jl index 976825ed646c3..9d9b60acfa1d3 100644 --- a/base/logging.jl +++ b/base/logging.jl @@ -297,7 +297,7 @@ function logmsg_code(_module, file, line, level, message, exs...) quote level = $level std_level = convert(LogLevel, level) - if std_level >= _min_enabled_level[] + if std_level >= getindex(_min_enabled_level) logstate = current_logstate() if std_level >= logstate.min_enabled_level logger = logstate.logger diff --git a/test/logging.jl b/test/logging.jl index ebd28572a5683..88ebb8f0c226f 100644 --- a/test/logging.jl +++ b/test/logging.jl @@ -267,4 +267,12 @@ end """ end +# Issue #26273 +let m = Module(:Bare26273i, false) + eval(m, :(import Base: @error)) + @test_logs (:error, "Hello") eval(m, quote + @error "Hello" + end) +end + end From df489f0b88229cd6c5cb4b15b2c5c587ff93a5d3 Mon Sep 17 00:00:00 2001 From: Jacob Quinn Date: Fri, 2 Mar 2018 00:22:25 -0700 Subject: [PATCH 12/28] Add adjoint(::Missing) method (#25502) --- base/missing.jl | 6 +++--- test/missing.jl | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/base/missing.jl b/base/missing.jl index 3c4b3760d623b..563770999ed96 100644 --- a/base/missing.jl +++ b/base/missing.jl @@ -68,11 +68,11 @@ for f in (:(!), :(~), :(+), :(-), :(identity), :(zero), :(one), :(oneunit), :(acos), :(acosh), :(asin), :(asinh), :(atan), :(atanh), :(sin), :(sinh), :(cos), :(cosh), :(tan), :(tanh), :(exp), :(exp2), :(expm1), :(log), :(log10), :(log1p), - :(log2), :(exponent), :(sqrt), :(gamma), :(lgamma), + :(log2), :(Math.exponent), :(sqrt), :(Math.gamma), :(Math.lgamma), :(iseven), :(ispow2), :(isfinite), :(isinf), :(isodd), :(isinteger), :(isreal), :(isnan), :(isempty), - :(iszero), :(transpose), :(float)) - @eval Math.$(f)(::Missing) = missing + :(iszero), :(transpose), :(adjoint), :(float)) + @eval $(f)(::Missing) = missing end for f in (:(Base.zero), :(Base.one), :(Base.oneunit)) diff --git a/test/missing.jl b/test/missing.jl index d1b13fc5922a5..2b6e3ee6a725c 100644 --- a/test/missing.jl +++ b/test/missing.jl @@ -150,7 +150,7 @@ Base.one(::Type{Unit}) = 1 identity, zero, one, oneunit, iseven, isodd, ispow2, isfinite, isinf, isnan, iszero, - isinteger, isreal, isempty, transpose, float] + isinteger, isreal, isempty, transpose, adjoint, float] # All elementary functions return missing when evaluating missing for f in elementary_functions @@ -218,6 +218,7 @@ end x = convert(Vector{Union{Int, Missing}}, [missing]) @test isa(x, Vector{Union{Int, Missing}}) @test isequal(x, [missing]) + @test eltype(adjoint([1, missing])) == Union{Int, Missing} end @testset "== and != on arrays" begin From d1f26785f2da38fd7897f6504b298748d2725772 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 2 Mar 2018 12:11:40 -0500 Subject: [PATCH 13/28] fix #25857, `typeinfo` problem in showing arrays with abstract tuple types (#26289) --- base/show.jl | 2 +- test/show.jl | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/base/show.jl b/base/show.jl index 5341d26e4d51e..f8f83b7d9f25e 100644 --- a/base/show.jl +++ b/base/show.jl @@ -685,7 +685,7 @@ function show_delim_array(io::IO, itr, op, delim, cl, delim_one, i1=1, n=typemax while true x, state = next(itr, state) show(IOContext(recur_io, :typeinfo => - typeinfo <: Tuple ? typeinfo.parameters[i1+i0] : typeinfo), + typeinfo <: Tuple ? fieldtype(typeinfo, i1+i0) : typeinfo), x) i1 += 1 if done(itr, state) || i1 > n diff --git a/test/show.jl b/test/show.jl index ab0b971b1381c..0ffda8661e1e7 100644 --- a/test/show.jl +++ b/test/show.jl @@ -1130,6 +1130,9 @@ end # Issue #25038 A = [0.0, 1.0] @test replstr(view(A, [1], :)) == "1×1 view(::Array{Float64,2}, [1], :) with eltype Float64:\n 0.0" + + # issue #25857 + @test repr([(1,),(1,2),(1,2,3)]) == "Tuple{$Int,Vararg{$Int,N} where N}[(1,), (1, 2), (1, 2, 3)]" end @testset "#14684: `display` should print associative types in full" begin From 275b105eadbc7bac258ff33bc0f524362d41aeb0 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 2 Mar 2018 12:13:17 -0500 Subject: [PATCH 14/28] fix #26267, regression in `names` with `imported=false` (#26293) --- src/module.c | 2 +- src/toplevel.c | 13 +++++++++++-- test/reflection.jl | 9 +++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/module.c b/src/module.c index 4f21408fa7626..ea62a300ce56b 100644 --- a/src/module.c +++ b/src/module.c @@ -648,7 +648,7 @@ JL_DLLEXPORT jl_value_t *jl_module_names(jl_module_t *m, int all, int imported) int hidden = jl_symbol_name(b->name)[0]=='#'; if ((b->exportp || (imported && b->imported) || - ((b->owner == m) && (all || m == jl_main_module))) && + (b->owner == m && !b->imported && (all || m == jl_main_module))) && (all || (!b->deprecated && !hidden))) { jl_array_grow_end(a, 1); //XXX: change to jl_arrayset if array storage allocation for Array{Symbols,1} changes: diff --git a/src/toplevel.c b/src/toplevel.c index f718d2df401fd..c3279117dacbe 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -516,14 +516,23 @@ static jl_method_instance_t *method_instance_for_thunk(jl_code_info_t *src, jl_m static void import_module(jl_module_t *m, jl_module_t *import) { jl_sym_t *name = import->name; + jl_binding_t *b; if (jl_binding_resolved_p(m, name)) { - jl_binding_t *b = jl_get_binding(m, name); + b = jl_get_binding(m, name); if (b->owner != m || (b->value && b->value != (jl_value_t*)import)) { jl_errorf("importing %s into %s conflicts with an existing identifier", jl_symbol_name(name), jl_symbol_name(m->name)); } } - jl_set_const(m, name, (jl_value_t*)import); + else { + b = jl_get_binding_wr(m, name, 1); + b->imported = 1; + } + if (!b->constp) { + b->value = (jl_value_t*)import; + b->constp = 1; + jl_gc_wb(m, (jl_value_t*)import); + } } // replace Base.X with top-level X diff --git a/test/reflection.jl b/test/reflection.jl index 38efa48b72f57..dbb544b2e8ac1 100644 --- a/test/reflection.jl +++ b/test/reflection.jl @@ -738,3 +738,12 @@ typeparam(::Type{T}, a::AbstractArray{T}) where T = 2 @test typeparam(Int, rand(Int, 2)) == 2 end + +# issue #26267 +module M26267 +import Test +foo(x) = x +end +@test !(:Test in names(M26267, all=true, imported=false)) +@test :Test in names(M26267, all=true, imported=true) +@test :Test in names(M26267, all=false, imported=true) From ade40f612c73dbd897cbae07a20d8e6dae5d33b5 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Fri, 2 Mar 2018 19:22:08 +0000 Subject: [PATCH 15/28] Deprecate conj(::Any), add real(::Missing) and imag(::Missing) (#26288) --- base/deprecated.jl | 3 +++ base/missing.jl | 4 ++-- base/operators.jl | 2 -- stdlib/LinearAlgebra/test/generic.jl | 1 + test/missing.jl | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 7196f1f4bddbe..1ca11b14bf637 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1488,6 +1488,9 @@ function assert(x) @assert x "" end +# Issue #26248 +@deprecate conj(x) x + # END 0.7 deprecations # BEGIN 1.0 deprecations diff --git a/base/missing.jl b/base/missing.jl index 563770999ed96..7ca2c9373bbf1 100644 --- a/base/missing.jl +++ b/base/missing.jl @@ -64,14 +64,14 @@ isless(::Any, ::Missing) = true # Unary operators/functions for f in (:(!), :(~), :(+), :(-), :(identity), :(zero), :(one), :(oneunit), - :(abs), :(abs2), :(sign), + :(abs), :(abs2), :(sign), :(real), :(imag), :(acos), :(acosh), :(asin), :(asinh), :(atan), :(atanh), :(sin), :(sinh), :(cos), :(cosh), :(tan), :(tanh), :(exp), :(exp2), :(expm1), :(log), :(log10), :(log1p), :(log2), :(Math.exponent), :(sqrt), :(Math.gamma), :(Math.lgamma), :(iseven), :(ispow2), :(isfinite), :(isinf), :(isodd), :(isinteger), :(isreal), :(isnan), :(isempty), - :(iszero), :(transpose), :(adjoint), :(float)) + :(iszero), :(transpose), :(adjoint), :(float), :(conj)) @eval $(f)(::Missing) = missing end diff --git a/base/operators.jl b/base/operators.jl index ff6e233d0f163..d5e052a2dc76d 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -733,8 +733,6 @@ See also: [`fld1`](@ref), [`mod1`](@ref). """ fldmod1(x, y) = (fld1(x, y), mod1(x, y)) -conj(x) = x - """ widen(x) diff --git a/stdlib/LinearAlgebra/test/generic.jl b/stdlib/LinearAlgebra/test/generic.jl index 00a560af9be51..cd44f36a96ab4 100644 --- a/stdlib/LinearAlgebra/test/generic.jl +++ b/stdlib/LinearAlgebra/test/generic.jl @@ -335,6 +335,7 @@ Base.zero(::Type{ModInt{n}}) where {n} = ModInt{n}(0) Base.zero(::ModInt{n}) where {n} = ModInt{n}(0) Base.one(::Type{ModInt{n}}) where {n} = ModInt{n}(1) Base.one(::ModInt{n}) where {n} = ModInt{n}(1) +Base.conj(a::ModInt{n}) where {n} = a Base.adjoint(a::ModInt{n}) where {n} = ModInt{n}(conj(a)) Base.transpose(a::ModInt{n}) where {n} = a # see Issue 20978 LinearAlgebra.Adjoint(a::ModInt{n}) where {n} = adjoint(a) diff --git a/test/missing.jl b/test/missing.jl index 2b6e3ee6a725c..4302ffe47d6b5 100644 --- a/test/missing.jl +++ b/test/missing.jl @@ -142,7 +142,7 @@ Base.zero(::Type{Unit}) = Unit(0) Base.one(::Type{Unit}) = 1 @testset "elementary functions" begin - elementary_functions = [abs, abs2, sign, + elementary_functions = [abs, abs2, sign, real, imag, acos, acosh, asin, asinh, atan, atanh, sin, sinh, conj, cos, cosh, tan, tanh, exp, exp2, expm1, log, log10, log1p, log2, From 8fff818005fe956f969da7247f435c897adf200d Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Fri, 2 Mar 2018 13:24:36 -0600 Subject: [PATCH 16/28] Deprecate adding integers to CartesianIndex (#26284) fixes #26227 --- NEWS.md | 3 +++ base/deprecated.jl | 6 ++++++ base/multidimensional.jl | 6 +----- test/arrayops.jl | 4 ++-- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/NEWS.md b/NEWS.md index 17332744894b1..190a456e62bb3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -587,6 +587,9 @@ Library improvements collection `A`. There are also two other methods with a different API, and a mutating variant, `replace!` ([#22324]). + * Adding integers to `CartesianIndex` objects is now deprecated. Instead of + `i::Int + x::CartesianIndex`, use `i*one(x) + x` ([#26284]). + * `CartesianRange` changes ([#24715]): - Inherits from `AbstractArray`, and linear indexing can be used to provide linear-to-cartesian conversion ([#24715]) diff --git a/base/deprecated.jl b/base/deprecated.jl index 1ca11b14bf637..9f90cf11e1858 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1422,6 +1422,12 @@ end @deprecate reprmime(mime, x) repr(mime, x) @deprecate mimewritable(mime, x) showable(mime, x) +# PR #26284 +@deprecate (+)(i::Integer, index::CartesianIndex) (i*one(index) + index) +@deprecate (+)(index::CartesianIndex, i::Integer) (index + i*one(index)) +@deprecate (-)(i::Integer, index::CartesianIndex) (i*one(index) - index) +@deprecate (-)(index::CartesianIndex, i::Integer) (index - i*one(index)) + # PR #23332 @deprecate ^(x, p::Integer) Base.power_by_squaring(x,p) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index d88794cd46798..66c3e255adf48 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -112,10 +112,6 @@ module IteratorsMD @inline max(index1::CartesianIndex{N}, index2::CartesianIndex{N}) where {N} = CartesianIndex{N}(map(max, index1.I, index2.I)) - @inline (+)(i::Integer, index::CartesianIndex) = index+i - @inline (+)(index::CartesianIndex{N}, i::Integer) where {N} = CartesianIndex{N}(map(x->x+i, index.I)) - @inline (-)(index::CartesianIndex{N}, i::Integer) where {N} = CartesianIndex{N}(map(x->x-i, index.I)) - @inline (-)(i::Integer, index::CartesianIndex{N}) where {N} = CartesianIndex{N}(map(x->i-x, index.I)) @inline (*)(a::Integer, index::CartesianIndex{N}) where {N} = CartesianIndex{N}(map(x->a*x, index.I)) @inline (*)(index::CartesianIndex, a::Integer) = *(a,index) @@ -279,7 +275,7 @@ module IteratorsMD @inline function start(iter::CartesianIndices) iterfirst, iterlast = first(iter), last(iter) if any(map(>, iterfirst.I, iterlast.I)) - return iterlast+1 + return iterlast+one(iterlast) end iterfirst end diff --git a/test/arrayops.jl b/test/arrayops.jl index 570c1510592b3..fde0b3f7d4fac 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -1616,8 +1616,8 @@ end @test I2 + I1 == CartesianIndex((1,8,2)) @test I1 - I2 == CartesianIndex((3,-2,-2)) @test I2 - I1 == CartesianIndex((-3,2,2)) - @test I1 + 1 == CartesianIndex((3,4,1)) - @test I1 - 2 == CartesianIndex((0,1,-2)) + @test I1 + 1*one(I1) == CartesianIndex((3,4,1)) + @test I1 - 2*one(I1) == CartesianIndex((0,1,-2)) @test zero(CartesianIndex{2}) == CartesianIndex((0,0)) @test zero(CartesianIndex((2,3))) == CartesianIndex((0,0)) From ce26ed0c132720bd30b4c1551c009c4a507a9276 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 2 Mar 2018 16:53:54 -0500 Subject: [PATCH 17/28] remove references to `TCPSocket` in Base docstrings (#26298) --- base/stream.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/base/stream.jl b/base/stream.jl index 789297918b7e7..84d36f9606e4a 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -951,7 +951,7 @@ the pipe. The `wr` end is given for convenience in case the old elsewhere. !!! note - `stream` must be a `TTY`, a `Pipe`, or a [`TCPSocket`](@ref). + `stream` must be a `TTY`, a `Pipe`, or a socket. """ redirect_stdout @@ -961,7 +961,7 @@ redirect_stdout Like [`redirect_stdout`](@ref), but for [`stderr`](@ref). !!! note - `stream` must be a `TTY`, a `Pipe`, or a [`TCPSocket`](@ref). + `stream` must be a `TTY`, a `Pipe`, or a socket. """ redirect_stderr @@ -973,7 +973,7 @@ Note that the order of the return tuple is still `(rd, wr)`, i.e. data to be read from [`stdin`](@ref) may be written to `wr`. !!! note - `stream` must be a `TTY`, a `Pipe`, or a [`TCPSocket`](@ref). + `stream` must be a `TTY`, a `Pipe`, or a socket. """ redirect_stdin @@ -998,7 +998,7 @@ Run the function `f` while redirecting [`stdout`](@ref) to `stream`. Upon completion, [`stdout`](@ref) is restored to its prior setting. !!! note - `stream` must be a `TTY`, a `Pipe`, or a [`TCPSocket`](@ref). + `stream` must be a `TTY`, a `Pipe`, or a socket. """ redirect_stdout(f::Function, stream) @@ -1009,7 +1009,7 @@ Run the function `f` while redirecting [`stderr`](@ref) to `stream`. Upon completion, [`stderr`](@ref) is restored to its prior setting. !!! note - `stream` must be a `TTY`, a `Pipe`, or a [`TCPSocket`](@ref). + `stream` must be a `TTY`, a `Pipe`, or a socket. """ redirect_stderr(f::Function, stream) @@ -1020,7 +1020,7 @@ Run the function `f` while redirecting [`stdin`](@ref) to `stream`. Upon completion, [`stdin`](@ref) is restored to its prior setting. !!! note - `stream` must be a `TTY`, a `Pipe`, or a [`TCPSocket`](@ref). + `stream` must be a `TTY`, a `Pipe`, or a socket. """ redirect_stdin(f::Function, stream) From 05ff71f187aa06e51f1eceb1c85cf439d09c790a Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Fri, 2 Mar 2018 20:29:37 -0500 Subject: [PATCH 18/28] performance tweak in reverse(::String) (#26300) No reason not to pass a `sizehint` in this function since we know the exact number of bytes required. --- base/strings/substring.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/strings/substring.jl b/base/strings/substring.jl index 879955daeba48..631d191dd678b 100644 --- a/base/strings/substring.jl +++ b/base/strings/substring.jl @@ -130,7 +130,7 @@ julia> join(reverse(collect(graphemes("ax̂e")))) # reverses graphemes ``` """ function reverse(s::Union{String,SubString{String}})::String - sprint() do io + sprint(sizehint=sizeof(s)) do io i, j = firstindex(s), lastindex(s) while i ≤ j c, j = s[j], prevind(s, j) From 8dc4fc13a65ede21b7a31456a27d4af4a006fa2a Mon Sep 17 00:00:00 2001 From: Don MacMillen Date: Sat, 3 Mar 2018 08:59:47 -0800 Subject: [PATCH 19/28] Slight update to doc string for at-enum to refer to instances (#26208) * Slight update to doc string for at-enum to refer to instances --- base/Enums.jl | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/base/Enums.jl b/base/Enums.jl index 3e20f055fe175..bf356c9490315 100644 --- a/base/Enums.jl +++ b/base/Enums.jl @@ -36,7 +36,7 @@ Create an `Enum{BaseType}` subtype with name `EnumName` and enum member values o `EnumName` can be used just like other types and enum member values as regular values, such as # Examples -```jldoctest +```jldoctest fruitenum julia> @enum Fruit apple=1 orange=2 kiwi=3 julia> f(x::Fruit) = "I'm a Fruit with value: \$(Int(x))" @@ -58,6 +58,13 @@ end `BaseType`, which defaults to [`Int32`](@ref), must be a primitive subtype of `Integer`. Member values can be converted between the enum type and `BaseType`. `read` and `write` perform these conversions automatically. + +To list all the instances of an enum use `instances`, e.g. + +```jldoctest fruitenum +julia> instances(Fruit) +(apple::Fruit = 1, orange::Fruit = 2, kiwi::Fruit = 3) +``` """ macro enum(T, syms...) if isempty(syms) From 4350098151d9d0ef0166a8a12b6716ebb5e237fc Mon Sep 17 00:00:00 2001 From: Jared Crean Date: Sat, 3 Mar 2018 12:12:41 -0500 Subject: [PATCH 20/28] download cert.pem from deps-getall, fixes #24903 (#25344) --- deps/libgit2.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/libgit2.mk b/deps/libgit2.mk index 367200cdb3365..3be41029ed9ae 100644 --- a/deps/libgit2.mk +++ b/deps/libgit2.mk @@ -120,7 +120,7 @@ clean-libgit2: -rm $(BUILDDIR)/$(LIBGIT2_SRC_DIR)/build-configured $(BUILDDIR)/$(LIBGIT2_SRC_DIR)/build-compiled -$(MAKE) -C $(BUILDDIR)/$(LIBGIT2_SRC_DIR) clean -get-libgit2: $(LIBGIT2_SRC_FILE) +get-libgit2: $(LIBGIT2_SRC_FILE) $(build_datarootdir)/julia/cert.pem extract-libgit2: $(SRCCACHE)/$(LIBGIT2_SRC_DIR)/source-extracted configure-libgit2: $(BUILDDIR)/$(LIBGIT2_SRC_DIR)/build-configured compile-libgit2: $(BUILDDIR)/$(LIBGIT2_SRC_DIR)/build-compiled From 87492e8ccf51bae7b0a850c124805572b53940c0 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Sat, 3 Mar 2018 12:03:59 -0800 Subject: [PATCH 21/28] Remove the examples/ folder (#26153) --- Make.inc | 1 - Makefile | 23 +- README.md | 1 - contrib/add_license_to_files.jl | 2 - doc/src/manual/embedding.md | 2 +- doc/src/manual/parallel-computing.md | 8 +- examples/Makefile | 12 - examples/ModInts.jl | 27 -- examples/bubblesort.jl | 19 -- examples/clustermanager/0mq/README | 27 -- examples/clustermanager/0mq/ZMQCM.jl | 281 ------------------ examples/clustermanager/0mq/broker.jl | 4 - examples/clustermanager/0mq/head.jl | 11 - examples/clustermanager/0mq/worker.jl | 5 - examples/clustermanager/simple/README | 12 - .../clustermanager/simple/UnixDomainCM.jl | 95 ------ examples/clustermanager/simple/head.jl | 7 - examples/clustermanager/simple/test_simple.jl | 13 - examples/dictchannel.jl | 34 --- examples/lru.jl | 130 -------- examples/lru_test.jl | 47 --- examples/ndgrid.jl | 52 ---- examples/queens.jl | 28 -- examples/quine.jl | 4 - examples/staged.jl | 61 ---- examples/time.jl | 45 --- examples/typetree.jl | 154 ---------- examples/wordcount.jl | 86 ------ .../InteractiveUtils/src/InteractiveUtils.jl | 2 +- test/choosetests.jl | 4 - test/cmdlineargs.jl | 2 +- 31 files changed, 11 insertions(+), 1188 deletions(-) delete mode 100644 examples/Makefile delete mode 100644 examples/ModInts.jl delete mode 100644 examples/bubblesort.jl delete mode 100644 examples/clustermanager/0mq/README delete mode 100644 examples/clustermanager/0mq/ZMQCM.jl delete mode 100644 examples/clustermanager/0mq/broker.jl delete mode 100644 examples/clustermanager/0mq/head.jl delete mode 100644 examples/clustermanager/0mq/worker.jl delete mode 100644 examples/clustermanager/simple/README delete mode 100644 examples/clustermanager/simple/UnixDomainCM.jl delete mode 100644 examples/clustermanager/simple/head.jl delete mode 100644 examples/clustermanager/simple/test_simple.jl delete mode 100644 examples/dictchannel.jl delete mode 100644 examples/lru.jl delete mode 100644 examples/lru_test.jl delete mode 100644 examples/ndgrid.jl delete mode 100644 examples/queens.jl delete mode 100644 examples/quine.jl delete mode 100644 examples/staged.jl delete mode 100644 examples/time.jl delete mode 100644 examples/typetree.jl delete mode 100644 examples/wordcount.jl diff --git a/Make.inc b/Make.inc index 9b7f7bdaf7034..d13527b19cb33 100644 --- a/Make.inc +++ b/Make.inc @@ -189,7 +189,6 @@ build_depsbindir := $(build_prefix)/tools build_libdir := $(build_prefix)/lib build_libexecdir := $(build_prefix)/libexec build_datarootdir := $(build_prefix)/share -build_docdir := $(build_datarootdir)/doc/julia build_mandir := $(build_datarootdir)/man build_man1dir := $(build_mandir)/man1 build_includedir := $(build_prefix)/include diff --git a/Makefile b/Makefile index 8eec035867f68..fa3a2e7bcb510 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ all: debug release # sort is used to remove potential duplicates DIRS := $(sort $(build_bindir) $(build_depsbindir) $(build_libdir) $(build_private_libdir) $(build_libexecdir) $(build_includedir) $(build_includedir)/julia $(build_sysconfdir)/julia $(build_datarootdir)/julia $(build_datarootdir)/julia/site $(build_man1dir)) ifneq ($(BUILDROOT),$(JULIAHOME)) -BUILDDIRS := $(BUILDROOT) $(addprefix $(BUILDROOT)/,base src ui doc deps test test/embedding test/perf examples) +BUILDDIRS := $(BUILDROOT) $(addprefix $(BUILDROOT)/,base src ui doc deps test test/embedding test/perf) BUILDDIRMAKE := $(addsuffix /Makefile,$(BUILDDIRS)) DIRS := $(DIRS) $(BUILDDIRS) $(BUILDDIRMAKE): | $(BUILDDIRS) @@ -56,20 +56,6 @@ julia_flisp.boot.inc.phony: julia-deps $(BUILDROOT)/doc/_build/html/en/index.html: $(shell find $(BUILDROOT)/base $(BUILDROOT)/doc \( -path $(BUILDROOT)/doc/_build -o -path $(BUILDROOT)/doc/deps -o -name *_constants.jl -o -name *_h.jl -o -name version_git.jl \) -prune -o -type f -print) @$(MAKE) docs -# doc needs to live under $(build_docdir), not under $(build_datarootdir)/julia/ -CLEAN_TARGETS += clean-docdir -clean-docdir: - @-rm -fr $(abspath $(build_docdir)) - -$(build_prefix)/.examples: $(wildcard $(JULIAHOME)/examples/*.jl) \ - $(shell find $(JULIAHOME)/examples/clustermanager) - @echo Copying in usr/share/doc/julia/examples - @-rm -fr $(build_docdir)/examples - @mkdir -p $(build_docdir)/examples - @cp -R $(JULIAHOME)/examples/*.jl $(build_docdir)/examples/ - @cp -R $(JULIAHOME)/examples/clustermanager $(build_docdir)/examples/ - @echo 1 > $@ - julia-symlink: julia-ui-$(JULIA_BUILD_MODE) ifneq ($(OS),WINNT) ifndef JULIA_VAGRANT_BUILD @@ -92,7 +78,7 @@ julia-src-release julia-src-debug : julia-src-% : julia-deps julia_flisp.boot.in julia-ui-release julia-ui-debug : julia-ui-% : julia-src-% @$(MAKE) $(QUIET_MAKE) -C $(BUILDROOT)/ui julia-$* -julia-base-compiler : julia-base julia-ui-$(JULIA_BUILD_MODE) $(build_prefix)/.examples +julia-base-compiler : julia-base julia-ui-$(JULIA_BUILD_MODE) @$(MAKE) $(QUIET_MAKE) -C $(BUILDROOT) $(build_private_libdir)/basecompiler.ji JULIA_BUILD_MODE=$(JULIA_BUILD_MODE) julia-sysimg-release : julia-base-compiler julia-ui-release @@ -353,7 +339,6 @@ endif # Copy in all .jl sources as well cp -R -L $(build_datarootdir)/julia $(DESTDIR)$(datarootdir)/ # Copy documentation - cp -R -L $(build_docdir)/* $(DESTDIR)$(docdir)/ cp -R -L $(BUILDROOT)/doc/_build/html $(DESTDIR)$(docdir)/ # Remove perf suite -rm -rf $(DESTDIR)$(datarootdir)/julia/test/perf/ @@ -504,7 +489,6 @@ clean: | $(CLEAN_TARGETS) @-$(MAKE) -C $(BUILDROOT)/src clean @-$(MAKE) -C $(BUILDROOT)/ui clean @-$(MAKE) -C $(BUILDROOT)/test clean - @-$(MAKE) -C $(BUILDROOT)/examples clean -rm -f $(BUILDROOT)/julia -rm -f $(BUILDROOT)/*.tar.gz -rm -f $(build_depsbindir)/stringreplace \ @@ -513,7 +497,6 @@ clean: | $(CLEAN_TARGETS) -rm -fr $(build_private_libdir) # Teporarily add this line to the Makefile to remove extras -rm -fr $(build_datarootdir)/julia/extras - -rm -f $(build_prefix)/.examples cleanall: clean @-$(MAKE) -C $(BUILDROOT)/src clean-flisp clean-support @@ -531,7 +514,7 @@ distcleanall: cleanall test testall testall1 test clean distcleanall cleanall clean-* \ run-julia run-julia-debug run-julia-release run \ install binary-dist light-source-dist.tmp light-source-dist \ - dist full-source-dist source-dist examples + dist full-source-dist source-dist test: check-whitespace $(JULIA_BUILD_MODE) @$(MAKE) $(QUIET_MAKE) -C $(BUILDROOT)/test default JULIA_BUILD_MODE=$(JULIA_BUILD_MODE) diff --git a/README.md b/README.md index 1e377307a5cc7..a3b7ef11315e7 100644 --- a/README.md +++ b/README.md @@ -411,7 +411,6 @@ The Julia source code is organized as follows: deps/ external dependencies doc/src/manual source for the user manual doc/src/stdlib source for standard library function reference - examples/ example Julia programs src/ source for Julia language core test/ test suites test/perf benchmark suites diff --git a/contrib/add_license_to_files.jl b/contrib/add_license_to_files.jl index b74fa66587f3f..5b461dc8615bd 100644 --- a/contrib/add_license_to_files.jl +++ b/contrib/add_license_to_files.jl @@ -16,7 +16,6 @@ const print_result = true # prints files which where not processed. const rootdirs = [ "../base", "../contrib", - "../examples", "../src", "../stdlib", "../test", @@ -59,7 +58,6 @@ const skipfiles = [ "../src/support/utf8.c", "../test/perf/micro/randmtzig.c", "../src/crc32c.c", - "../examples/quine.jl", # has license text in code ] const ext_prefix = Dict([ diff --git a/doc/src/manual/embedding.md b/doc/src/manual/embedding.md index 54cabebd07c6f..496d0f1b425fd 100644 --- a/doc/src/manual/embedding.md +++ b/doc/src/manual/embedding.md @@ -44,7 +44,7 @@ gcc -o test -fPIC -I$JULIA_DIR/include/julia -L$JULIA_DIR/lib test.c -ljulia $JU Then if the environment variable `JULIA_BINDIR` is set to `$JULIA_DIR/bin`, the output `test` program can be executed. -Alternatively, look at the `embedding.c` program in the Julia source tree in the `examples/` folder. +Alternatively, look at the `embedding.c` program in the Julia source tree in the `test/embedding/` folder. The file `ui/repl.c` program is another simple example of how to set `jl_options` options while linking against `libjulia`. diff --git a/doc/src/manual/parallel-computing.md b/doc/src/manual/parallel-computing.md index d70befabd87ae..58bdaf9f72de0 100644 --- a/doc/src/manual/parallel-computing.md +++ b/doc/src/manual/parallel-computing.md @@ -727,7 +727,8 @@ Methods [`put!`](@ref), [`take!`](@ref), [`fetch`](@ref), [`isready`](@ref) and on a [`RemoteChannel`](@ref) are proxied onto the backing store on the remote process. [`RemoteChannel`](@ref) can thus be used to refer to user implemented `AbstractChannel` objects. -A simple example of this is provided in `examples/dictchannel.jl` which uses a dictionary as its +A simple example of this is provided in `dictchannel.jl` in the +[Examples repository](https://github.com/JuliaArchive/Examples), which uses a dictionary as its remote store. ## Channels and RemoteChannels @@ -1246,7 +1247,8 @@ transport and Julia's in-built parallel infrastructure. A `BufferStream` is an in-memory [`IOBuffer`](@ref) which behaves like an `IO`--it is a stream which can be handled asynchronously. -Folder `examples/clustermanager/0mq` contains an example of using ZeroMQ to connect Julia workers +The folder `clustermanager/0mq` in the [Examples repository](https://github.com/JuliaArchive/Examples) +contains an example of using ZeroMQ to connect Julia workers in a star topology with a 0MQ broker in the middle. Note: The Julia processes are still all *logically* connected to each other--any worker can message any other worker directly without any awareness of 0MQ being used as the transport layer. @@ -1268,7 +1270,7 @@ When using custom transports: the corresponding `IO` objects must be closed by the implementation to ensure proper cleanup. The default implementation simply executes an `exit()` call on the specified remote worker. -`examples/clustermanager/simple` is an example that shows a simple implementation using UNIX domain +The Examples folder `clustermanager/simple` is an example that shows a simple implementation using UNIX domain sockets for cluster setup. ## Network Requirements for LocalManager and SSHManager diff --git a/examples/Makefile b/examples/Makefile deleted file mode 100644 index 6a3244b3aa4a8..0000000000000 --- a/examples/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -## this is a simple wrapper just to forward on known commands to the -## embedding example with values pulled from Make.inc -SRCDIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) -JULIAHOME := $(abspath $(SRCDIR)/..) -BUILDDIR := . -include $(JULIAHOME)/Make.inc - -release: # default target -# forward all variables expected by the embedding example -JULIA:=$(call spawn,$(JULIA_EXECUTABLE)) -BIN:=$(BUILDDIR)/embedding -CC:=$(CC) diff --git a/examples/ModInts.jl b/examples/ModInts.jl deleted file mode 100644 index 01fa574a4188a..0000000000000 --- a/examples/ModInts.jl +++ /dev/null @@ -1,27 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -module ModInts -export ModInt - -import Base: +, -, *, /, inv - -struct ModInt{n} <: Integer - k::Int - ModInt{n}(k) where {n} = new(mod(k,n)) -end - -Base.show(io::IO, k::ModInt{n}) where {n} = - print(io, get(io, :typeinfo, Any) == typeof(k) ? k.k : "$(k.k) mod $n") - -(+)(a::ModInt{n}, b::ModInt{n}) where {n} = ModInt{n}(a.k+b.k) -(-)(a::ModInt{n}, b::ModInt{n}) where {n} = ModInt{n}(a.k-b.k) -(*)(a::ModInt{n}, b::ModInt{n}) where {n} = ModInt{n}(a.k*b.k) -(-)(a::ModInt{n}) where {n} = ModInt{n}(-a.k) - -inv(a::ModInt{n}) where {n} = ModInt{n}(invmod(a.k, n)) -(/)(a::ModInt{n}, b::ModInt{n}) where {n} = a*inv(b) # broaden for non-coprime? - -Base.promote_rule(::Type{ModInt{n}}, ::Type{Int}) where {n} = ModInt{n} -Base.convert(::Type{ModInt{n}}, i::Int) where {n} = ModInt{n}(i) - -end # module diff --git a/examples/bubblesort.jl b/examples/bubblesort.jl deleted file mode 100644 index 6b7c244da1fa9..0000000000000 --- a/examples/bubblesort.jl +++ /dev/null @@ -1,19 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -import Base.Sort -struct BubbleSortAlg <: Sort.Algorithm end -const BubbleSort = BubbleSortAlg() - -function Base.sort!(v::AbstractVector, lo::Int, hi::Int, ::BubbleSortAlg, o::Sort.Ordering) - while true - clean = true - for i = lo:hi-1 - if Sort.lt(o, v[i+1], v[i]) - v[i+1], v[i] = v[i], v[i+1] - clean = false - end - end - clean && break - end - return v -end diff --git a/examples/clustermanager/0mq/README b/examples/clustermanager/0mq/README deleted file mode 100644 index c6bb2cfcfb7ff..0000000000000 --- a/examples/clustermanager/0mq/README +++ /dev/null @@ -1,27 +0,0 @@ -This is a proof-of-concept that uses ZeroMQ as transport. -It uses a star topology as opposed to the native mesh network. - -Package ZMQ must be installed. All workers only run on localhost. - -All Julia nodes only connect to a "broker" process that listens on known ports -8100 and 8101 via ZMQ sockets. - - -All commands must be run from `examples/clustermanager/0mq` directory - -First, start the broker. In a new console type: - julia broker.jl - -This does not return. - -Next, start a Julia REPL and type: - include("ZMQCM.jl") - ZMQCM.start_master(4) # start with four workers - - -Alternatively, head.jl, a test script could be run. It just launches the requested number of workers, -executes a simple command on all of them and exits. - julia head.jl 4 - -NOTE: As stated this is a proof-of-concept. A real Julia cluster using ZMQ will probably use -different ZMQ socket types and optimize the transport. diff --git a/examples/clustermanager/0mq/ZMQCM.jl b/examples/clustermanager/0mq/ZMQCM.jl deleted file mode 100644 index 4955cc2e12514..0000000000000 --- a/examples/clustermanager/0mq/ZMQCM.jl +++ /dev/null @@ -1,281 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -# the 0mq clustermanager depends on package ZMQ. For testing purposes, at least -# make sure the code loads without it. -try - using ZMQ -end - -using Distributed -import Distributed: launch, manage, connect, kill - -const BROKER_SUB_PORT = 8100 -const BROKER_PUB_PORT = 8101 - -const SELF_INITIATED = 0 -const REMOTE_INITIATED = 1 - -const PAYLOAD_MSG = "J" -const CONTROL_MSG = "Z" - -const REQUEST_ACK = "R" -const ACK_MSG = "A" -const KILL_MSG = "K" - -mutable struct ZMQCMan <: ClusterManager - map_zmq_julia::Dict{Int, Tuple} - c::Condition - isfree::Bool - ctx - pub - sub - zid_self - ZMQCMan() = new(Dict{Int, Tuple}(), Condition(), true) -end - -const manager = ZMQCMan() - -function lock_for_send() - if manager.isfree == true - manager.isfree = false - else - while manager.isfree == false - wait(manager.c) - if manager.isfree == true - manager.isfree = false - return - end - end - end -end - -function release_lock_for_send() - manager.isfree = true - notify(manager.c, all=true) -end - -function init_node(zid=0) - manager.ctx = Context(1) - pub=Socket(manager.ctx, PUB) # Outbound - connect(pub, "tcp://127.0.0.1:$BROKER_SUB_PORT") - - sub=Socket(manager.ctx, SUB) # In bound - connect(sub, "tcp://127.0.0.1:$BROKER_PUB_PORT") - ZMQ.set_subscribe(sub, string(zid)) - - manager.pub = pub - manager.sub = sub - manager.zid_self = zid - - (pub, sub) -end - -function send_data(zid, mtype, data) - lock_for_send() - ZMQ.send(manager.pub, Message(string(zid)), SNDMORE) - ZMQ.send(manager.pub, Message(string(manager.zid_self)), SNDMORE) - #println("Sending message of type $mtype to $zid") - ZMQ.send(manager.pub, Message(mtype), SNDMORE) - ZMQ.send(manager.pub, Message(data)) - release_lock_for_send() -end - -function setup_connection(zid, initiated_by) - try - read_stream=BufferStream() - write_stream=BufferStream() - - if initiated_by == REMOTE_INITIATED - test_remote = false - else - test_remote = true - end - - manager.map_zmq_julia[zid] = (read_stream, write_stream, test_remote) - - @schedule begin - while true - (r_s, w_s, do_test_remote) = manager.map_zmq_julia[zid] - if do_test_remote - send_data(zid, CONTROL_MSG, REQUEST_ACK) - sleep(0.5) - else - break - end - end - (r_s, w_s, do_test_remote) = manager.map_zmq_julia[zid] - - while true - data = readavailable(w_s) - send_data(zid, PAYLOAD_MSG, data) - end - end - (read_stream, write_stream) - catch e - Base.show_backtrace(stdout,catch_backtrace()) - println(e) - rethrow(e) - end -end - -# BROKER -function start_broker() - ctx=Context(1) - xpub=Socket(ctx, XPUB) - xsub=Socket(ctx, XSUB) - - ZMQ.bind(xsub, "tcp://127.0.0.1:$(BROKER_SUB_PORT)") - ZMQ.bind(xpub, "tcp://127.0.0.1:$(BROKER_PUB_PORT)") - - ccall((:zmq_proxy, :libzmq), Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), xsub.data, xpub.data, C_NULL) -# proxy(xsub, xpub) - - # control never comes here - ZMQ.close(xpub) - ZMQ.close(xsub) - ZMQ.close(ctx) -end - -function recv_data() - try - #println("On $(manager.zid_self) waiting to recv message") - zid = parse(Int,String(ZMQ.recv(manager.sub))) - @assert zid == manager.zid_self - - from_zid = parse(Int,String(ZMQ.recv(manager.sub))) - mtype = String(ZMQ.recv(manager.sub)) - - #println("$zid received message of type $mtype from $from_zid") - - data = ZMQ.recv(manager.sub) - if mtype == CONTROL_MSG - cmsg = String(data) - if cmsg == REQUEST_ACK - #println("$from_zid REQUESTED_ACK from $zid") - # send back a control_msg - send_data(from_zid, CONTROL_MSG, ACK_MSG) - elseif cmsg == ACK_MSG - #println("$zid got ACK_MSG from $from_zid") - (r_s, w_s, test_remote) = manager.map_zmq_julia[from_zid] - manager.map_zmq_julia[from_zid] = (r_s, w_s, false) - elseif cmsg == KILL_MSG - exit(0) - else - error("Unknown control message : ", cmsg) - end - data = "" - end - - (from_zid, data) - catch e - Base.show_backtrace(stdout,catch_backtrace()) - println(e) - rethrow(e) - end - -end - -# MASTER -function start_master(np) - init_node() - @schedule begin - try - while true - (from_zid, data) = recv_data() - - #println("master recv data from $from_zid") - - (r_s, w_s, t_r) = manager.map_zmq_julia[from_zid] - unsafe_write(r_s, pointer(data), length(data)) - end - catch e - Base.show_backtrace(stdout,catch_backtrace()) - println(e) - rethrow(e) - end - end - - addprocs(manager; np=np) -end - - -function launch(manager::ZMQCMan, params::Dict, launched::Array, c::Condition) - #println("launch $(params[:np])") - for i in 1:params[:np] - io, pobj = open(`$(params[:exename]) worker.jl $i $(cluster_cookie())`, "r") - - wconfig = WorkerConfig() - wconfig.userdata = Dict(:zid=>i, :io=>io) - push!(launched, wconfig) - notify(c) - end -end - -function connect(manager::ZMQCMan, pid::Int, config::WorkerConfig) - #println("connect_m2w") - if myid() == 1 - zid = config.userdata[:zid] - config.connect_at = zid # This will be useful in the worker-to-worker connection setup. - - print_worker_stdout(config.userdata[:io], pid) - else - #println("connect_w2w") - zid = config.connect_at - config.userdata = Dict{Symbol, Any}(:zid=>zid) - end - - streams = setup_connection(zid, SELF_INITIATED) - - udata = config.userdata - udata[:streams] = streams - - streams -end - -# WORKER -function start_worker(zid, cookie) - #println("start_worker") - init_worker(cookie, ZMQCMan()) - init_node(zid) - - while true - (from_zid, data) = recv_data() - - #println("worker recv data from $from_zid") - - streams = get(manager.map_zmq_julia, from_zid, nothing) - if streams === nothing - # First time.. - (r_s, w_s) = setup_connection(from_zid, REMOTE_INITIATED) - process_messages(r_s, w_s) - else - (r_s, w_s, t_r) = streams - end - - unsafe_write(r_s, pointer(data), length(data)) - end -end - -function manage(manager::ZMQCMan, id::Int, config::WorkerConfig, op) - nothing -end - -function kill(manager::ZMQCMan, pid::Int, config::WorkerConfig) - send_data(config.userdata[:zid], CONTROL_MSG, KILL_MSG) - (r_s, w_s) = config.userdata[:streams] - close(r_s) - close(w_s) - - # remove from our map - delete!(manager.map_zmq_julia, config.userdata[:zid]) - - nothing -end - - -function print_worker_stdout(io, pid) - @schedule while !eof(io) - line = readline(io) - println(" From worker $(pid):\t$line") - end -end diff --git a/examples/clustermanager/0mq/broker.jl b/examples/clustermanager/0mq/broker.jl deleted file mode 100644 index 87d2849046356..0000000000000 --- a/examples/clustermanager/0mq/broker.jl +++ /dev/null @@ -1,4 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -include("ZMQCM.jl") -start_broker() diff --git a/examples/clustermanager/0mq/head.jl b/examples/clustermanager/0mq/head.jl deleted file mode 100644 index ff0f718eb10b5..0000000000000 --- a/examples/clustermanager/0mq/head.jl +++ /dev/null @@ -1,11 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -include("ZMQCM.jl") - -# @spawn run(`julia broker.jl`) - -start_master(parse(Int,ARGS[1])) - -resp = pmap(x -> myid() *2, [1:nworkers()]) - -println(resp) diff --git a/examples/clustermanager/0mq/worker.jl b/examples/clustermanager/0mq/worker.jl deleted file mode 100644 index bbb2ebca60a85..0000000000000 --- a/examples/clustermanager/0mq/worker.jl +++ /dev/null @@ -1,5 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -include("ZMQCM.jl") - -start_worker(parse(Int,ARGS[1]), ARGS[2]) diff --git a/examples/clustermanager/simple/README b/examples/clustermanager/simple/README deleted file mode 100644 index b14d0699d4bc2..0000000000000 --- a/examples/clustermanager/simple/README +++ /dev/null @@ -1,12 +0,0 @@ -This is a simple proof-of-concept that uses UNIX domain sockets as transport. - -All commands must be run from `examples/clustermanager/simple` directory - -Start a Julia REPL and type: - include("UnixDomainCM.jl") - addprocs(UnixDomainCM(4)) # start with four workers - -Alternatively, head.jl, a test script could be run. It just launches the requested number of workers, -executes a simple command on all of them and exits. - julia head.jl 4 - diff --git a/examples/clustermanager/simple/UnixDomainCM.jl b/examples/clustermanager/simple/UnixDomainCM.jl deleted file mode 100644 index 5426a64010a04..0000000000000 --- a/examples/clustermanager/simple/UnixDomainCM.jl +++ /dev/null @@ -1,95 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -using Sockets, Distributed -import Distributed: launch, manage, connect, exit - -mutable struct UnixDomainCM <: ClusterManager - np::Integer -end - -function launch(manager::UnixDomainCM, params::Dict, launched::Array, c::Condition) -# println("launch $(manager.np)") - cookie = cluster_cookie() - for i in 1:manager.np - sockname = tempname() - try - __file__ = @__FILE__ - cmd = `$(params[:exename]) --startup-file=no $__file__ udwrkr $sockname $cookie` - pobj = open(cmd) - - wconfig = WorkerConfig() - wconfig.userdata = Dict(:sockname=>sockname, :io=>pobj.out, :process=>pobj) - push!(launched, wconfig) - notify(c) - catch e - println(e) - end - end -end - -function connect(manager::UnixDomainCM, pid::Int, config::WorkerConfig) - if myid() == 1 -# println("connect_m2w") - # This will be useful in the worker-to-worker connection setup. - config.connect_at = config.userdata[:sockname] - - print_worker_stdout(config.userdata[:io], pid) - else -# println("connect_w2w") - sockname = config.connect_at - config.userdata = Dict{Symbol, Any}(:sockname=>sockname) - end - - t = time() - while true - try - address = config.userdata[:sockname] - if isa(address, Tuple) - sock = connect(address...) - else - sock = connect(address) - end - return (sock, sock) - catch e - if (time() - t) > 30.0 - rethrow(e) - else - sleep(0.1) - end - end - end - -end - -# WORKER -function start_worker(sockname, cookie) - init_worker(cookie, UnixDomainCM(0)) - - srvr = listen(sockname) - while true - sock = accept(srvr) - process_messages(sock, sock) - end -end - -function manage(manager::UnixDomainCM, id::Int, config::WorkerConfig, op) - # Does not seem to be required, filesystem entry cleanup is happening automatically on process exit -# if op == :deregister -# try -# rm(config.userdata[:sockname]) -# end -# end - nothing -end - -function print_worker_stdout(io, pid) - @schedule while !eof(io) - line = readline(io) - println(" From worker $(pid):\t$line") - end -end - -if (length(ARGS) > 0) && (ARGS[1] == "udwrkr") - # script has been launched as a worker - start_worker(ARGS[2], ARGS[3]) -end diff --git a/examples/clustermanager/simple/head.jl b/examples/clustermanager/simple/head.jl deleted file mode 100644 index cb16b8eb4d740..0000000000000 --- a/examples/clustermanager/simple/head.jl +++ /dev/null @@ -1,7 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -include("UnixDomainCM.jl") - -addprocs(UnixDomainCM(parse(Int,ARGS[1]))) -resp = pmap(x -> myid() *2, [1:nworkers()]) -println(resp) diff --git a/examples/clustermanager/simple/test_simple.jl b/examples/clustermanager/simple/test_simple.jl deleted file mode 100644 index 7cbb4d8008d95..0000000000000 --- a/examples/clustermanager/simple/test_simple.jl +++ /dev/null @@ -1,13 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -using Distributed -cmanpath = joinpath(@__DIR__, "UnixDomainCM.jl") -include(cmanpath) - -npids = addprocs(UnixDomainCM(2)) -@assert length(npids) == 2 -test_pids = [remotecall_fetch(myid, x) for x in npids] -@assert npids == test_pids -rmprocs(npids; waitfor=1.0) - -exit(0) diff --git a/examples/dictchannel.jl b/examples/dictchannel.jl deleted file mode 100644 index f1b9bfd68a6ca..0000000000000 --- a/examples/dictchannel.jl +++ /dev/null @@ -1,34 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -import Base: put!, wait, isready, take!, fetch - -mutable struct DictChannel <: AbstractChannel - d::Dict - cond_take::Condition # waiting for data to become available - DictChannel() = new(Dict(), Condition()) -end - -function put!(D::DictChannel, k, v) - D.d[k] = v - notify(D.cond_take) - D -end - -function take!(D::DictChannel, k) - v=fetch(D,k) - delete!(D.d, k) - v -end - -isready(D::DictChannel) = length(D.d) > 1 -isready(D::DictChannel, k) = haskey(D.d,k) -function fetch(D::DictChannel, k) - wait(D,k) - D.d[k] -end - -function wait(D::DictChannel, k) - while !isready(D, k) - wait(D.cond_take) - end -end diff --git a/examples/lru.jl b/examples/lru.jl deleted file mode 100644 index 7703f078469a3..0000000000000 --- a/examples/lru.jl +++ /dev/null @@ -1,130 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -module LRUExample -# An LRU (Least Recently Used) cache is an associative data structure which -# maintains its contents in an order such that the most recently used item -# is at the beginning of the structure, and the least recently used at the end. -# -# This file specifies two types of LRU caches, both with and without a size -# limit. BoundedLRU has a limit and evicts the LRU item if a new item is added -# after that bound is reached. UnboundedLRU does not have a maximum size, but -# can be used as a basis for more complex LRUs. -# -# LRUs should follow the interfaces for general collections, indexable -# collections, and associative collections. - -# The standard implementation of an LRU backs a hash table with a doubly-linked -# list for O(1) operations when reordering on access and eviction. The Julia -# implementation instead backs the table with a Vector. For moderately-sized -# collections, the difference in performance is small, and this implmentation -# is simpler and easier to understand. - -import Base.isempty, Base.length, Base.sizeof -import Base.start, Base.next, Base.done -import Base.haskey, Base.get -import Base.setindex!, Base.getindex, Base.delete!, Base.empty! -import Base.show - -abstract type LRU{K,V} <: AbstractDict{K,V} end - -# Default cache size -const __MAXCACHE = 1024 - -mutable struct CacheItem{K,V} - k::K - v::V -end - -mutable struct UnboundedLRU{K,V} <: LRU{K,V} - ht::Dict - q::Vector{CacheItem} - - UnboundedLRU{K,V}() where {K,V} = new(Dict(), similar(Vector{CacheItem}(uninitialized, 1), 0)) -end -UnboundedLRU() = UnboundedLRU{Any, Any}() - -mutable struct BoundedLRU{K,V} <: LRU{K,V} - ht::Dict - q::Vector{CacheItem} - maxsize::Int - - BoundedLRU{K,V}(m) where {K,V} = new(Dict(), similar(Vector{CacheItem}(uninitialized, 1), 0), m) - BoundedLRU{K,V}() where {K,V} = BoundedLRU(__MAXCACHE) -end -BoundedLRU(m) = BoundedLRU{Any, Any}(m) -BoundedLRU() = BoundedLRU{Any, Any}() - -## collections ## - -isempty(lru::LRU) = isempty(lru.q) -length(lru::LRU) = length(lru.q) - -## associative ## - -# Should this check count as an access? -haskey(lru::LRU, key) = haskey(lru.ht, key) - -get(lru::LRU, key, default) = haskey(lru, key) ? lru[key] : default - -function empty!(lru::LRU) - empty!(lru.ht) - empty!(lru.q) -end - - -show(io::IO, lru::UnboundedLRU) = print(io,"UnboundedLRU()") -show(io::IO, lru::BoundedLRU) = print(io,"BoundedLRU($(lru.maxsize))") - -## indexable ## - -# Method to do the second, slow lookup in the list with early return. -function locate(q, x) - for i = 1:length(q) - if q[i] == x - return i - end - end - error("Item not found.") -end - -function getindex(lru::LRU, key) - item = lru.ht[key] - idx = locate(lru.q, item) - splice!(lru.q, idx) - pushfirst!(lru.q, item) - item.v -end - -function setindex!(lru::LRU, v, key) - if haskey(lru, key) - item = lru.ht[key] - idx = locate(lru.q, item) - item.v = v - splice!(lru.q, idx) - else - item = CacheItem(key, v) - lru.ht[key] = item - end - pushfirst!(lru.q, item) -end - -# Eviction -function setindex!(lru::BoundedLRU, v::V, key::K) where {V,K} - invoke(setindex!, Tuple{LRU,V,K}, lru, v, key) - nrm = length(lru) - lru.maxsize - for i in 1:nrm - rm = pop!(lru.q) - delete!(lru.ht, rm.k) - end -end - -## associative ## - -function delete!(lru::LRU, key) - item = lru.ht[key] - idx = locate(lru.q, item) - delete!(lru.ht, key) - delete!(lru.q, idx) -end - -end # module diff --git a/examples/lru_test.jl b/examples/lru_test.jl deleted file mode 100644 index 5c797c2a57906..0000000000000 --- a/examples/lru_test.jl +++ /dev/null @@ -1,47 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -using .LRUExample - -TestLRU = LRUExample.UnboundedLRU{String, String}() -TestBLRU = LRUExample.BoundedLRU{String, String}(1000) - -get_str(i) = String(vcat(map(x->[x>>4; x&0x0F], reinterpret(UInt8, [Int32(i)]))...)) - -isbounded(::Type{L}) where {L<:LRUExample.LRU} = any(map(n->n==:maxsize, fieldnames(L))) -isbounded(l::L) where {L<:LRUExample.LRU} = isbounded(L) - -nmax = map(x->round(Int, exp10(x)), range(2, stop=5, length=4)) - -function lrutest() - #println("LRU consistency tests") - for lru in (TestLRU,TestBLRU) - for n in nmax - empty!(lru) - #@printf(" %s, %d items\n", lru, n) - #print(" Simple eviction: ") - for i in 1:n - str = get_str(i) - lru[str] = str - @assert lru.q[1].v == str - if isbounded(lru) && length(lru) >= lru.maxsize - tailstr = get_str(i-lru.maxsize+1) - @assert lru.q[end].v == tailstr - end - end - #println("pass") - - #print(" Lookup, random access: ") - for i in 1:n - str = get_str(rand(1:n)) - if haskey(lru, str) # the bounded LRUs can have cache misses - blah = lru[str] - @assert lru.q[1].v == blah - end - end - #println("pass") - end - empty!(lru) - end -end - -lrutest() diff --git a/examples/ndgrid.jl b/examples/ndgrid.jl deleted file mode 100644 index f5fce291c4636..0000000000000 --- a/examples/ndgrid.jl +++ /dev/null @@ -1,52 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -ndgrid(v::AbstractVector) = copy(v) - -function ndgrid(v1::AbstractVector{T}, v2::AbstractVector{T}) where T - m, n = length(v1), length(v2) - v1 = reshape(v1, m, 1) - v2 = reshape(v2, 1, n) - (repeat(v1, 1, n), repeat(v2, m, 1)) -end - -function ndgrid_fill(a, v, s, snext) - for j = 1:length(a) - a[j] = v[div(rem(j-1, snext), s)+1] - end -end - -function ndgrid(vs::AbstractVector{T}...) where T - n = length(vs) - sz = map(length, vs) - out = ntuple(i->Array{T}(uninitialized, sz), n) - s = 1 - for i=1:n - a = out[i]::Array - v = vs[i] - snext = s*size(a,i) - ndgrid_fill(a, v, s, snext) - s = snext - end - out -end - -meshgrid(v::AbstractVector) = meshgrid(v, v) - -function meshgrid(vx::AbstractVector{T}, vy::AbstractVector{T}) where T - m, n = length(vy), length(vx) - vx = reshape(vx, 1, n) - vy = reshape(vy, m, 1) - (repeat(vx, m, 1), repeat(vy, 1, n)) -end - -function meshgrid(vx::AbstractVector{T}, vy::AbstractVector{T}, - vz::AbstractVector{T}) where T - m, n, o = length(vy), length(vx), length(vz) - vx = reshape(vx, 1, n, 1) - vy = reshape(vy, m, 1, 1) - vz = reshape(vz, 1, 1, o) - om = fill(1, m) - on = fill(1, n) - oo = fill(1, o) - (vx[om, :, oo], vy[:, on, oo], vz[om, on, :]) -end diff --git a/examples/queens.jl b/examples/queens.jl deleted file mode 100644 index e44e2fd2c083b..0000000000000 --- a/examples/queens.jl +++ /dev/null @@ -1,28 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -# n-queens (nqueens) solver, for nsquaresx-by-nsquaresy board - -struct Queen - x::Int - y::Int -end -hitshorz(queena, queenb) = queena.x == queenb.x -hitsvert(queena, queenb) = queena.y == queenb.y -hitsdiag(queena, queenb) = abs(queena.x - queenb.x) == abs(queena.y - queenb.y) -hitshvd(qa, qb) = hitshorz(qa, qb) || hitsvert(qa, qb) || hitsdiag(qa, qb) -hitsany(testqueen, queens) = any(q -> hitshvd(testqueen, q), queens) - -function trysolve(nsquaresx, nsquaresy, nqueens, presqueens = ()) - nqueens == 0 && return presqueens - for xsquare in 1:nsquaresx - for ysquare in 1:nsquaresy - testqueen = Queen(xsquare, ysquare) - if !hitsany(testqueen, presqueens) - tryqueens = (presqueens..., testqueen) - maybesol = trysolve(nsquaresx, nsquaresy, nqueens - 1, tryqueens) - maybesol !== nothing && return maybesol - end - end - end - return nothing -end diff --git a/examples/quine.jl b/examples/quine.jl deleted file mode 100644 index aae47e3dbfdbf..0000000000000 --- a/examples/quine.jl +++ /dev/null @@ -1,4 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -x="println(\"# This file is a part of Julia. License is MIT: https://julialang.org/license\\n\\nx=\$(repr(x))\\n\$x\")" -println("# This file is a part of Julia. License is MIT: https://julialang.org/license\n\nx=$(repr(x))\n$x") diff --git a/examples/staged.jl b/examples/staged.jl deleted file mode 100644 index 96f3ebb6aa6c6..0000000000000 --- a/examples/staged.jl +++ /dev/null @@ -1,61 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -function add_method(gf, an, at, body) - argexs = [Expr(Symbol("::"), an[i], at[i]) for i=1:length(an)] - def = quote - let __F__=($gf) - function __F__($(argexs...)) - $body - end - end - end - eval(def) -end - -macro staged(fdef) - if !isa(fdef,Expr) || fdef.head !== :function - error("@staged: expected method definition") - end - fname = fdef.args[1].args[1] - argspec = fdef.args[1].args[2:end] - argnames = map(x->(isa(x,Expr) ? x.args[1] : x), argspec) - qargnames = map(x->Expr(:quote,x), argnames) - fbody = fdef.args[2] - @gensym gengf argtypes expander genbody - quote - let ($gengf) - global ($fname) # should be "outer" - local ($expander) - function ($expander)($(argnames...)) - $fbody - end - ($gengf)() = 0 # should be initially empty GF - function ($fname)($(argspec...)) - ($argtypes) = typeof(tuple($(argnames...))) - if !hasmethod($gengf, $argtypes) - ($genbody) = apply(($expander), ($argtypes)) - add_method($gengf, Any[$(qargnames...)], - $argtypes, $genbody) - end - return ($gengf)($(argnames...)) - end - end - end -end - -# example - -@staged function nloops(dims::Tuple) - names = map(x->gensym(), dims) - ex = quote - println([$(names...)]) - end - for i = 1:length(dims) - ex = quote - for $(names[i]) in dims[$i] - $ex - end - end - end - ex -end diff --git a/examples/time.jl b/examples/time.jl deleted file mode 100644 index 2ffb69dcaabbd..0000000000000 --- a/examples/time.jl +++ /dev/null @@ -1,45 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -module Time -export TimeDelta - -import Base.show, Base.+, Base.-, Base.convert, Base.promote_rule - -struct TimeDelta{p} - v::Int64 -end - -const PREFIXES = [ - "yocto", "zepto", "atto", "femto", "pico", "nano", "micro", "milli", - "", "kilo", "mega", "giga", "tera", "peta", "exa", "zetta", "yotta", -] -const ZERO_INDEX = 9 -const MAX_INDEX = 17 - -function show(io::IO, x::TimeDelta{p}) where p - k = max(1,min(MAX_INDEX,fld(p,3)+ZERO_INDEX)) - r = p-3(k-ZERO_INDEX) - prefix = PREFIXES[k] - if r == 0 - s = x.v == 1 ? "" : "s" - print(io, "$(x.v) $(prefix)second$s") - elseif r > 0 - print(io, "$(x.v*10^r) $(prefix)seconds") - else - print(io, "$(x.v/10^-r) $(prefix)seconds") - end -end - -convert(::Type{TimeDelta{p}}, x::TimeDelta{q}) where {p,q} = - TimeDelta{p}(p <= q ? x.v*10^(q-p) : div(x.v,10^(p-q))) - -promote_rule(::Type{TimeDelta{p}}, ::Type{TimeDelta{q}}) where {p,q} = TimeDelta{min(p,q)} - -(-)(x::TimeDelta{p}) where {p} = TimeDelta{p}(-x.v) -(+)(x::TimeDelta{p}, y::TimeDelta{p}) where {p} = TimeDelta{p}(x.v+y.v) -(-)(x::TimeDelta{p}, y::TimeDelta{p}) where {p} = TimeDelta{p}(x.v-y.v) - -(+)(x::TimeDelta, y::TimeDelta) = +(promote(x,y)...) -(-)(x::TimeDelta, y::TimeDelta) = -(promote(x,y)...) - -end # module diff --git a/examples/typetree.jl b/examples/typetree.jl deleted file mode 100644 index 1735f32a01c02..0000000000000 --- a/examples/typetree.jl +++ /dev/null @@ -1,154 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -module TypeTrees -## -# Generate a text graphic of Julia modules type tree -## - -struct Binding - mod::Module - sym::Symbol -end -Binding(tn::TypeName) = Binding(tn.module, tn.name) -Base.isless(a::Binding, b::Binding) = isless(a.sym, b.sym) - -# The node type holds the type of the current node and a dict of subtypes -struct TTNode - typ # ::Type - subtypes::Dict{Binding, TTNode} - - TTNode(@nospecialize t) = new(t, Dict{Binding, TTNode}()) -end - -# Add a node to a dict if not added -function add_ttnode(subtypes::Dict{Binding, TTNode}, sname::Binding, tnode::TTNode) - return get!(subtypes, sname, tnode) -end - -function add_ttnode(subtypes::Dict{Binding, TTNode}, sname::Binding, t::Type) - return get!(subtypes, sname, TTNode(t)) -end - -# Store a type and its type hierarchy chain -# Recurse till we reach the top level type -function store_type(sname::Binding, t::Union) - suptype = Union - tnode = TTNode(t) - - # store unions under Union type - subtypes = store_type(Binding(suptype.name), suptype) - add_ttnode(subtypes, sname, tnode) - store_union(sname, tnode, t) - - # unions are also in a sense related to the types of their components - - return tnode.subtypes -end -function store_union(sname::Binding, tnode::TTNode, @nospecialize t) - t = Base.unwrap_unionall(t) - if isa(t, Union) - store_union(sname, tnode, t.a) - store_union(sname, tnode, t.b) - elseif isa(t, DataType) - binding = Binding(t.name) - subtypes = store_type(binding, t) - add_ttnode(subtypes, sname, tnode) - end - nothing -end - -function store_type(sname::Binding, t::UnionAll) - suptype = Base.unwrap_unionall(t) - binding = isa(suptype, DataType) ? Binding(suptype.name) : Binding(Main, string(suptype::Union)) - subtypes = store_type(binding, suptype) - tnode = add_ttnode(subtypes, sname, t) - return tnode.subtypes -end - -function store_type(sname::Binding, t::DataType) - suptype = supertype(t) - subtypes = (suptype != t) ? store_type(Binding(suptype.name), suptype) : types_tree - tnode = add_ttnode(subtypes, sname, t) - return tnode.subtypes -end - -# examine all symbols in module and store those that are types -function store_all_from(m::Module) - for s in names(m, all = true) - if isdefined(m, s) && !Base.isdeprecated(m, s) - t = getfield(m, s) - if isa(t, Type) && t !== Union{} - store_type(Binding(m, s), t) - elseif isa(t, Module) && nameof(t) === s && parentmodule(t) === m && t !== m - store_all_from(t) - end - end - end -end - -type_props(typ) = "" -type_props(typ::DataType) = string("<<", - typ.abstract ? " abstract" : " concrete", - typ.mutable ? " mutable" : " immutable", - typ.layout != C_NULL ? string( - Base.datatype_pointerfree(typ) ? " pointerfree" : "", - Base.datatype_haspadding(typ) ? " haspadding" : "", - " nfields:", Core.nfields(typ), - " size:", typ.size, - ", align:", Base.datatype_alignment(typ)) : "", - " >>") - -function print_tree(subtypes::Dict{Binding, TTNode}, pfx::String="") - for b in sort!(collect(keys(subtypes))) - v = subtypes[b] - ishidden = unsafe_load(Base.unsafe_convert(Ptr{UInt8}, b.sym)) == UInt8('#') - if ishidden && supertype(v.typ) === Function - continue - end - if b.mod === Main - n = string(b.sym) - elseif !isa(v.typ, DataType) || v.typ.name.module != b.mod || v.typ.name.name != b.sym - n_io = IOBuffer() - print(n_io, b.mod, '.', b.sym) - ua = v.typ - if isa(ua, UnionAll) - print(n_io, "{") - while true - print(n_io, ua.var) - ua = ua.body - if isa(ua, UnionAll) - print(n_io, ", ") - else - break - end - end - print(n_io, "}") - end - n = String(take!(n_io)) - else - n = string(v.typ) - end - if n == string(v.typ) - println(pfx, "+- ", n, " ", type_props(v.typ)) - else - println(pfx, "+- ", n, " = ", v.typ, " ", type_props(v.typ)) - end - v.typ === Function && println(pfx, ". ## hiding implicit Function subtypes ##") - print_tree(v.subtypes, pfx * ". ") - end -end - - -# TODO: optionally take module names in command line -# TODO: option to list subtrees of type tree, or other symbol types -const types_tree = Dict{Binding, TTNode}() - -store_all_from(Main) - -# print_tree(types_tree) - -end # module - -if !isinteractive() - TypeTrees.print_tree(TypeTrees.types_tree) -end diff --git a/examples/wordcount.jl b/examples/wordcount.jl deleted file mode 100644 index f93dd84e2893d..0000000000000 --- a/examples/wordcount.jl +++ /dev/null @@ -1,86 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -# wordcount.jl -# -# Implementation of parallelized "word-count" of a text, inspired by the -# Hadoop WordCount example. Uses @spawn and fetch() to parallelize -# the "map" task. Reduce is currently done single-threaded. -# -# To run in parallel on a string stored in variable `text`: -# julia -p -# julia> require("/examples/wordcount.jl") -# julia> ...(define text)... -# julia> counts=parallel_wordcount(text) -# -# Or to run on a group of files, writing results to an output file: -# julia -p -# julia> require("/examples/wordcount.jl") -# julia> wordcount_files("/tmp/output.txt", "/tmp/input1.txt","/tmp/input2.txt",...) - -# "Map" function. -# Takes a string. Returns a Dict with the number of times each word -# appears in that string. -function wordcount(text) - words=split(text,[' ','\n','\t','-','.',',',':',';'];keep=false) - counts=Dict() - for w = words - counts[w]=get(counts,w,0)+1 - end - return counts -end - -# "Reduce" function. -# Takes a collection of Dicts in the format returned by wordcount() -# Returns a Dict in which words that appear in multiple inputs -# have their totals added together. -function wcreduce(wcs) - counts=Dict() - for c in wcs, (k,v) in c - counts[k] = get(counts,k,0)+v - end - return counts -end - -# Splits input string into nprocs() equal-sized chunks (last one rounds up), -# and @spawns wordcount() for each chunk to run in parallel. Then fetch()s -# results and performs wcreduce(). -function parallel_wordcount(text) - lines=split(text,'\n';keep=false) - np=nprocs() - unitsize=ceil(length(lines)/np) - wcounts=[] - rrefs=[] - # spawn procs - for i=1:np - first=unitsize*(i-1)+1 - last=unitsize*i - if last>length(lines) - last=length(lines) - end - subtext=join(lines[Int(first):Int(last)],"\n") - push!(rrefs, @spawn wordcount( subtext ) ) - end - # fetch results - while length(rrefs)>0 - push!(wcounts,fetch(pop!(rrefs))) - end - # reduce - count=wcreduce(wcounts) - return count -end - -# Takes the name of a result file, and a list of input file names. -# Combines the contents of all files, then performs a parallel_wordcount -# on the resulting string. Writes the results to result_file. -function wordcount_files(result_file,inputs...) - text = "" - for file in inputs - text *= read(file, String) - end - wc = parallel_wordcount(text) - open(result_file,"w") do f - for (k,v) in wc - println(f, k,"=",v) - end - end -end diff --git a/stdlib/InteractiveUtils/src/InteractiveUtils.jl b/stdlib/InteractiveUtils/src/InteractiveUtils.jl index c507dbc412d2a..9d23cb9dabb8a 100644 --- a/stdlib/InteractiveUtils/src/InteractiveUtils.jl +++ b/stdlib/InteractiveUtils/src/InteractiveUtils.jl @@ -258,7 +258,7 @@ julia> subtypes(Integer) subtypes(x::Type) = _subtypes_in(Base.loaded_modules_array(), x) # dumptype is for displaying abstract type hierarchies, -# based on Jameson Nash's examples/typetree.jl +# based on Jameson Nash's typetree.jl in https://github.com/JuliaArchive/Examples function dumptype(io::IO, @nospecialize(x), n::Int, indent) print(io, x) n == 0 && return # too deeply nested diff --git a/test/choosetests.jl b/test/choosetests.jl index c3044693373bc..49584c8d2c7a1 100644 --- a/test/choosetests.jl +++ b/test/choosetests.jl @@ -57,10 +57,6 @@ function choosetests(choices = []) "reinterpretarray", "syntax", "logging", "missing", "asyncmap" ] - if isdir(joinpath(Sys.BINDIR, Base.DOCDIR, "examples")) - push!(testnames, "examples") - end - tests = [] skip_tests = [] exit_on_error = false diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index 92688887e02a3..f368d278a5d90 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -269,7 +269,7 @@ let exename = `$(Base.julia_cmd()) --sysimage-native-code=yes --startup-file=no` end # --worker takes default / custom as argument (default/custom arguments - # tested in test/parallel.jl, test/examples.jl) + # tested in test/parallel.jl) @test !success(`$exename --worker=true`) # test passing arguments From 1033f65e703ff2f78ae2c2876c32968ffaa89c8d Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Sat, 3 Mar 2018 17:38:02 -0500 Subject: [PATCH 22/28] fix docstring for code_llvm (#26266) * fix docstring for code_llvm --- stdlib/InteractiveUtils/src/codeview.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/InteractiveUtils/src/codeview.jl b/stdlib/InteractiveUtils/src/codeview.jl index 1c7555fc4f350..1983c95dc9366 100644 --- a/stdlib/InteractiveUtils/src/codeview.jl +++ b/stdlib/InteractiveUtils/src/codeview.jl @@ -116,7 +116,7 @@ end Prints the LLVM bitcodes generated for running the method matching the given generic function and type signature to `io`. -All metadata and dbg.* calls are removed from the printed bitcode. Use code_llvm_raw for the full IR. +All metadata and dbg.* calls are removed from the printed bitcode. Use `code_llvm_raw` for the full IR. """ code_llvm(io::IO, @nospecialize(f), @nospecialize(types=Tuple), strip_ir_metadata=true, dump_module=false) = print(io, _dump_function(f, types, false, false, strip_ir_metadata, dump_module)) From d02546a08646b347720c0eac1f004fb71abd8c05 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Sat, 3 Mar 2018 14:38:20 -0800 Subject: [PATCH 23/28] Add a missing "that" (#26313) --- doc/src/manual/interfaces.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/interfaces.md b/doc/src/manual/interfaces.md index 236641c254821..9dd11fe22ef4b 100644 --- a/doc/src/manual/interfaces.md +++ b/doc/src/manual/interfaces.md @@ -39,7 +39,7 @@ tests if there are any elements remaining, and `next(iter, state)`, which return the current element and an updated `state`. The `state` object can be anything, and is generally considered to be an implementation detail private to the iterable object. -Any object defines these three methods is iterable and can be used in the [many functions that rely upon iteration](@ref lib-collections-iteration). +Any object that defines these three methods is iterable and can be used in the [many functions that rely upon iteration](@ref lib-collections-iteration). It can also be used directly in a `for` loop since the syntax: ```julia From acb18983342732eabd9df6efd48172a5ca37c4cc Mon Sep 17 00:00:00 2001 From: StephenVavasis Date: Sat, 3 Mar 2018 17:49:59 -0500 Subject: [PATCH 24/28] FIx intro to manual chapter on types (#26312) The paragraph I edited in this chapter of the manual on types confused me when I was a Julia newbie, and I still find it confusing. How do type annotations simplify a program? Improve performance? I rewrote it to state the purpose of type annotations more accurately, --- doc/src/manual/types.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/src/manual/types.md b/doc/src/manual/types.md index c64215b7a9203..6fc06ca3f4bbb 100644 --- a/doc/src/manual/types.md +++ b/doc/src/manual/types.md @@ -16,10 +16,11 @@ of function arguments to be deeply integrated with the language. Method dispatch detail in [Methods](@ref), but is rooted in the type system presented here. The default behavior in Julia when types are omitted is to allow values to be of any type. Thus, -one can write many useful Julia programs without ever explicitly using types. When additional +one can write many useful Julia functions without ever explicitly using types. When additional expressiveness is needed, however, it is easy to gradually introduce explicit type annotations -into previously "untyped" code. Doing so will typically increase both the performance and robustness -of these systems, and perhaps somewhat counterintuitively, often significantly simplify them. +into previously "untyped" code. Adding annotations serves three primary purposes: to take advantage +of Julia's powerful multiple-dispatch mechanism, to improve human readability, and to catch +programmer errors. Describing Julia in the lingo of [type systems](https://en.wikipedia.org/wiki/Type_system), it is: dynamic, nominative and parametric. Generic types can be parameterized, and the hierarchical From 705fb65910e3189a35c92523ab90f73988fc95f8 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Sun, 4 Mar 2018 09:16:48 +0100 Subject: [PATCH 25/28] fix doctests, and make them less prone to errors (#26275) * fix all doctests, update stale documentation * update Documenter version --- base/abstractdict.jl | 16 +++--- base/array.jl | 46 ++++++----------- base/broadcast.jl | 4 +- base/dict.jl | 16 +++--- base/docs/basedocs.jl | 15 +++--- base/essentials.jl | 20 ++++---- base/floatfuncs.jl | 2 +- base/io.jl | 8 +-- base/iostream.jl | 8 +-- base/iterators.jl | 2 +- base/meta.jl | 2 +- base/missing.jl | 9 ++-- base/multidimensional.jl | 16 +++--- base/operators.jl | 1 - base/permuteddimsarray.jl | 8 +-- base/show.jl | 4 +- base/some.jl | 3 +- base/stat.jl | 2 +- base/strings/basic.jl | 7 ++- base/strings/search.jl | 4 +- base/strings/util.jl | 2 +- doc/REQUIRE | 4 +- doc/src/base/arrays.md | 4 +- doc/src/base/collections.md | 12 ++--- doc/src/base/io-network.md | 2 +- doc/src/devdocs/reflection.md | 34 +++++++------ doc/src/index.md | 4 +- doc/src/manual/arrays.md | 4 +- .../manual/complex-and-rational-numbers.md | 2 +- doc/src/manual/constructors.md | 17 ++++--- doc/src/manual/control-flow.md | 24 +++++---- doc/src/manual/conversion-and-promotion.md | 3 +- doc/src/manual/faq.md | 20 ++++---- doc/src/manual/functions.md | 9 ++-- doc/src/manual/index.md | 2 +- doc/src/manual/interfaces.md | 20 +++++--- doc/src/manual/mathematical-operations.md | 20 +++----- doc/src/manual/metaprogramming.md | 2 +- doc/src/manual/missing.md | 4 -- doc/src/manual/performance-tips.md | 9 ++-- doc/src/manual/running-external-programs.md | 50 ++++++++----------- doc/src/manual/strings.md | 21 ++++---- doc/src/manual/types.md | 16 ++---- doc/src/manual/variables-and-scoping.md | 14 +++--- stdlib/Dates/docs/src/index.md | 17 +++---- stdlib/Dates/src/rounding.jl | 4 +- .../InteractiveUtils/src/InteractiveUtils.jl | 2 +- .../IterativeEigensolvers/docs/src/index.md | 37 ++++++-------- .../src/IterativeEigensolvers.jl | 2 +- stdlib/LinearAlgebra/docs/src/index.md | 28 +++++++---- stdlib/LinearAlgebra/src/blas.jl | 16 +++--- stdlib/LinearAlgebra/src/bunchkaufman.jl | 14 +++--- stdlib/LinearAlgebra/src/cholesky.jl | 6 ++- stdlib/LinearAlgebra/src/dense.jl | 8 +-- stdlib/LinearAlgebra/src/eigen.jl | 12 ++++- stdlib/LinearAlgebra/src/lu.jl | 8 +-- stdlib/LinearAlgebra/src/qr.jl | 27 +++++++--- stdlib/LinearAlgebra/src/schur.jl | 36 +++++++++---- stdlib/LinearAlgebra/src/transpose.jl | 34 +++++++------ stdlib/Random/src/misc.jl | 8 +-- stdlib/Sockets/docs/src/index.md | 8 +++ stdlib/SparseArrays/docs/src/index.md | 2 +- stdlib/SparseArrays/src/sparsematrix.jl | 21 +++----- stdlib/Test/src/Test.jl | 11 ++-- stdlib/UUIDs/docs/src/index.md | 2 +- stdlib/UUIDs/src/UUIDs.jl | 6 +-- 66 files changed, 414 insertions(+), 387 deletions(-) diff --git a/base/abstractdict.jl b/base/abstractdict.jl index 3b538817809ff..d4233f95782d8 100644 --- a/base/abstractdict.jl +++ b/base/abstractdict.jl @@ -90,15 +90,15 @@ return the elements in the same order. # Examples ```jldoctest -julia> a = Dict('a'=>2, 'b'=>3) +julia> D = Dict('a'=>2, 'b'=>3) Dict{Char,Int64} with 2 entries: - 'b' => 3 'a' => 2 + 'b' => 3 -julia> collect(keys(a)) +julia> collect(keys(D)) 2-element Array{Char,1}: - 'b' 'a' + 'b' ``` """ keys(a::AbstractDict) = KeySet(a) @@ -115,15 +115,15 @@ return the elements in the same order. # Examples ```jldoctest -julia> a = Dict('a'=>2, 'b'=>3) +julia> D = Dict('a'=>2, 'b'=>3) Dict{Char,Int64} with 2 entries: - 'b' => 3 'a' => 2 + 'b' => 3 -julia> collect(values(a)) +julia> collect(values(D)) 2-element Array{Int64,1}: - 3 2 + 3 ``` """ values(a::AbstractDict) = ValueIterator(a) diff --git a/base/array.jl b/base/array.jl index 668beb348ddfd..16c23f862ecfb 100644 --- a/base/array.jl +++ b/base/array.jl @@ -1523,8 +1523,7 @@ julia> A = [false, false, true, false] julia> findnext(A, 1) 3 -julia> findnext(A, 4) == nothing -true +julia> findnext(A, 4) # returns nothing, but not printed in the REPL julia> A = [false false; true false] 2×2 Array{Bool,2}: @@ -1575,8 +1574,7 @@ julia> A = [false, false, true, false] julia> findfirst(A) 3 -julia> findfirst(falses(3)) == nothing -true +julia> findfirst(falses(3)) # returns nothing, but not printed in the REPL julia> A = [false false; true false] 2×2 Array{Bool,2}: @@ -1615,23 +1613,14 @@ and [`pairs(A)`](@ref). # Examples ```jldoctest -A = [1, 4, 2, 2] -4-element Array{Int64,1}: - 1 - 4 - 2 - 2 +julia> A = [1, 4, 2, 2]; julia> findnext(isodd, A, 1) 1 -julia> findnext(isodd, A, 2) == nothing -true +julia> findnext(isodd, A, 2) # returns nothing, but not printed in the REPL -julia> A = [1 4; 2 2] -2×2 Array{Int64,2}: - 1 4 - 2 2 +julia> A = [1 4; 2 2]; julia> findnext(isodd, A, CartesianIndex(1, 1)) CartesianIndex(1, 1) @@ -1670,8 +1659,7 @@ julia> A = [1, 4, 2, 2] julia> findfirst(iseven, A) 2 -julia> findfirst(x -> x>10, A) == nothing -true +julia> findfirst(x -> x>10, A) # returns nothing, but not printed in the REPL julia> findfirst(equalto(4), A) 2 @@ -1717,8 +1705,7 @@ julia> A = [false, false, true, true] julia> findprev(A, 3) 3 -julia> findprev(A, 1) == nothing -true +julia> findprev(A, 1) # returns nothing, but not printed in the REPL julia> A = [false false; true true] 2×2 Array{Bool,2}: @@ -1767,8 +1754,7 @@ julia> findlast(A) julia> A = falses(2,2); -julia> findlast(A) == nothing -true +julia> findlast(A) # returns nothing, but not printed in the REPL julia> A = [true false; true false] 2×2 Array{Bool,2}: @@ -1814,8 +1800,7 @@ julia> A = [4, 6, 1, 2] 1 2 -julia> findprev(isodd, A, 1) == nothing -true +julia> findprev(isodd, A, 1) # returns nothing, but not printed in the REPL julia> findprev(isodd, A, 3) 3 @@ -1859,8 +1844,7 @@ julia> A = [1, 2, 3, 4] julia> findlast(isodd, A) 3 -julia> findlast(x -> x > 5, A) == nothing -true +julia> findlast(x -> x > 5, A) # returns nothing, but not printed in the REPL julia> A = [1 2; 3 4] 2×2 Array{Int64,2}: @@ -1965,9 +1949,9 @@ julia> A = [true false; false true] false true julia> findall(A) -2-element Array{Int64,1}: - 1 - 4 +2-element Array{CartesianIndex{2},1}: + CartesianIndex(1, 1) + CartesianIndex(2, 2) julia> findall(falses(3)) 0-element Array{Int64,1} @@ -2137,9 +2121,9 @@ array contains `nothing` wherever `a` is not a member of `b`. # Examples ```jldoctest -julia> a = ['a', 'b', 'c', 'b', 'd', 'a'] +julia> a = ['a', 'b', 'c', 'b', 'd', 'a']; -julia> b = ['a', 'b', 'c'] +julia> b = ['a', 'b', 'c']; julia> indexin(a, b) 6-element Array{Union{Nothing, Int64},1}: diff --git a/base/broadcast.jl b/base/broadcast.jl index f2c550c65aba9..f3210fca4ae8d 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -700,7 +700,7 @@ would be the broadcast `inds`). The shape of the output is equal to the shape of element of `indsb`. # Examples -```jldoctest +```jldoctest bc_getindex julia> A = [11 12; 21 22] 2×2 Array{Int64,2}: 11 12 @@ -729,7 +729,7 @@ julia> broadcast_getindex(A, 1:2, 2:-1:1) Because the indices are all vectors, these calls are like `[A[i[k], j[k]] for k = 1:2]` where `i` and `j` are the two index vectors. -```jldoctest +```jldoctest bc_getindex julia> broadcast_getindex(A, 1:2, (1:2)') 2×2 Array{Int64,2}: 11 12 diff --git a/base/dict.jl b/base/dict.jl index b967e957baaf4..eacbbb2b0bf44 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -530,15 +530,15 @@ end Determine whether a collection has a mapping for a given key. ```jldoctest -julia> a = Dict('a'=>2, 'b'=>3) +julia> D = Dict('a'=>2, 'b'=>3) Dict{Char,Int64} with 2 entries: - 'b' => 3 'a' => 2 + 'b' => 3 -julia> haskey(a,'a') +julia> haskey(D, 'a') true -julia> haskey(a,'c') +julia> haskey(D, 'c') false ``` """ @@ -551,15 +551,15 @@ in(key, v::KeySet{<:Any, <:Dict}) = (ht_keyindex(v.dict, key) >= 0) Return the key matching argument `key` if one exists in `collection`, otherwise return `default`. ```jldoctest -julia> a = Dict('a'=>2, 'b'=>3) +julia> D = Dict('a'=>2, 'b'=>3) Dict{Char,Int64} with 2 entries: - 'b' => 3 'a' => 2 + 'b' => 3 -julia> getkey(a,'a',1) +julia> getkey(D, 'a', 1) 'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase) -julia> getkey(a,'d','a') +julia> getkey(D, 'd', 'a') 'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase) ``` """ diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 673a098d1c69a..454d8fd3dbf34 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -924,25 +924,28 @@ OutOfMemoryError An indexing operation into an array, `a`, tried to access an out-of-bounds element at index `i`. # Examples -```jldoctest +```jldoctest; filter = r"Stacktrace:(\\n \\[[0-9]+\\].*)*" julia> A = fill(1.0, 7); julia> A[8] ERROR: BoundsError: attempt to access 7-element Array{Float64,1} at index [8] Stacktrace: - [1] getindex(::Array{Float64,1}, ::Int64) at ./array.jl:758 + [1] getindex(::Array{Float64,1}, ::Int64) at ./array.jl:660 + [2] top-level scope julia> B = fill(1.0, (2,3)); julia> B[2, 4] ERROR: BoundsError: attempt to access 2×3 Array{Float64,2} at index [2, 4] Stacktrace: - [1] getindex(::Array{Float64,2}, ::Int64, ::Int64) at ./array.jl:759 + [1] getindex(::Array{Float64,2}, ::Int64, ::Int64) at ./array.jl:661 + [2] top-level scope julia> B[9] ERROR: BoundsError: attempt to access 2×3 Array{Float64,2} at index [9] Stacktrace: - [1] getindex(::Array{Float64,2}, ::Int64) at ./array.jl:758 + [1] getindex(::Array{Float64,2}, ::Int64) at ./array.jl:660 + [2] top-level scope ``` """ BoundsError @@ -955,9 +958,9 @@ Cannot exactly convert `val` to type `T` in a method of function `name`. # Examples ```jldoctest julia> convert(Float64, 1+2im) -ERROR: InexactError: convert(Float64, 1 + 2im) +ERROR: InexactError: Float64(Float64, 1 + 2im) Stacktrace: - [1] convert(::Type{Float64}, ::Complex{Int64}) at ./complex.jl:37 +[...] ``` """ InexactError diff --git a/base/essentials.jl b/base/essentials.jl index 6ead9541b318e..b05fb0f5cb9d4 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -84,9 +84,9 @@ julia> convert(Int, 3.0) 3 julia> convert(Int, 3.5) -ERROR: InexactError: convert(Int64, 3.5) +ERROR: InexactError: Int64(Int64, 3.5) Stacktrace: - [1] convert(::Type{Int64}, ::Float64) at ./float.jl:703 +[...] ``` If `T` is a [`AbstractFloat`](@ref) or [`Rational`](@ref) type, @@ -414,22 +414,24 @@ Annotates the expression `blk` as a bounds checking block, allowing it to be eli its caller in order for `@inbounds` to have effect. # Examples -```jldoctest +```jldoctest; filter = r"Stacktrace:(\\n \\[[0-9]+\\].*)*" julia> @inline function g(A, i) @boundscheck checkbounds(A, i) return "accessing (\$A)[\$i]" - end - f1() = return g(1:2, -1) - f2() = @inbounds return g(1:2, -1) -f2 (generic function with 1 method) + end; + +julia> f1() = return g(1:2, -1); + +julia> f2() = @inbounds return g(1:2, -1); julia> f1() ERROR: BoundsError: attempt to access 2-element UnitRange{Int64} at index [-1] Stacktrace: - [1] throw_boundserror(::UnitRange{Int64}, ::Tuple{Int64}) at ./abstractarray.jl:435 - [2] checkbounds at ./abstractarray.jl:399 [inlined] + [1] throw_boundserror(::UnitRange{Int64}, ::Tuple{Int64}) at ./abstractarray.jl:455 + [2] checkbounds at ./abstractarray.jl:420 [inlined] [3] g at ./none:2 [inlined] [4] f1() at ./none:1 + [5] top-level scope julia> f2() "accessing (1:2)[-1]" diff --git a/base/floatfuncs.jl b/base/floatfuncs.jl index 09c70c7fe27e5..249c4ee4204fd 100644 --- a/base/floatfuncs.jl +++ b/base/floatfuncs.jl @@ -90,7 +90,7 @@ julia> round(pi, 3, base = 2) rounded to 1.2. # Examples - ```jldoctest + ```jldoctest; setup = :(using Printf) julia> x = 1.15 1.15 diff --git a/base/io.jl b/base/io.jl index 6f1ed0b654b77..6fc3dde5f0209 100644 --- a/base/io.jl +++ b/base/io.jl @@ -315,9 +315,9 @@ julia> open("my_file.txt", "w") do io 57 julia> readuntil("my_file.txt", 'L') -"JuliaL" +"Julia" -julia> readuntil("my_file.txt", '.') +julia> readuntil("my_file.txt", '.', keep = true) "JuliaLang is a GitHub organization." julia> rm("my_file.txt") @@ -1003,7 +1003,7 @@ end with the EOL, matching the length returned by [`eachline`](@ref) and [`readl # Examples ```jldoctest -julia> io = IOBuffer("JuliaLang is a GitHub organization.\n"); +julia> io = IOBuffer("JuliaLang is a GitHub organization.\\n"); julia> countlines(io) 1 @@ -1014,7 +1014,7 @@ julia> countlines(io) 1 julia> countlines(io, eol = '.') -1 +0 ``` """ function countlines(io::IO; eol::Char='\n') diff --git a/base/iostream.jl b/base/iostream.jl index 611a8bc303b56..b8de905c101c9 100644 --- a/base/iostream.jl +++ b/base/iostream.jl @@ -48,7 +48,7 @@ iswritable(s::IOStream) = ccall(:ios_get_writable, Cint, (Ptr{Cvoid},), s.ios)!= isreadable(s::IOStream) = ccall(:ios_get_readable, Cint, (Ptr{Cvoid},), s.ios)!=0 """ - truncate(file,n) + truncate(file, n) Resize the file or buffer given by the first argument to exactly `n` bytes, filling previously unallocated space with '\\0' if the file or buffer is grown. @@ -73,7 +73,7 @@ julia> write(io, "JuliaLang is a GitHub organization."); julia> truncate(io, 40); julia> String(take!(io)) -"JuliaLang is a GitHub organization.\0\0\0\0\0" +"JuliaLang is a GitHub organization.\\0\\0\\0\\0\\0" ``` """ function truncate(s::IOStream, n::Integer) @@ -354,8 +354,8 @@ descriptor upon completion. # Examples ```jldoctest julia> open("myfile.txt", "w") do io - write(io, "Hello world!"); - end + write(io, "Hello world!") + end; julia> open(f->read(f, String), "myfile.txt") "Hello world!" diff --git a/base/iterators.jl b/base/iterators.jl index 817c699f26f9c..9ddec3c59f5db 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -376,7 +376,7 @@ See [`Base.filter`](@ref) for an eager implementation of filtering for arrays. # Examples ```jldoctest julia> f = Iterators.filter(isodd, [1, 2, 3, 4, 5]) -Base.Iterators.Filter{Base.#isodd,Array{Int64,1}}(isodd, [1, 2, 3, 4, 5]) +Base.Iterators.Filter{typeof(isodd),Array{Int64,1}}(isodd, [1, 2, 3, 4, 5]) julia> foreach(println, f) 1 diff --git a/base/meta.jl b/base/meta.jl index 36683fc569930..62b7b89a2dde9 100644 --- a/base/meta.jl +++ b/base/meta.jl @@ -152,7 +152,7 @@ julia> Meta.parse("x = ") :($(Expr(:incomplete, "incomplete: premature end of input"))) julia> Meta.parse("1.0.2") -ERROR: ParseError("invalid numeric constant \\\"1.0.\\\"") +ERROR: Base.Meta.ParseError("invalid numeric constant \\\"1.0.\\\"") Stacktrace: [...] diff --git a/base/missing.jl b/base/missing.jl index 7ca2c9373bbf1..95d40f3eea3ec 100644 --- a/base/missing.jl +++ b/base/missing.jl @@ -159,14 +159,13 @@ julia> sum(skipmissing([1, missing, 2])) julia> collect(skipmissing([1, missing, 2])) 2-element Array{Int64,1}: -1 -2 + 1 + 2 julia> collect(skipmissing([1 missing; 2 missing])) 2-element Array{Int64,1}: -1 -2 - + 1 + 2 ``` """ skipmissing(itr) = SkipMissing(itr) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 66c3e255adf48..130330f67bbe3 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -191,8 +191,8 @@ module IteratorsMD julia> CartesianIndices(fill(1, (2,3))) 2×3 CartesianIndices{2,Tuple{Base.OneTo{Int64},Base.OneTo{Int64}}}: - CartesianIndex(1, 1) CartesianIndex(1, 2) CartesianIndex(1, 3) - CartesianIndex(2, 1) CartesianIndex(2, 2) CartesianIndex(2, 3) + CartesianIndex(1, 1) CartesianIndex(1, 2) CartesianIndex(1, 3) + CartesianIndex(2, 1) CartesianIndex(2, 2) CartesianIndex(2, 3) ``` ## Conversion between linear and cartesian indices @@ -391,9 +391,9 @@ module IteratorsMD ```jldoctest subarray julia> linear = LinearIndices(1:3,1:2) LinearIndices{2,Tuple{UnitRange{Int64},UnitRange{Int64}}} with indices 1:3×1:2: - 1 4 - 2 5 - 3 6 + 1 4 + 2 5 + 3 6 julia> linear[1,2] 4 @@ -861,9 +861,9 @@ julia> cumprod(fill(1//2, 3)) julia> cumprod([fill(1//3, 2, 2) for i in 1:3]) 3-element Array{Array{Rational{Int64},2},1}: - Rational{Int64}[1//3 1//3; 1//3 1//3] - Rational{Int64}[2//9 2//9; 2//9 2//9] - Rational{Int64}[4//27 4//27; 4//27 4//27] + [1//3 1//3; 1//3 1//3] + [2//9 2//9; 2//9 2//9] + [4//27 4//27; 4//27 4//27] ``` """ cumprod(x::AbstractVector) = cumprod(x, dims=1) diff --git a/base/operators.jl b/base/operators.jl index d5e052a2dc76d..e918dcec16627 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -362,7 +362,6 @@ julia> cmp(2, 1) julia> cmp(2+im, 3-im) ERROR: MethodError: no method matching isless(::Complex{Int64}, ::Complex{Int64}) -Stacktrace: [...] ``` """ diff --git a/base/permuteddimsarray.jl b/base/permuteddimsarray.jl index 4a82f4670bf9d..de9c8c1944d7b 100644 --- a/base/permuteddimsarray.jl +++ b/base/permuteddimsarray.jl @@ -121,7 +121,7 @@ the matrix. Differs from `LinearAlgebra`'s [`transpose`](@ref) in that the operation is not recursive. # Examples -```jldoctest +```jldoctest; setup = :(using LinearAlgebra) julia> a = [1 2; 3 4]; julia> b = [5 6; 7 8]; @@ -141,7 +141,7 @@ julia> permutedims(X) [5 6; 7 8] [13 14; 15 16] julia> transpose(X) -2×2 LinearAlgebra.Transpose{LinearAlgebra.Transpose{Int64,Array{Int64,2}},Array{Array{Int64,2},2}}: +2×2 Transpose{Transpose{Int64,Array{Int64,2}},Array{Array{Int64,2},2}}: [1 3; 2 4] [9 11; 10 12] [5 7; 6 8] [13 15; 14 16] ``` @@ -156,7 +156,7 @@ Differs from `LinearAlgebra`'s [`transpose`](@ref) in that the operation is not recursive. # Examples -```jldoctest +```jldoctest; setup = :(using LinearAlgebra) julia> permutedims([1, 2, 3, 4]) 1×4 Array{Int64,2}: 1 2 3 4 @@ -171,7 +171,7 @@ julia> permutedims(V) [1 2; 3 4] [5 6; 7 8] julia> transpose(V) -1×2 LinearAlgebra.Transpose{LinearAlgebra.Transpose{Int64,Array{Int64,2}},Array{Array{Int64,2},1}}: +1×2 Transpose{Transpose{Int64,Array{Int64,2}},Array{Array{Int64,2},1}}: [1 3; 2 4] [5 7; 6 8] ``` """ diff --git a/base/show.jl b/base/show.jl index f8f83b7d9f25e..3ae04fe14b0fa 100644 --- a/base/show.jl +++ b/base/show.jl @@ -236,7 +236,7 @@ julia> io = IOBuffer(); julia> printstyled(IOContext(io, :color => true), "string", color=:red) julia> String(take!(io)) -"\e[31mstring\e[39m" +"\\e[31mstring\\e[39m" julia> printstyled(io, "string", color=:red) @@ -823,7 +823,7 @@ operators. Return `0` if `s` is not a valid operator. # Examples ```jldoctest julia> Base.operator_precedence(:+), Base.operator_precedence(:*), Base.operator_precedence(:.) -(9, 11, 15) +(11, 13, 17) julia> Base.operator_precedence(:sin), Base.operator_precedence(:+=), Base.operator_precedence(:(=)) # (Note the necessary parens on `:(=)`) (0, 1, 1) diff --git a/base/some.jl b/base/some.jl index 1c066bc5f0768..f75a493d91703 100644 --- a/base/some.jl +++ b/base/some.jl @@ -51,8 +51,7 @@ julia> coalesce(missing, 1) julia> coalesce(1, nothing) 1 -julia> coalesce(nothing, nothing) -nothing +julia> coalesce(nothing, nothing) # returns nothing, but not printed in the REPL julia> coalesce(Some(1)) 1 diff --git a/base/stat.jl b/base/stat.jl index fc1e3c399c7f2..1f5aca7921864 100644 --- a/base/stat.jl +++ b/base/stat.jl @@ -207,7 +207,7 @@ julia> f = open("test_file.txt", "w"); julia> isfile(f) true -julia> close(f) +julia> close(f); rm("test_file.txt") ``` """ isfile(st::StatStruct) = filemode(st) & 0xf000 == 0x8000 diff --git a/base/strings/basic.jl b/base/strings/basic.jl index 50091f5f11049..8b41bbff31be5 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -113,7 +113,7 @@ julia> isvalid(str, 2) false julia> str[2] -ERROR: StringIndexError: invalid character index +ERROR: StringIndexError("αβγdef", 2) Stacktrace: [...] ``` @@ -410,7 +410,10 @@ julia> prevind("αβγdef", 1) 0 julia> prevind("αβγdef", 0) --1 +ERROR: BoundsError: attempt to access "αβγdef" + at index [0] +Stacktrace: +[...] julia> prevind("αβγdef", 3, 2) 0 diff --git a/base/strings/search.jl b/base/strings/search.jl index 2b3c0633e07f3..72e434d1f96f6 100644 --- a/base/strings/search.jl +++ b/base/strings/search.jl @@ -244,8 +244,8 @@ julia> findnext("z", "Hello to the world", 1) julia> findnext("o", "Hello to the world", 6) 8:8 -julia> findnext("Julia", "JuliaLang", 2) -1:5 +julia> findnext("Lang", "JuliaLang", 2) +6:9 ``` """ findnext(t::AbstractString, s::AbstractString, i::Integer) = _search(s, t, i) diff --git a/base/strings/util.jl b/base/strings/util.jl index 397613e57f271..eff5dc9f36247 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -455,7 +455,7 @@ julia> hex2bytes(s) 0x39 julia> a = b"01abEF" -6-element Array{UInt8,1}: +6-element Base.CodeUnits{UInt8,String}: 0x30 0x31 0x61 diff --git a/doc/REQUIRE b/doc/REQUIRE index 144d91adbe044..8b6fd177b73f1 100644 --- a/doc/REQUIRE +++ b/doc/REQUIRE @@ -1,3 +1,3 @@ -Compat 0.54.0 0.54.0+ +Compat 0.56.0 0.56.0+ DocStringExtensions 0.4.3 0.4.3+ -Documenter 0.13.2 0.13.2+ +Documenter 0.14.0 0.14.0+ diff --git a/doc/src/base/arrays.md b/doc/src/base/arrays.md index 402ebab2d4da8..11b3c6dbb7b2d 100644 --- a/doc/src/base/arrays.md +++ b/doc/src/base/arrays.md @@ -138,7 +138,7 @@ Base.promote_shape ## Array functions ```@docs -Base.accumulate(::Any, ::Any, ::Integer) +Base.accumulate Base.accumulate! Base.cumprod Base.cumprod! @@ -149,8 +149,6 @@ Base.repeat Base.rot180 Base.rotl90 Base.rotr90 -Base.reducedim -Base.mapreducedim Base.mapslices ``` diff --git a/doc/src/base/collections.md b/doc/src/base/collections.md index 43ba36a803bf2..cdc77c296de43 100644 --- a/doc/src/base/collections.md +++ b/doc/src/base/collections.md @@ -88,20 +88,16 @@ Base.foldl(::Any, ::Any, ::Any) Base.foldl(::Any, ::Any) Base.foldr(::Any, ::Any, ::Any) Base.foldr(::Any, ::Any) -Base.maximum(::Any) -Base.maximum(::Any, ::Any) +Base.maximum Base.maximum! -Base.minimum(::Any) -Base.minimum(::Any, ::Any) +Base.minimum Base.minimum! Base.extrema(::Any) Base.extrema(::AbstractArray, ::Any) Base.argmax Base.argmin -Base.findmax(::Any) -Base.findmax(::AbstractArray, ::Any) -Base.findmin(::Any) -Base.findmin(::AbstractArray, ::Any) +Base.findmax +Base.findmin Base.findmax! Base.findmin! Base.sum diff --git a/doc/src/base/io-network.md b/doc/src/base/io-network.md index c99684c3bd698..9c0cf8161da23 100644 --- a/doc/src/base/io-network.md +++ b/doc/src/base/io-network.md @@ -94,7 +94,7 @@ Base.Multimedia.redisplay Base.Multimedia.displayable Base.show(::Any, ::Any, ::Any) Base.Multimedia.showable -Base.repr(::Any, ::Any) +Base.repr(::MIME, ::Any) ``` As mentioned above, one can also define new display backends. For example, a module that can display diff --git a/doc/src/devdocs/reflection.md b/doc/src/devdocs/reflection.md index d664ef0aeb92d..23ff13b919b1d 100644 --- a/doc/src/devdocs/reflection.md +++ b/doc/src/devdocs/reflection.md @@ -11,7 +11,7 @@ returns symbols for all bindings in `m`, regardless of export status. ## DataType fields The names of `DataType` fields may be interrogated using [`fieldnames`](@ref). For example, -given the following type, `fieldnames(Point)` returns an arrays of [`Symbol`](@ref) elements representing +given the following type, `fieldnames(Point)` returns a tuple of [`Symbol`](@ref)s representing the field names: ```jldoctest struct_point @@ -21,9 +21,7 @@ julia> struct Point end julia> fieldnames(Point) -2-element Array{Symbol,1}: - :x - :y +(:x, :y) ``` The type of each field in a `Point` object is stored in the `types` field of the `Point` variable @@ -52,9 +50,9 @@ of these fields is the `types` field observed in the example above. The *direct* subtypes of any `DataType` may be listed using [`subtypes`](@ref). For example, the abstract `DataType` [`AbstractFloat`](@ref) has four (concrete) subtypes: -```jldoctest +```jldoctest; setup = :(using InteractiveUtils) julia> subtypes(AbstractFloat) -4-element Array{Union{DataType, UnionAll},1}: +4-element Array{Any,1}: BigFloat Float16 Float32 @@ -83,9 +81,9 @@ the unquoted and interpolated expression (`Expr`) form for a given macro. To use `quote` the expression block itself (otherwise, the macro will be evaluated and the result will be passed instead!). For example: -```jldoctest +```jldoctest; setup = :(using InteractiveUtils) julia> macroexpand(@__MODULE__, :(@edit println("")) ) -:((Base.edit)(println, (Base.typesof)(""))) +:((InteractiveUtils.edit)(println, (Base.typesof)(""))) ``` The functions `Base.Meta.show_sexpr` and [`dump`](@ref) are used to display S-expr style views @@ -97,14 +95,18 @@ and variable assignments: ```jldoctest julia> Meta.lower(@__MODULE__, :(f() = 1) ) -:(begin - $(Expr(:method, :f)) - $(Expr(:method, :f, :((Core.svec)((Core.svec)((Core.Typeof)(f)), (Core.svec)())), CodeInfo(:(begin - #= none:1 =# - return 1 - end)), false)) - return f - end) +:($(Expr(:thunk, CodeInfo(:(begin + $(Expr(:method, :f)) + Core.SSAValue(0) = (Core.Typeof)(f) + Core.SSAValue(1) = (Core.svec)(Core.SSAValue(0)) + Core.SSAValue(2) = (Core.svec)() + Core.SSAValue(3) = (Core.svec)(Core.SSAValue(1), Core.SSAValue(2)) + $(Expr(:method, :f, Core.SSAValue(3), CodeInfo(:(begin + #= none:1 =# + return 1 + end)))) + return f + end))))) ``` ## Intermediate and compiled representations diff --git a/doc/src/index.md b/doc/src/index.md index f7e5765a4bfb7..dba35ba7a1b56 100644 --- a/doc/src/index.md +++ b/doc/src/index.md @@ -79,7 +79,7 @@ Please read the [release notes](NEWS.md) to see what has changed since the last * [Base64](@ref) * [CRC32c](@ref) * [SHA](@ref) - * [Dates](@ref stdlib-dates) + * [Dates](@ref) * [Delimited Files](@ref) * [Distributed Computing](@ref) * [File Events](@ref lib-filewatching) @@ -114,7 +114,7 @@ Please read the [release notes](NEWS.md) to see what has changed since the last * [printf() and stdio in the Julia runtime](@ref) * [Bounds checking](@ref) * [Proper maintenance and care of multi-threading locks](@ref) - * [Arrays with custom indices](@ref) + * [Arrays with custom indices](@ref man-custom-indices) * [Module loading](@ref) * [Inference](@ref) * Developing/debugging Julia's C code diff --git a/doc/src/manual/arrays.md b/doc/src/manual/arrays.md index 09ca6a3af90b1..28f2c51f17a45 100644 --- a/doc/src/manual/arrays.md +++ b/doc/src/manual/arrays.md @@ -661,8 +661,8 @@ it also handles tuples and treats any argument that is not an array, tuple or [` ```jldoctest julia> convert.(Float32, [1, 2]) 2-element Array{Float32,1}: - 1.0f0 - 2.0f0 + 1.0 + 2.0 julia> ceil.((UInt8,), [1.2 3.4; 5.6 6.7]) 2×2 Array{UInt8,2}: diff --git a/doc/src/manual/complex-and-rational-numbers.md b/doc/src/manual/complex-and-rational-numbers.md index ebb7a0617f429..9f49aa0901139 100644 --- a/doc/src/manual/complex-and-rational-numbers.md +++ b/doc/src/manual/complex-and-rational-numbers.md @@ -37,7 +37,7 @@ julia> (-1 + 2im)^2 -3 - 4im julia> (-1 + 2im)^2.5 -2.7296244647840084 - 6.960664459571898im +2.729624464784009 - 6.9606644595719im julia> (-1 + 2im)^(1 + 1im) -0.27910381075826657 + 0.08708053414102428im diff --git a/doc/src/manual/constructors.md b/doc/src/manual/constructors.md index 153d6e35f8938..8ee79ea5ceaa9 100644 --- a/doc/src/manual/constructors.md +++ b/doc/src/manual/constructors.md @@ -97,14 +97,16 @@ julia> struct OrderedPair Now `OrderedPair` objects can only be constructed such that `x <= y`: -```jldoctest pairtype +```jldoctest pairtype; filter = r"Stacktrace:(\n \[[0-9]+\].*)*" julia> OrderedPair(1, 2) OrderedPair(1, 2) julia> OrderedPair(2,1) ERROR: out of order Stacktrace: - [1] OrderedPair(::Int64, ::Int64) at ./none:4 + [1] error at ./error.jl:33 [inlined] + [2] OrderedPair(::Int64, ::Int64) at ./none:4 + [3] top-level scope ``` If the type were declared `mutable`, you could reach in and directly change the field values to @@ -277,7 +279,7 @@ that, by default, instances of parametric composite types can be constructed eit given type parameters or with type parameters implied by the types of the arguments given to the constructor. Here are some examples: -```jldoctest parametric +```jldoctest parametric; filter = r"Closest candidates.*\n .*" julia> struct Point{T<:Real} x::T y::T @@ -292,16 +294,15 @@ Point{Float64}(1.0, 2.5) julia> Point(1,2.5) ## implicit T ## ERROR: MethodError: no method matching Point(::Int64, ::Float64) Closest candidates are: - Point(::T<:Real, !Matched::T<:Real) where T<:Real at none:2 + Point(::T<:Real, ::T<:Real) where T<:Real at none:2 julia> Point{Int64}(1, 2) ## explicit T ## Point{Int64}(1, 2) julia> Point{Int64}(1.0,2.5) ## explicit T ## -ERROR: InexactError: convert(Int64, 2.5) +ERROR: InexactError: Int64(Int64, 2.5) Stacktrace: - [1] convert at ./float.jl:703 [inlined] - [2] Point{Int64}(::Float64, ::Float64) at ./none:2 +[...] julia> Point{Float64}(1.0, 2.5) ## explicit T ## Point{Float64}(1.0, 2.5) @@ -502,7 +503,7 @@ julia> typeof(z) <: Complex{OurRational} false ``` -Thus, although the [`⊘`](@ref) operator usually returns an instance of `OurRational`, if either +Thus, although the `⊘` operator usually returns an instance of `OurRational`, if either of its arguments are complex integers, it will return an instance of `Complex{OurRational}` instead. The interested reader should consider perusing the rest of [`rational.jl`](https://github.com/JuliaLang/julia/blob/master/base/rational.jl): it is short, self-contained, and implements an entire basic Julia type. diff --git a/doc/src/manual/control-flow.md b/doc/src/manual/control-flow.md index 18dd9828087cb..5d38a7f4fdfa1 100644 --- a/doc/src/manual/control-flow.md +++ b/doc/src/manual/control-flow.md @@ -124,7 +124,7 @@ The variable `relation` is declared inside the `if` block, but used outside. How on this behavior, make sure all possible code paths define a value for the variable. The following change to the above function results in a runtime error -```jldoctest +```jldoctest; filter = r"Stacktrace:(\n \[[0-9]+\].*)*" julia> function test(x,y) if x < y relation = "less than" @@ -315,7 +315,7 @@ one can write ` || ` (which could be read as: *or else* For example, a recursive factorial routine could be defined like this: -```jldoctest +```jldoctest; filter = r"Stacktrace:(\n \[[0-9]+\].*)*" julia> function fact(n::Int) n >= 0 || error("n must be non-negative") n == 0 && return 1 @@ -332,7 +332,9 @@ julia> fact(0) julia> fact(-1) ERROR: n must be non-negative Stacktrace: - [1] fact(::Int64) at ./none:2 + [1] error at ./error.jl:33 [inlined] + [2] fact(::Int64) at ./none:2 + [3] top-level scope ``` Boolean operations *without* short-circuit evaluation can be done with the bitwise boolean operators @@ -589,7 +591,7 @@ Exceptions can be created explicitly with [`throw`](@ref). For example, a functi for nonnegative numbers could be written to [`throw`](@ref) a [`DomainError`](@ref) if the argument is negative: -```jldoctest +```jldoctest; filter = r"Stacktrace:(\n \[[0-9]+\].*)*" julia> f(x) = x>=0 ? exp(-x) : throw(DomainError(x, "argument must be nonnegative")) f (generic function with 1 method) @@ -652,7 +654,7 @@ Suppose we want to stop execution immediately if the square root of a negative n To do this, we can define a fussy version of the [`sqrt`](@ref) function that raises an error if its argument is negative: -```jldoctest fussy_sqrt +```jldoctest fussy_sqrt; filter = r"Stacktrace:(\n \[[0-9]+\].*)*" julia> fussy_sqrt(x) = x >= 0 ? sqrt(x) : error("negative x not allowed") fussy_sqrt (generic function with 1 method) @@ -662,14 +664,16 @@ julia> fussy_sqrt(2) julia> fussy_sqrt(-1) ERROR: negative x not allowed Stacktrace: - [1] fussy_sqrt(::Int64) at ./none:1 + [1] error at ./error.jl:33 [inlined] + [2] fussy_sqrt(::Int64) at ./none:1 + [3] top-level scope ``` If `fussy_sqrt` is called with a negative value from another function, instead of trying to continue execution of the calling function, it returns immediately, displaying the error message in the interactive session: -```jldoctest fussy_sqrt +```jldoctest fussy_sqrt; filter = r"Stacktrace:(\n \[[0-9]+\].*)*" julia> function verbose_fussy_sqrt(x) println("before fussy_sqrt") r = fussy_sqrt(x) @@ -687,8 +691,10 @@ julia> verbose_fussy_sqrt(-1) before fussy_sqrt ERROR: negative x not allowed Stacktrace: - [1] fussy_sqrt at ./none:1 [inlined] - [2] verbose_fussy_sqrt(::Int64) at ./none:3 + [1] error at ./error.jl:33 [inlined] + [2] fussy_sqrt at ./none:1 [inlined] + [3] verbose_fussy_sqrt(::Int64) at ./none:3 + [4] top-level scope ``` ### The `try/catch` statement diff --git a/doc/src/manual/conversion-and-promotion.md b/doc/src/manual/conversion-and-promotion.md index b824c97b6b015..7345334714953 100644 --- a/doc/src/manual/conversion-and-promotion.md +++ b/doc/src/manual/conversion-and-promotion.md @@ -88,7 +88,8 @@ doesn't know how to perform the requested conversion: ```jldoctest julia> convert(AbstractFloat, "foo") -ERROR: MethodError: Cannot `convert` an object of type String to an object of type AbstractFloat. +ERROR: MethodError: Cannot `convert` an object of type String to an object of type AbstractFloat +[...] ``` Some languages consider parsing strings as numbers or formatting numbers as strings to be conversions diff --git a/doc/src/manual/faq.md b/doc/src/manual/faq.md index fe8ca94e66d2a..da681180598be 100644 --- a/doc/src/manual/faq.md +++ b/doc/src/manual/faq.md @@ -147,18 +147,18 @@ argument is called slurping: ```jldoctest julia> function printargs(args...) - @printf("%s\n", typeof(args)) + println(typeof(args)) for (i, arg) in enumerate(args) - @printf("Arg %d = %s\n", i, arg) + println("Arg #$i = $arg") end end printargs (generic function with 1 method) julia> printargs(1, 2, 3) Tuple{Int64,Int64,Int64} -Arg 1 = 1 -Arg 2 = 2 -Arg 3 = 3 +Arg #1 = 1 +Arg #2 = 2 +Arg #3 = 3 ``` If Julia were a language that made more liberal use of ASCII characters, the slurping operator @@ -173,19 +173,19 @@ call. This use of `...` is called splatting: ```jldoctest julia> function threeargs(a, b, c) - @printf("a = %s::%s\n", a, typeof(a)) - @printf("b = %s::%s\n", b, typeof(b)) - @printf("c = %s::%s\n", c, typeof(c)) + println("a = $a::$(typeof(a))") + println("b = $b::$(typeof(b))") + println("c = $c::$(typeof(c))") end threeargs (generic function with 1 method) -julia> vec = [1, 2, 3] +julia> x = [1, 2, 3] 3-element Array{Int64,1}: 1 2 3 -julia> threeargs(vec...) +julia> threeargs(x...) a = 1::Int64 b = 2::Int64 c = 3::Int64 diff --git a/doc/src/manual/functions.md b/doc/src/manual/functions.md index db16602cca700..5779954cb6050 100644 --- a/doc/src/manual/functions.md +++ b/doc/src/manual/functions.md @@ -129,9 +129,12 @@ A return type can also be specified in the function declaration using the `::` o the return value to the specified type. ```jldoctest -function g(x,y)::Int8 - return x * y -end +julia> function g(x, y)::Int8 + return x * y + end; + +julia> typeof(g(1, 2)) +Int8 ``` This function will always return an `Int8` regardless of the types of `x` and `y`. diff --git a/doc/src/manual/index.md b/doc/src/manual/index.md index 5d776d5dbf22e..148d5e021ea54 100644 --- a/doc/src/manual/index.md +++ b/doc/src/manual/index.md @@ -22,7 +22,7 @@ * [Missing Values](@ref missing) * [Networking and Streams](@ref) * [Parallel Computing](@ref) - * [Date and DateTime](@ref) + * [Dates](@ref) * [Running External Programs](@ref) * [Calling C and Fortran Code](@ref) * [Handling Operating System Variation](@ref) diff --git a/doc/src/manual/interfaces.md b/doc/src/manual/interfaces.md index 9dd11fe22ef4b..2349da948f253 100644 --- a/doc/src/manual/interfaces.md +++ b/doc/src/manual/interfaces.md @@ -189,6 +189,7 @@ valid index. It is recommended to also define [`firstindex`](@ref) to specify th ```jldoctest squaretype julia> Base.firstindex(S::Squares) = 1 + julia> Base.lastindex(S::Squares) = length(S) julia> Squares(23)[end] @@ -400,7 +401,8 @@ julia> mean(A) If you are defining an array type that allows non-traditional indexing (indices that start at something other than 1), you should specialize `indices`. You should also specialize [`similar`](@ref) so that the `dims` argument (ordinarily a `Dims` size-tuple) can accept `AbstractUnitRange` objects, -perhaps range-types `Ind` of your own design. For more information, see [Arrays with custom indices](@ref). +perhaps range-types `Ind` of your own design. For more information, see +[Arrays with custom indices](@ref man-custom-indices). ## [Strided Arrays](@id man-interface-strided-arrays) @@ -505,7 +507,7 @@ However, if needed you can specialize on any or all of these arguments. For a complete example, let's say you have created a type, `ArrayAndChar`, that stores an array and a single character: -```jldoctest +```jldoctest ArrayAndChar struct ArrayAndChar{T,N} <: AbstractArray{T,N} data::Array{T,N} char::Char @@ -514,16 +516,20 @@ Base.size(A::ArrayAndChar) = size(A.data) Base.getindex(A::ArrayAndChar{T,N}, inds::Vararg{Int,N}) where {T,N} = A.data[inds...] Base.setindex!(A::ArrayAndChar{T,N}, val, inds::Vararg{Int,N}) where {T,N} = A.data[inds...] = val Base.showarg(io::IO, A::ArrayAndChar, toplevel) = print(io, typeof(A), " with char '", A.char, "'") +# output + ``` You might want broadcasting to preserve the `char` "metadata." First we define -```jldoctest +```jldoctest ArrayAndChar Base.BroadcastStyle(::Type{<:ArrayAndChar}) = Broadcast.ArrayStyle{ArrayAndChar}() +# output + ``` This forces us to also define a `broadcast_similar` method: -```jldoctest +```jldoctest ArrayAndChar; filter = r"(^find_aac \(generic function with 2 methods\)$|^$)" function Base.broadcast_similar(f, ::Broadcast.ArrayStyle{ArrayAndChar}, ::Type{ElType}, inds, As...) where ElType # Scan the inputs for the ArrayAndChar: A = find_aac(As...) @@ -533,11 +539,13 @@ end "`A = find_aac(As...)` returns the first ArrayAndChar among the arguments." find_aac(A::ArrayAndChar, B...) = A -find_aac(A, B...) = find_aac(B...) +find_aac(A, B...) = find_aac(B...); +# output + ``` From these definitions, one obtains the following behavior: -```jldoctest +```jldoctest ArrayAndChar julia> a = ArrayAndChar([1 2; 3 4], 'x') 2×2 ArrayAndChar{Int64,2} with char 'x': 1 2 diff --git a/doc/src/manual/mathematical-operations.md b/doc/src/manual/mathematical-operations.md index b539efbe3d0e5..f33449c9678db 100644 --- a/doc/src/manual/mathematical-operations.md +++ b/doc/src/manual/mathematical-operations.md @@ -380,7 +380,7 @@ You can also find the numerical precedence for any given operator via the built- ```jldoctest julia> Base.operator_precedence(:+), Base.operator_precedence(:*), Base.operator_precedence(:.) -(9, 11, 15) +(11, 13, 17) julia> Base.operator_precedence(:sin), Base.operator_precedence(:+=), Base.operator_precedence(:(=)) # (Note the necessary parens on `:(=)`) (0, 1, 1) @@ -424,25 +424,20 @@ julia> Int8(127) julia> Int8(128) ERROR: InexactError: trunc(Int8, 128) Stacktrace: - [1] throw_inexacterror(::Symbol, ::Type{Int8}, ::Int64) at ./int.jl:34 - [2] checked_trunc_sint at ./int.jl:438 [inlined] - [3] convert at ./int.jl:458 [inlined] - [4] Int8(::Int64) at ./sysimg.jl:114 +[...] julia> Int8(127.0) 127 julia> Int8(3.14) -ERROR: InexactError: convert(Int8, 3.14) +ERROR: InexactError: Int8(Int8, 3.14) Stacktrace: - [1] convert at ./float.jl:682 [inlined] - [2] Int8(::Float64) at ./sysimg.jl:114 +[...] julia> Int8(128.0) -ERROR: InexactError: convert(Int8, 128.0) +ERROR: InexactError: Int8(Int8, 128.0) Stacktrace: - [1] convert at ./float.jl:682 [inlined] - [2] Int8(::Float64) at ./sysimg.jl:114 +[...] julia> 127 % Int8 127 @@ -456,8 +451,7 @@ julia> round(Int8,127.4) julia> round(Int8,127.6) ERROR: InexactError: trunc(Int8, 128.0) Stacktrace: - [1] trunc at ./float.jl:675 [inlined] - [2] round(::Type{Int8}, ::Float64) at ./float.jl:353 +[...] ``` See [Conversion and Promotion](@ref conversion-and-promotion) for how to define your own conversions and promotions. diff --git a/doc/src/manual/metaprogramming.md b/doc/src/manual/metaprogramming.md index 2ac0c0c829e8e..901076ca9cee4 100644 --- a/doc/src/manual/metaprogramming.md +++ b/doc/src/manual/metaprogramming.md @@ -216,7 +216,7 @@ Interpolating into an unquoted expression is not supported and will cause a comp ```jldoctest interp1 julia> $a + b -ERROR: unsupported or misplaced expression $ +ERROR: syntax: "$" expression outside quote ``` In this example, the tuple `(1,2,3)` is interpolated as an expression into a conditional test: diff --git a/doc/src/manual/missing.md b/doc/src/manual/missing.md index 89ccb7fd0fa25..4467f587da162 100644 --- a/doc/src/manual/missing.md +++ b/doc/src/manual/missing.md @@ -276,10 +276,6 @@ julia> y = Union{Missing, String}[missing, "b"] julia> convert(Array{String}, y) ERROR: MethodError: Cannot `convert` an object of type Missing to an object of type String -This may have arisen from a call to the constructor String(...), -since type constructors fall back to convert methods. -Stacktrace: -[... ``` ## Skipping Missing Values diff --git a/doc/src/manual/performance-tips.md b/doc/src/manual/performance-tips.md index a832506733236..84dd79caf4b69 100644 --- a/doc/src/manual/performance-tips.md +++ b/doc/src/manual/performance-tips.md @@ -453,10 +453,7 @@ MyBetterContainer{Float64,UnitRange{Float64}} julia> b = MyBetterContainer{Int64, UnitRange{Float64}}(UnitRange(1.3, 5.0)); ERROR: MethodError: Cannot `convert` an object of type UnitRange{Float64} to an object of type MyBetterContainer{Int64,UnitRange{Float64}} -This may have arisen from a call to the constructor MyBetterContainer{Int64,UnitRange{Float64}}(...), -since type constructors fall back to convert methods. -Stacktrace: - [1] MyBetterContainer{Int64,UnitRange{Float64}}(::UnitRange{Float64}) at ./sysimg.jl:114 +[...] ``` The inner constructor requires that the element type of `A` be `T`. @@ -621,7 +618,7 @@ end ```jldoctest julia> function strange_twos(n) - a = Vector{rand(Bool) ? Int64 : Float64}(n) + a = Vector{rand(Bool) ? Int64 : Float64}(uninitialized, n) for i = 1:n a[i] = 2 end @@ -640,7 +637,7 @@ This should be written as: ```jldoctest julia> function fill_twos!(a) - for i=eachindex(a) + for i = eachindex(a) a[i] = 2 end end diff --git a/doc/src/manual/running-external-programs.md b/doc/src/manual/running-external-programs.md index 88fc04405e43c..749d88b75f2cf 100644 --- a/doc/src/manual/running-external-programs.md +++ b/doc/src/manual/running-external-programs.md @@ -29,7 +29,7 @@ julia> mycommand = `echo hello` julia> typeof(mycommand) Cmd -julia> run(mycommand) +julia> run(mycommand); hello ``` @@ -209,7 +209,7 @@ values. Let's try the above two examples in Julia: julia> A = `perl -le '$|=1; for (0..3) { print }'` `perl -le '$|=1; for (0..3) { print }'` -julia> run(A) +julia> run(A); 0 1 2 @@ -220,7 +220,7 @@ julia> first = "A"; second = "B"; julia> B = `perl -le 'print for @ARGV' "1: $first" "2: $second"` `perl -le 'print for @ARGV' '1: A' '2: B'` -julia> run(B) +julia> run(B); 1: A 2: B ``` @@ -236,10 +236,10 @@ easily and safely just examine its interpretation without doing any damage. Shell metacharacters, such as `|`, `&`, and `>`, need to be quoted (or escaped) inside of Julia's backticks: ```jldoctest -julia> run(`echo hello '|' sort`) +julia> run(`echo hello '|' sort`); hello | sort -julia> run(`echo hello \| sort`) +julia> run(`echo hello \| sort`); hello | sort ``` @@ -248,7 +248,7 @@ The result is that a single line is printed: `hello | sort`. How, then, does one pipeline? Instead of using `'|'` inside of backticks, one uses [`pipeline`](@ref): ```jldoctest -julia> run(pipeline(`echo hello`, `sort`)) +julia> run(pipeline(`echo hello`, `sort`)); hello ``` @@ -273,8 +273,8 @@ that shells cannot. Julia can run multiple commands in parallel: -```julia-repl -julia> run(`echo hello` & `echo world`) +```jldoctest; filter = r"(world\nhello|hello\nworld)" +julia> run(`echo hello` & `echo world`); world hello ``` @@ -285,7 +285,7 @@ share with each other and the `julia` parent process. Julia lets you pipe the ou of these processes to another program: ```jldoctest -julia> run(pipeline(`echo world` & `echo hello`, `sort`)) +julia> run(pipeline(`echo world` & `echo hello`, `sort`)); hello world ``` @@ -326,24 +326,20 @@ setup of pipes between processes is a powerful one. To give some sense of the co that can be created easily, here are some more sophisticated examples, with apologies for the excessive use of Perl one-liners: -```julia-repl +```jldoctest prefixer; filter = r"([A-B] [0-5])" julia> prefixer(prefix, sleep) = `perl -nle '$|=1; print "'$prefix' ", $_; sleep '$sleep';'`; -julia> run(pipeline(`perl -le '$|=1; for(0..9){ print; sleep 1 }'`, prefixer("A",2) & prefixer("B",2))) -A 0 -B 1 -A 2 -B 3 -A 4 -B 5 -A 6 -B 7 -A 8 -B 9 +julia> run(pipeline(`perl -le '$|=1; for(0..5){ print; sleep 1 }'`, prefixer("A",2) & prefixer("B",2))); +B 0 +A 1 +B 2 +A 3 +B 4 +A 5 ``` This is a classic example of a single producer feeding two concurrent consumers: one `perl` process -generates lines with the numbers 0 through 9 on them, while two parallel processes consume that +generates lines with the numbers 0 through 5 on them, while two parallel processes consume that output, one prefixing lines with the letter "A", the other with the letter "B". Which consumer gets the first line is non-deterministic, but once that race has been won, the lines are consumed alternately by one process and then the other. (Setting `$|=1` in Perl causes each print statement @@ -352,20 +348,16 @@ the output is buffered and printed to the pipe at once, to be read by just one c Here is an even more complex multi-stage producer-consumer example: -```julia-repl -julia> run(pipeline(`perl -le '$|=1; for(0..9){ print; sleep 1 }'`, +```jldoctest prefixer; filter = r"[A-B] [X-Z] [0-5]" +julia> run(pipeline(`perl -le '$|=1; for(0..5){ print; sleep 1 }'`, prefixer("X",3) & prefixer("Y",3) & prefixer("Z",3), - prefixer("A",2) & prefixer("B",2))) + prefixer("A",2) & prefixer("B",2))); A X 0 B Y 1 A Z 2 B X 3 A Y 4 B Z 5 -A X 6 -B Y 7 -A Z 8 -B X 9 ``` This example is similar to the previous one, except there are two stages of consumers, and the diff --git a/doc/src/manual/strings.md b/doc/src/manual/strings.md index dcfd739dbc3ae..50020168e3ccd 100644 --- a/doc/src/manual/strings.md +++ b/doc/src/manual/strings.md @@ -78,7 +78,7 @@ is a valid code point, use the [`isvalid`](@ref) function: ```jldoctest julia> Char(0x110000) -'\U110000': Unicode U+110000 (category Cn: Other, not assigned) +'\U110000': Unicode U+110000 (category In: Invalid, too high) julia> isvalid(Char, 0x110000) false @@ -129,9 +129,6 @@ julia> Int('\x7f') julia> Int('\177') 127 - -julia> Int('\xff') -255 ``` You can do comparisons and a limited amount of arithmetic with `Char` values: @@ -275,11 +272,12 @@ julia> s[1] '∀': Unicode U+2200 (category Sm: Symbol, math) julia> s[2] -ERROR: UnicodeError: invalid character index +ERROR: StringIndexError("∀ x ∃ y", 2) [...] julia> s[3] -ERROR: UnicodeError: invalid character index +ERROR: StringIndexError("∀ x ∃ y", 3) +Stacktrace: [...] julia> s[4] @@ -297,7 +295,8 @@ julia> s[1:1] "∀" julia> s[1:2] -ERROR: UnicodeError: invalid character index +ERROR: StringIndexError("∀ x ∃ y", 2) +Stacktrace: [...] julia> s[1:4] @@ -312,7 +311,7 @@ since each character in a string must have its own index. The following is an in verbose way to iterate through the characters of `s`: ```jldoctest unicodestring -julia> for i = begindex(s):lastindex(s) +julia> for i = firstindex(s):lastindex(s) try println(s[i]) catch @@ -824,7 +823,7 @@ produce arrays of bytes. Here is an example using all three: ```jldoctest julia> b"DATA\xff\u2200" -8-element Array{UInt8,1}: +8-element Base.CodeUnits{UInt8,String}: 0x44 0x41 0x54 @@ -851,11 +850,11 @@ is encoded as two bytes in UTF-8: ```jldoctest julia> b"\xff" -1-element Array{UInt8,1}: +1-element Base.CodeUnits{UInt8,String}: 0xff julia> b"\uff" -2-element Array{UInt8,1}: +2-element Base.CodeUnits{UInt8,String}: 0xc3 0xbf ``` diff --git a/doc/src/manual/types.md b/doc/src/manual/types.md index 6fc06ca3f4bbb..3260b396a2780 100644 --- a/doc/src/manual/types.md +++ b/doc/src/manual/types.md @@ -344,20 +344,16 @@ must be convertible to `Int`: ```jldoctest footype julia> Foo((), 23.5, 1) -ERROR: InexactError: convert(Int64, 23.5) +ERROR: InexactError: Int64(Int64, 23.5) Stacktrace: - [1] convert at ./float.jl:703 [inlined] - [2] Foo(::Tuple{}, ::Float64, ::Int64) at ./none:2 +[...] ``` You may find a list of field names using the `fieldnames` function. ```jldoctest footype julia> fieldnames(Foo) -3-element Array{Symbol,1}: - :bar - :baz - :qux +(:bar, :baz, :qux) ``` You can access the field values of a composite object using the traditional `foo.bar` notation: @@ -649,13 +645,11 @@ For the default constructor, exactly one argument must be supplied for each fiel ```jldoctest pointtype julia> Point{Float64}(1.0) ERROR: MethodError: Cannot `convert` an object of type Float64 to an object of type Point{Float64} -This may have arisen from a call to the constructor Point{Float64}(...), -since type constructors fall back to convert methods. -Stacktrace: - [1] Point{Float64}(::Float64) at ./sysimg.jl:114 +[...] julia> Point{Float64}(1.0,2.0,3.0) ERROR: MethodError: no method matching Point{Float64}(::Float64, ::Float64, ::Float64) +[...] ``` Only one default constructor is generated for parametric types, since overriding it is not possible. diff --git a/doc/src/manual/variables-and-scoping.md b/doc/src/manual/variables-and-scoping.md index 4fc5ba1ee0b1f..088aafdb19eb9 100644 --- a/doc/src/manual/variables-and-scoping.md +++ b/doc/src/manual/variables-and-scoping.md @@ -251,15 +251,15 @@ which have a private state, for instance the ``state`` variable in the following example: ```jldoctest - julia> let state = 0 - global counter() = (state += 1) - end; +julia> let state = 0 + global counter() = (state += 1) + end; - julia> counter() - 1 +julia> counter() +1 - julia> counter() - 2 +julia> counter() +2 ``` See also the closures in the examples in the next two sections. diff --git a/stdlib/Dates/docs/src/index.md b/stdlib/Dates/docs/src/index.md index 2b3adef744b08..3a434cc11b731 100644 --- a/stdlib/Dates/docs/src/index.md +++ b/stdlib/Dates/docs/src/index.md @@ -144,14 +144,14 @@ julia> dt2 = Date(2000,2,1) julia> dump(dt) Date - instant: Dates.UTInstant{Dates.Day} - periods: Dates.Day + instant: Dates.UTInstant{Day} + periods: Day value: Int64 734562 julia> dump(dt2) Date - instant: Dates.UTInstant{Dates.Day} - periods: Dates.Day + instant: Dates.UTInstant{Day} + periods: Day value: Int64 730151 julia> dt > dt2 @@ -170,7 +170,6 @@ ERROR: MethodError: no method matching *(::Date, ::Date) julia> dt / dt2 ERROR: MethodError: no method matching /(::Date, ::Date) -[...] julia> dt - dt2 4411 days @@ -240,12 +239,12 @@ One may also access the underlying `UTInstant` or integer value: ```jldoctest tdate julia> dump(t) Date - instant: Dates.UTInstant{Dates.Day} - periods: Dates.Day + instant: Dates.UTInstant{Day} + periods: Day value: Int64 735264 julia> t.instant -Dates.UTInstant{Dates.Day}(735264 days) +Dates.UTInstant{Day}(735264 days) julia> Dates.value(t) 735264 @@ -559,7 +558,7 @@ julia> round(DateTime(2016, 8, 6, 20, 15), Dates.Day) Unlike the numeric [`round`](@ref) method, which breaks ties toward the even number by default, the [`TimeType`](@ref)[`round`](@ref) method uses the `RoundNearestTiesUp` rounding mode. (It's difficult to guess what breaking ties to nearest "even" [`TimeType`](@ref) would entail.) Further -details on the available `RoundingMode` s can be found in the [API reference](@ref stdlib-dates). +details on the available `RoundingMode` s can be found in the [API reference](@ref stdlib-dates-api). Rounding should generally behave as expected, but there are a few cases in which the expected behaviour is not obvious. diff --git a/stdlib/Dates/src/rounding.jl b/stdlib/Dates/src/rounding.jl index f575f71e9760a..fdd2f7658f555 100644 --- a/stdlib/Dates/src/rounding.jl +++ b/stdlib/Dates/src/rounding.jl @@ -170,7 +170,7 @@ julia> ceil(Dates.Minute(44), Dates.Minute(15)) 45 minutes julia> ceil(Dates.Hour(36), Dates.Day) -3 days +2 days ``` Rounding to a `precision` of `Month`s or `Year`s is not supported, as these `Period`s are of @@ -250,7 +250,7 @@ julia> round(Dates.Minute(44), Dates.Minute(15)) 45 minutes julia> round(Dates.Hour(36), Dates.Day) -3 days +2 days ``` Valid rounding modes for `round(::Period, ::T, ::RoundingMode)` are `RoundNearestTiesUp` diff --git a/stdlib/InteractiveUtils/src/InteractiveUtils.jl b/stdlib/InteractiveUtils/src/InteractiveUtils.jl index 9d23cb9dabb8a..0c397ba534c8f 100644 --- a/stdlib/InteractiveUtils/src/InteractiveUtils.jl +++ b/stdlib/InteractiveUtils/src/InteractiveUtils.jl @@ -249,7 +249,7 @@ are included, including those not visible in the current module. # Examples ```jldoctest julia> subtypes(Integer) -3-element Array{Union{DataType, UnionAll},1}: +3-element Array{Any,1}: Bool Signed Unsigned diff --git a/stdlib/IterativeEigensolvers/docs/src/index.md b/stdlib/IterativeEigensolvers/docs/src/index.md index 62dadc72c74a1..185d2dcc14a56 100644 --- a/stdlib/IterativeEigensolvers/docs/src/index.md +++ b/stdlib/IterativeEigensolvers/docs/src/index.md @@ -1,7 +1,7 @@ # [Iterative Eigensolvers](@id lib-itereigen) ```@meta -DocTestSetup = :(using IterativeEigensolvers) +DocTestSetup = :(using IterativeEigensolvers, LinearAlgebra, SparseArrays) ``` Julia provides bindings to [ARPACK](http://www.caam.rice.edu/software/ARPACK/), which @@ -53,9 +53,7 @@ the following keyword arguments are supported: * `v0`: starting vector from which to start the iterations We can see the various keywords in action in the following examples: -```jldoctest -julia> using IterativeEigensolvers - +```jldoctest; filter = r"(1|2)-element Array{(Float64|Complex{Float64}),1}:\n (.|\s)*$" julia> A = Diagonal(1:4); julia> λ, ϕ = eigs(A, nev = 2, which=:SM); @@ -65,42 +63,37 @@ julia> λ 1.0000000000000002 2.0 -julia> B = Diagonal([1., 2., -3im, 4im]) -4×4 Diagonal{Complex{Float64},Array{Complex{Float64},1}}: - 1.0+0.0im ⋅ ⋅ ⋅ - ⋅ 2.0+0.0im ⋅ ⋅ - ⋅ ⋅ 0.0-3.0im ⋅ - ⋅ ⋅ ⋅ 0.0+4.0im +julia> B = Diagonal([1., 2., -3im, 4im]); julia> λ, ϕ = eigs(B, nev=1, which=:LI); julia> λ 1-element Array{Complex{Float64},1}: - -4.440892098500626e-16 + 3.999999999999998im + 1.3322676295501878e-15 + 4.0im julia> λ, ϕ = eigs(B, nev=1, which=:SI); julia> λ 1-element Array{Complex{Float64},1}: - 1.3877787807814457e-16 - 2.999999999999999im + -2.498001805406602e-16 - 3.0000000000000018im julia> λ, ϕ = eigs(B, nev=1, which=:LR); julia> λ 1-element Array{Complex{Float64},1}: - 2.0 + 4.242754940683747e-17im + 2.0000000000000004 + 4.0615212488780827e-17im julia> λ, ϕ = eigs(B, nev=1, which=:SR); julia> λ 1-element Array{Complex{Float64},1}: - 4.440892098500626e-16 + 4.0000000000000036im + -8.881784197001252e-16 + 3.999999999999997im julia> λ, ϕ = eigs(B, nev=1, sigma=1.5); julia> λ 1-element Array{Complex{Float64},1}: - 1.9999999999999996 + 2.4290457684137336e-17im + 1.0000000000000004 + 4.0417078924070745e-18im ``` !!! note @@ -168,31 +161,29 @@ iterations `niter` and the number of matrix vector multiplications `nmult`, as w final residual vector `resid`. We can see the various keywords in action in the following examples: -```jldoctest -julia> using IterativeEigensolvers - +```jldoctest; filter = r"(1|2)-element Array{(Float64|Complex{Float64}),1}:\n (.|\s)*$" julia> A = sparse(1.0I, 4, 4); B = Diagonal(1:4); julia> λ, ϕ = eigs(A, B, nev = 2); julia> λ 2-element Array{Float64,1}: - 1.0 - 0.4999999999999999 + 1.0000000000000002 + 0.5 -julia> A = sparse(1.0I, 4, 4); B = Diagonal([1, -2im, 3, 4im]); +julia> A = Diagonal([1, -2im, 3, 4im]); B = sparse(1.0I, 4, 4); julia> λ, ϕ = eigs(A, B, nev=1, which=:SI); julia> λ 1-element Array{Complex{Float64},1}: - 0.03291282838780993 - 2.0627621271174514im + -1.5720931501039814e-16 - 1.9999999999999984im julia> λ, ϕ = eigs(A, B, nev=1, which=:LI); julia> λ 1-element Array{Complex{Float64},1}: - -0.6428551411711136 + 2.1820633510068994im + 0.0 + 4.000000000000002im ``` !!! note diff --git a/stdlib/IterativeEigensolvers/src/IterativeEigensolvers.jl b/stdlib/IterativeEigensolvers/src/IterativeEigensolvers.jl index 3bad088d82d54..64f2c4393aaa3 100644 --- a/stdlib/IterativeEigensolvers/src/IterativeEigensolvers.jl +++ b/stdlib/IterativeEigensolvers/src/IterativeEigensolvers.jl @@ -278,7 +278,7 @@ iterations derived from [`eigs`](@ref). * `resid`: Final residual vector. # Examples -```jldoctest +```jldoctest; filter = r"2-element Array{Float64,1}:\\n.*\\n.*" julia> A = Diagonal(1:4); julia> s = svds(A, nsv = 2)[1]; diff --git a/stdlib/LinearAlgebra/docs/src/index.md b/stdlib/LinearAlgebra/docs/src/index.md index d931b8c3a1693..e46e75ee0fb68 100644 --- a/stdlib/LinearAlgebra/docs/src/index.md +++ b/stdlib/LinearAlgebra/docs/src/index.md @@ -60,9 +60,17 @@ julia> A = [1.5 2 -4; 3 -1 -6; -10 2.3 4] -10.0 2.3 4.0 julia> factorize(A) -LinearAlgebra.LU{Float64,Array{Float64,2}} with factors L and U: -[1.0 0.0 0.0; -0.15 1.0 0.0; -0.3 -0.132196 1.0] -[-10.0 2.3 4.0; 0.0 2.345 -3.4; 0.0 0.0 -5.24947] +LU{Float64,Array{Float64,2}} +L factor: +3×3 Array{Float64,2}: + 1.0 0.0 0.0 + -0.15 1.0 0.0 + -0.3 -0.132196 1.0 +U factor: +3×3 Array{Float64,2}: + -10.0 2.3 4.0 + 0.0 2.345 -3.4 + 0.0 0.0 -5.24947 ``` Since `A` is not Hermitian, symmetric, triangular, tridiagonal, or bidiagonal, an LU factorization may be the @@ -76,17 +84,17 @@ julia> B = [1.5 2 -4; 2 -1 -3; -4 -3 5] -4.0 -3.0 5.0 julia> factorize(B) -LinearAlgebra.BunchKaufman{Float64,Array{Float64,2}} +BunchKaufman{Float64,Array{Float64,2}} D factor: 3×3 Tridiagonal{Float64,Array{Float64,1}}: -1.64286 0.0 ⋅ 0.0 -2.8 0.0 ⋅ 0.0 5.0 U factor: -3×3 LinearAlgebra.UnitUpperTriangular{Float64,Array{Float64,2}}: +3×3 UnitUpperTriangular{Float64,Array{Float64,2}}: 1.0 0.142857 -0.8 - 0.0 1.0 -0.6 - 0.0 0.0 1.0 + ⋅ 1.0 -0.6 + ⋅ ⋅ 1.0 permutation: 3-element Array{Int64,1}: 1 @@ -252,9 +260,7 @@ julia> b = [1 2 3; 4 5 6] julia> b - U ERROR: DimensionMismatch("matrix is not square: dimensions are (2, 3)") Stacktrace: - [1] checksquare at ./linalg/linalg.jl:220 [inlined] - [2] -(::Array{Int64,2}, ::UniformScaling{Int64}) at ./linalg/uniformscaling.jl:156 - [3] top-level scope +[...] ``` ## [Matrix factorizations](@id man-linalg-factorizations) @@ -416,7 +422,7 @@ Base.transpose LinearAlgebra.transpose! Base.adjoint LinearAlgebra.adjoint! -LinearAlgebra.peakflops +Base.copy(::Union{Transpose,Adjoint}) LinearAlgebra.stride1 LinearAlgebra.checksquare ``` diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 5d6d5198b79d9..5733fa8ad528b 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -246,7 +246,7 @@ conjugating the first vector. # Examples ```jldoctest -julia> Base.BLAS.dotc(10, fill(1.0im, 10), 1, fill(1.0+im, 20), 2) +julia> BLAS.dotc(10, fill(1.0im, 10), 1, fill(1.0+im, 20), 2) 10.0 - 10.0im ``` """ @@ -260,7 +260,7 @@ with stride `incx` and `n` elements of array `Y` with stride `incy`. # Examples ```jldoctest -julia> Base.BLAS.dotu(10, fill(1.0im, 10), 1, fill(1.0+im, 20), 2) +julia> BLAS.dotu(10, fill(1.0im, 10), 1, fill(1.0+im, 20), 2) -10.0 + 10.0im ``` """ @@ -350,10 +350,10 @@ end # Examples ```jldoctest -julia> Base.BLAS.nrm2(4, fill(1.0, 8), 2) +julia> BLAS.nrm2(4, fill(1.0, 8), 2) 2.0 -julia> Base.BLAS.nrm2(1, fill(1.0, 8), 2) +julia> BLAS.nrm2(1, fill(1.0, 8), 2) 1.0 ``` """ @@ -383,10 +383,10 @@ Sum of the absolute values of the first `n` elements of array `X` with stride `i # Examples ```jldoctest -julia> Base.BLAS.asum(5, fill(1.0im, 10), 2) +julia> BLAS.asum(5, fill(1.0im, 10), 2) 5.0 -julia> Base.BLAS.asum(2, fill(1.0im, 10), 5) +julia> BLAS.asum(2, fill(1.0im, 10), 5) 2.0 ``` """ @@ -420,7 +420,7 @@ julia> x = [1; 2; 3]; julia> y = [4; 5; 6]; -julia> Base.BLAS.axpy!(2, x, y) +julia> BLAS.axpy!(2, x, y) 3-element Array{Int64,1}: 6 9 @@ -483,7 +483,7 @@ julia> x = [1., 2, 3]; julia> y = [4., 5, 6]; -julia> Base.BLAS.axpby!(2., x, 3., y) +julia> BLAS.axpby!(2., x, 3., y) 3-element Array{Float64,1}: 14.0 19.0 diff --git a/stdlib/LinearAlgebra/src/bunchkaufman.jl b/stdlib/LinearAlgebra/src/bunchkaufman.jl index 80db51dcb802c..70f31800670e0 100644 --- a/stdlib/LinearAlgebra/src/bunchkaufman.jl +++ b/stdlib/LinearAlgebra/src/bunchkaufman.jl @@ -59,15 +59,15 @@ julia> A = [1 2; 2 3] 2 3 julia> bkfact(A) -LinearAlgebra.BunchKaufman{Float64,Array{Float64,2}} +BunchKaufman{Float64,Array{Float64,2}} D factor: 2×2 Tridiagonal{Float64,Array{Float64,1}}: -0.333333 0.0 0.0 3.0 U factor: -2×2 LinearAlgebra.UnitUpperTriangular{Float64,Array{Float64,2}}: +2×2 UnitUpperTriangular{Float64,Array{Float64,2}}: 1.0 0.666667 - 0.0 1.0 + ⋅ 1.0 permutation: 2-element Array{Int64,1}: 1 @@ -135,16 +135,16 @@ julia> A = [1 2 3; 2 1 2; 3 2 1] 3 2 1 julia> F = bkfact(Symmetric(A, :L)) -LinearAlgebra.BunchKaufman{Float64,Array{Float64,2}} +BunchKaufman{Float64,Array{Float64,2}} D factor: 3×3 Tridiagonal{Float64,Array{Float64,1}}: 1.0 3.0 ⋅ 3.0 1.0 0.0 ⋅ 0.0 -1.0 L factor: -3×3 LinearAlgebra.UnitLowerTriangular{Float64,Array{Float64,2}}: - 1.0 0.0 0.0 - 0.0 1.0 0.0 +3×3 UnitLowerTriangular{Float64,Array{Float64,2}}: + 1.0 ⋅ ⋅ + 0.0 1.0 ⋅ 0.5 0.5 1.0 permutation: 3-element Array{Int64,1}: diff --git a/stdlib/LinearAlgebra/src/cholesky.jl b/stdlib/LinearAlgebra/src/cholesky.jl index 1f390615da0e6..aba49d0676332 100644 --- a/stdlib/LinearAlgebra/src/cholesky.jl +++ b/stdlib/LinearAlgebra/src/cholesky.jl @@ -231,7 +231,9 @@ julia> A = [1 2; 2 50] 2 50 julia> cholfact!(A) -ERROR: InexactError: convert(Int64, 6.782329983125268) +ERROR: InexactError: Int64(Int64, 6.782329983125268) +Stacktrace: +[...] ``` """ function cholfact!(A::StridedMatrix, ::Val{false}=Val(false)) @@ -298,7 +300,7 @@ julia> A = [4. 12. -16.; 12. 37. -43.; -16. -43. 98.] -16.0 -43.0 98.0 julia> C = cholfact(A) -LinearAlgebra.Cholesky{Float64,Array{Float64,2}} +Cholesky{Float64,Array{Float64,2}} U factor: 3×3 UpperTriangular{Float64,Array{Float64,2}}: 2.0 6.0 -8.0 diff --git a/stdlib/LinearAlgebra/src/dense.jl b/stdlib/LinearAlgebra/src/dense.jl index a1e8997d68659..80ef0071081a1 100644 --- a/stdlib/LinearAlgebra/src/dense.jl +++ b/stdlib/LinearAlgebra/src/dense.jl @@ -621,8 +621,8 @@ julia> A = Matrix(2.7182818*I, 2, 2) julia> log(A) 2×2 Array{Float64,2}: - 1.0 0.0 - 0.0 1.0 + 1.0 0.0 + -0.0 1.0 ``` """ function log(A::StridedMatrix) @@ -935,8 +935,8 @@ this function, see [^AH16_1]. ```jldoctest julia> acos(cos([0.5 0.1; -0.2 0.3])) 2×2 Array{Complex{Float64},2}: - 0.5-8.32667e-17im 0.1-2.77556e-17im - -0.2+2.77556e-16im 0.3-3.46945e-16im + 0.5-5.55112e-17im 0.1-2.77556e-17im + -0.2+2.498e-16im 0.3-3.46945e-16im ``` """ function acos(A::AbstractMatrix) diff --git a/stdlib/LinearAlgebra/src/eigen.jl b/stdlib/LinearAlgebra/src/eigen.jl index 44b6721c604ba..56890060f13f2 100644 --- a/stdlib/LinearAlgebra/src/eigen.jl +++ b/stdlib/LinearAlgebra/src/eigen.jl @@ -75,7 +75,17 @@ make rows and columns more equal in norm. The default is `true` for both options # Examples ```jldoctest julia> F = eigfact([1.0 0.0 0.0; 0.0 3.0 0.0; 0.0 0.0 18.0]) -LinearAlgebra.Eigen{Float64,Float64,Array{Float64,2},Array{Float64,1}}([1.0, 3.0, 18.0], [1.0 0.0 0.0; 0.0 1.0 0.0; 0.0 0.0 1.0]) +Eigen{Float64,Float64,Array{Float64,2},Array{Float64,1}} +eigenvalues: +3-element Array{Float64,1}: + 1.0 + 3.0 + 18.0 +eigenvectors: +3×3 Array{Float64,2}: + 1.0 0.0 0.0 + 0.0 1.0 0.0 + 0.0 0.0 1.0 julia> F.values 3-element Array{Float64,1}: diff --git a/stdlib/LinearAlgebra/src/lu.jl b/stdlib/LinearAlgebra/src/lu.jl index 17cab622dad5b..3dc604869305a 100644 --- a/stdlib/LinearAlgebra/src/lu.jl +++ b/stdlib/LinearAlgebra/src/lu.jl @@ -39,11 +39,11 @@ element type of `A`, e.g. for integer types. ```jldoctest julia> A = [4. 3.; 6. 3.] 2×2 Array{Float64,2}: - 6.0 3.0 4.0 3.0 + 6.0 3.0 julia> F = lufact!(A) -LinearAlgebra.LU{Float64,Array{Float64,2}} +LU{Float64,Array{Float64,2}} L factor: 2×2 Array{Float64,2}: 1.0 0.0 @@ -59,7 +59,7 @@ julia> iA = [4 3; 6 3] 6 3 julia> lufact!(iA) -ERROR: InexactError: convert(Int64, 0.6666666666666666) +ERROR: InexactError: Int64(Int64, 0.6666666666666666) Stacktrace: [...] ``` @@ -162,7 +162,7 @@ julia> A = [4 3; 6 3] 6 3 julia> F = lufact(A) -LinearAlgebra.LU{Float64,Array{Float64,2}} +LU{Float64,Array{Float64,2}} L factor: 2×2 Array{Float64,2}: 1.0 0.0 diff --git a/stdlib/LinearAlgebra/src/qr.jl b/stdlib/LinearAlgebra/src/qr.jl index 25a1a69e2527d..543f6600e5ccd 100644 --- a/stdlib/LinearAlgebra/src/qr.jl +++ b/stdlib/LinearAlgebra/src/qr.jl @@ -216,9 +216,15 @@ julia> a = [1. 2.; 3. 4.] 3.0 4.0 julia> qrfact!(a) -LinearAlgebra.QRCompactWY{Float64,Array{Float64,2}} with factors Q and R: -[-0.316228 -0.948683; -0.948683 0.316228] -[-3.16228 -4.42719; 0.0 -0.632456] +LinearAlgebra.QRCompactWY{Float64,Array{Float64,2}} +Q factor: +2×2 LinearAlgebra.QRCompactWYQ{Float64,Array{Float64,2}}: + -0.316228 -0.948683 + -0.948683 0.316228 +R factor: +2×2 Array{Float64,2}: + -3.16228 -4.42719 + 0.0 -0.632456 julia> a = [1 2; 3 4] 2×2 Array{Int64,2}: @@ -226,7 +232,7 @@ julia> a = [1 2; 3 4] 3 4 julia> qrfact!(a) -ERROR: InexactError: convert(Int64, -3.1622776601683795) +ERROR: InexactError: Int64(Int64, -3.1622776601683795) Stacktrace: [...] ``` @@ -280,9 +286,16 @@ julia> A = [3.0 -6.0; 4.0 -8.0; 0.0 1.0] 0.0 1.0 julia> F = qrfact(A) -LinearAlgebra.QRCompactWY{Float64,Array{Float64,2}} with factors Q and R: -[-0.6 0.0 0.8; -0.8 0.0 -0.6; 0.0 -1.0 0.0] -[-5.0 10.0; 0.0 -1.0] +LinearAlgebra.QRCompactWY{Float64,Array{Float64,2}} +Q factor: +3×3 LinearAlgebra.QRCompactWYQ{Float64,Array{Float64,2}}: + -0.6 0.0 0.8 + -0.8 0.0 -0.6 + 0.0 -1.0 0.0 +R factor: +2×2 Array{Float64,2}: + -5.0 10.0 + 0.0 -1.0 julia> F.Q * F.R == A true diff --git a/stdlib/LinearAlgebra/src/schur.jl b/stdlib/LinearAlgebra/src/schur.jl index 410cce702409c..ec4595351bfe2 100644 --- a/stdlib/LinearAlgebra/src/schur.jl +++ b/stdlib/LinearAlgebra/src/schur.jl @@ -22,11 +22,19 @@ julia> A = [5. 7.; -2. -4.] -2.0 -4.0 julia> F = schurfact!(A) -LinearAlgebra.Schur{Float64,Array{Float64,2}} with factors T and Z: -[3.0 9.0; 0.0 -2.0] -[0.961524 0.274721; -0.274721 0.961524] -and values: -[3.0, -2.0] +Schur{Float64,Array{Float64,2}} +T factor: +2×2 Array{Float64,2}: + 3.0 9.0 + 0.0 -2.0 +Z factor: +2×2 Array{Float64,2}: + 0.961524 0.274721 + -0.274721 0.961524 +eigenvalues: +2-element Array{Float64,1}: + 3.0 + -2.0 julia> A 2×2 Array{Float64,2}: @@ -52,11 +60,19 @@ julia> A = [5. 7.; -2. -4.] -2.0 -4.0 julia> F = schurfact(A) -LinearAlgebra.Schur{Float64,Array{Float64,2}} with factors T and Z: -[3.0 9.0; 0.0 -2.0] -[0.961524 0.274721; -0.274721 0.961524] -and values: -[3.0, -2.0] +Schur{Float64,Array{Float64,2}} +T factor: +2×2 Array{Float64,2}: + 3.0 9.0 + 0.0 -2.0 +Z factor: +2×2 Array{Float64,2}: + 0.961524 0.274721 + -0.274721 0.961524 +eigenvalues: +2-element Array{Float64,1}: + 3.0 + -2.0 julia> F.vectors * F.Schur * F.vectors' 2×2 Array{Float64,2}: diff --git a/stdlib/LinearAlgebra/src/transpose.jl b/stdlib/LinearAlgebra/src/transpose.jl index 5b67703c57ee7..747be1c155efc 100644 --- a/stdlib/LinearAlgebra/src/transpose.jl +++ b/stdlib/LinearAlgebra/src/transpose.jl @@ -146,29 +146,35 @@ function ccopy!(B, A) end """ - transpose(A::AbstractMatrix) + copy(A::Transpose) + copy(A::Adjoint) -Eager matrix transpose. Note that the transposition is applied recursively to -elements. +Eagerly evaluate the lazy matrix transpose/adjoint. +Note that the transposition is applied recursively to elements. This operation is intended for linear algebra usage - for general data manipulation see [`permutedims`](@ref), which is non-recursive. # Examples ```jldoctest -julia> A = [1 2 3; 4 5 6; 7 8 9] -3×3 Array{Int64,2}: - 1 2 3 - 4 5 6 - 7 8 9 - -julia> transpose(A) -3×3 Array{Int64,2}: - 1 4 7 - 2 5 8 - 3 6 9 +julia> A = [1 2im; -3im 4] +2×2 Array{Complex{Int64},2}: + 1+0im 0+2im + 0-3im 4+0im + +julia> T = transpose(A) +2×2 Transpose{Complex{Int64},Array{Complex{Int64},2}}: + 1+0im 0-3im + 0+2im 4+0im + +julia> copy(T) +2×2 Array{Complex{Int64},2}: + 1+0im 0-3im + 0+2im 4+0im ``` """ +copy(::Union{Transpose,Adjoint}) + Base.copy(A::Transpose{<:Any,<:AbstractMatrix}) = transpose!(similar(A.parent, reverse(axes(A.parent))), A.parent) Base.copy(A::Adjoint{<:Any,<:AbstractMatrix}) = adjoint!(similar(A.parent, reverse(axes(A.parent))), A.parent) diff --git a/stdlib/Random/src/misc.jl b/stdlib/Random/src/misc.jl index 4978510245dca..5aaf8f0335795 100644 --- a/stdlib/Random/src/misc.jl +++ b/stdlib/Random/src/misc.jl @@ -21,14 +21,14 @@ julia> rng = MersenneTwister(1234); julia> bitrand(rng, 10) 10-element BitArray{1}: + false true true true - false true - false false true + false false true ``` @@ -53,10 +53,10 @@ number generator, see [Random Numbers](@ref). # Examples ```jldoctest julia> srand(0); randstring() -"c03rgKi1" +"Qgt7sUOP" julia> randstring(MersenneTwister(0), 'a':'z', 6) -"wijzek" +"oevnou" julia> randstring("ACGT") "TATCGGTC" diff --git a/stdlib/Sockets/docs/src/index.md b/stdlib/Sockets/docs/src/index.md index d457da9dfbeb9..2b258710f1445 100644 --- a/stdlib/Sockets/docs/src/index.md +++ b/stdlib/Sockets/docs/src/index.md @@ -1,5 +1,9 @@ ## Sockets +```@meta +DocTestSetup = :(using Sockets) +``` + ```@docs Sockets.connect(::TCPSocket, ::Integer) Sockets.connect(::AbstractString) @@ -23,3 +27,7 @@ Sockets.recv Sockets.recvfrom Sockets.setopt ``` + +```@meta +DocTestSetup = nothing +``` diff --git a/stdlib/SparseArrays/docs/src/index.md b/stdlib/SparseArrays/docs/src/index.md index 34dd58c361a52..afde15ce99740 100644 --- a/stdlib/SparseArrays/docs/src/index.md +++ b/stdlib/SparseArrays/docs/src/index.md @@ -1,7 +1,7 @@ # Sparse Arrays ```@meta -DocTestSetup = :(using SparseArrays) +DocTestSetup = :(using SparseArrays, LinearAlgebra) ``` Julia has support for sparse vectors and [sparse matrices](https://en.wikipedia.org/wiki/Sparse_matrix) diff --git a/stdlib/SparseArrays/src/sparsematrix.jl b/stdlib/SparseArrays/src/sparsematrix.jl index f4b8a8a549e34..ec1cec1f69a90 100644 --- a/stdlib/SparseArrays/src/sparsematrix.jl +++ b/stdlib/SparseArrays/src/sparsematrix.jl @@ -1393,15 +1393,13 @@ distribution is used in case `rfn` is not specified. The optional `rng` argument specifies a random number generator, see [Random Numbers](@ref). # Examples -```jldoctest -julia> rng = MersenneTwister(1234); - -julia> sprand(rng, Bool, 2, 2, 0.5) +```jldoctest; setup = :(using Random; srand(1234)) +julia> sprand(Bool, 2, 2, 0.5) 2×2 SparseMatrixCSC{Bool,Int64} with 2 stored entries: [1, 1] = true [2, 1] = true -julia> sprand(rng, Float64, 3, 0.75) +julia> sprand(Float64, 3, 0.75) 3-element SparseVector{Float64,Int64} with 1 stored entry: [3] = 0.298614 ``` @@ -1444,14 +1442,11 @@ where nonzero values are sampled from the normal distribution. The optional `rng argument specifies a random number generator, see [Random Numbers](@ref). # Examples -```jldoctest -julia> rng = MersenneTwister(1234); - -julia> sprandn(rng, 2, 2, 0.75) -2×2 SparseMatrixCSC{Float64,Int64} with 3 stored entries: - [1, 1] = 0.532813 - [2, 1] = -0.271735 - [2, 2] = 0.502334 +```jldoctest; setup = :(using Random; srand(0)) +julia> sprandn(2, 2, 0.75) +2×2 SparseMatrixCSC{Float64,Int64} with 2 stored entries: + [1, 1] = 0.586617 + [1, 2] = 0.297336 ``` """ sprandn(r::AbstractRNG, m::Integer, n::Integer, density::AbstractFloat) = sprand(r,m,n,density,randn,Float64) diff --git a/stdlib/Test/src/Test.jl b/stdlib/Test/src/Test.jl index eb546b614b88b..bdffcc68808a3 100644 --- a/stdlib/Test/src/Test.jl +++ b/stdlib/Test/src/Test.jl @@ -1209,7 +1209,7 @@ inferred by the compiler. It is useful to check for type stability. Returns the result of `f(x)` if the types match, and an `Error` `Result` if it finds different types. -```jldoctest +```jldoctest; setup = :(using InteractiveUtils), filter = r"begin\\n(.|\\n)*end" julia> f(a,b,c) = b > 1 ? 1 : 1.0 f (generic function with 1 method) @@ -1224,14 +1224,19 @@ Variables: Body: begin - unless (Base.slt_int)(1, b::Int64)::Bool goto 3 + # meta: location operators.jl > 279 + # meta: location int.jl < 49 + Core.SSAValue(2) = (Base.slt_int)(1, b::Int64)::Bool + # meta: pop locations (2) + unless Core.SSAValue(2) goto 7 return 1 - 3: + 7: return 1.0 end::UNION{FLOAT64, INT64} julia> @inferred f(1,2,3) ERROR: return type Int64 does not match inferred return type Union{Float64, Int64} +Stacktrace: [...] julia> @inferred max(1,2) diff --git a/stdlib/UUIDs/docs/src/index.md b/stdlib/UUIDs/docs/src/index.md index ddc490f4e46c9..3b936e7c82178 100644 --- a/stdlib/UUIDs/docs/src/index.md +++ b/stdlib/UUIDs/docs/src/index.md @@ -1,7 +1,7 @@ # UUIDs ```@meta -DocTestSetup = :(using UUIDs) +DocTestSetup = :(using UUIDs, Random) ``` ```@docs diff --git a/stdlib/UUIDs/src/UUIDs.jl b/stdlib/UUIDs/src/UUIDs.jl index 0f9ddc46027c7..cf59d0fb9f71b 100644 --- a/stdlib/UUIDs/src/UUIDs.jl +++ b/stdlib/UUIDs/src/UUIDs.jl @@ -32,11 +32,11 @@ by RFC 4122. Note that the Node ID is randomly generated (does not identify the according to section 4.5 of the RFC. # Examples -```jldoctest +```jldoctest; filter = r"[a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}" julia> rng = MersenneTwister(1234); julia> uuid1(rng) -2cc938da-5937-11e7-196e-0f4ef71aa64b +fcbd9b64-1bc2-11e8-1f13-43a2532b2fa8 ``` """ function uuid1(rng::AbstractRNG=Random.GLOBAL_RNG) @@ -73,7 +73,7 @@ as specified by RFC 4122. julia> rng = MersenneTwister(1234); julia> uuid4(rng) -82015f10-44cc-4827-996e-0f4ef71aa64b +196f2941-2d58-45ba-9f13-43a2532b2fa8 ``` """ function uuid4(rng::AbstractRNG=Random.GLOBAL_RNG) From 1a870b466d83068fad9f280cc1f8e65a108cb6bc Mon Sep 17 00:00:00 2001 From: Morten Piibeleht Date: Mon, 5 Mar 2018 00:08:58 +1300 Subject: [PATCH 26/28] Make sure Sockets page has h1 header (#26315) Currently the "Sockets" page shows up as a dash in the navbar of the manual since Documenter is unable to figure out the page title. --- stdlib/Sockets/docs/src/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/Sockets/docs/src/index.md b/stdlib/Sockets/docs/src/index.md index 2b258710f1445..7f4d72b20e522 100644 --- a/stdlib/Sockets/docs/src/index.md +++ b/stdlib/Sockets/docs/src/index.md @@ -1,4 +1,4 @@ -## Sockets +# Sockets ```@meta DocTestSetup = :(using Sockets) From f569ebe9bcfdeeae94952d9105c33dbf6b545da7 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sun, 4 Mar 2018 10:47:29 -0500 Subject: [PATCH 27/28] lower top-level statements in such a way that the front-end knows (#26304) their values are not used fixes most false positives in the deprecation for using the value of `.=` --- src/ast.c | 18 +++++++++++++++++- src/jlfrontend.scm | 17 ++++++++++++----- src/julia.h | 1 + src/toplevel.c | 2 +- test/deprecation_exec.jl | 12 ++++++++++++ 5 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/ast.c b/src/ast.c index d6c8968350187..84da490035742 100644 --- a/src/ast.c +++ b/src/ast.c @@ -829,7 +829,11 @@ jl_value_t *jl_parse_eval_all(const char *fname, form = jl_expand_macros(form, inmodule, NULL, 0); expression = julia_to_scm(fl_ctx, form); } - expression = fl_applyn(fl_ctx, 1, symbol_value(symbol(fl_ctx, "jl-expand-to-thunk")), expression); + // expand non-final expressions in statement position (value unused) + expression = + fl_applyn(fl_ctx, 1, + symbol_value(symbol(fl_ctx, iscons(cdr_(ast)) ? "jl-expand-to-thunk-stmt" : "jl-expand-to-thunk")), + expression); } jl_get_ptls_states()->world_age = jl_world_counter; form = scm_to_julia(fl_ctx, expression, inmodule); @@ -1115,6 +1119,18 @@ JL_DLLEXPORT jl_value_t *jl_expand(jl_value_t *expr, jl_module_t *inmodule) return expr; } +// expand in a context where the expression value is unused +JL_DLLEXPORT jl_value_t *jl_expand_stmt(jl_value_t *expr, jl_module_t *inmodule) +{ + JL_TIMING(LOWERING); + JL_GC_PUSH1(&expr); + expr = jl_copy_ast(expr); + expr = jl_expand_macros(expr, inmodule, NULL, 0); + expr = jl_call_scm_on_ast("jl-expand-to-thunk-stmt", expr, inmodule); + JL_GC_POP(); + return expr; +} + #ifdef __cplusplus } diff --git a/src/jlfrontend.scm b/src/jlfrontend.scm index 8dc9a853f5014..9572225af114b 100644 --- a/src/jlfrontend.scm +++ b/src/jlfrontend.scm @@ -94,12 +94,14 @@ (define *in-expand* #f) +(define (toplevel-only-expr? e) + (and (pair? e) + (or (memq (car e) '(toplevel line module import importall using export + error incomplete)) + (and (eq? (car e) 'global) (every symbol? (cdr e)))))) + (define (expand-toplevel-expr e) - (cond ((or (atom? e) - (and (pair? e) - (or (memq (car e) '(toplevel line module import importall using export - error incomplete)) - (and (eq? (car e) 'global) (every symbol? (cdr e)))))) + (cond ((or (atom? e) (toplevel-only-expr? e)) (if (underscore-symbol? e) (syntax-deprecation "underscores as an rvalue" "" #f)) e) @@ -207,6 +209,11 @@ (parser-wrap (lambda () (expand-toplevel-expr expr)))) +(define (jl-expand-to-thunk-stmt expr) + (jl-expand-to-thunk (if (toplevel-only-expr? expr) + expr + `(block ,expr (null))))) + ; run whole frontend on a string. useful for testing. (define (fe str) (expand-toplevel-expr (julia-parse str))) diff --git a/src/julia.h b/src/julia.h index de449173e0100..9b11afdfffd80 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1450,6 +1450,7 @@ JL_DLLEXPORT jl_value_t *jl_parse_string(const char *str, size_t len, JL_DLLEXPORT jl_value_t *jl_load_file_string(const char *text, size_t len, char *filename, jl_module_t *inmodule); JL_DLLEXPORT jl_value_t *jl_expand(jl_value_t *expr, jl_module_t *inmodule); +JL_DLLEXPORT jl_value_t *jl_expand_stmt(jl_value_t *expr, jl_module_t *inmodule); JL_DLLEXPORT jl_value_t *jl_eval_string(const char *str); // external libraries diff --git a/src/toplevel.c b/src/toplevel.c index c3279117dacbe..c8f27868f3ed4 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -228,7 +228,7 @@ jl_value_t *jl_eval_module_expr(jl_module_t *parent_module, jl_expr_t *ex) for (int i = 0; i < jl_array_len(exprs); i++) { // process toplevel form ptls->world_age = jl_world_counter; - form = jl_expand(jl_array_ptr_ref(exprs, i), newm); + form = jl_expand_stmt(jl_array_ptr_ref(exprs, i), newm); ptls->world_age = jl_world_counter; (void)jl_toplevel_eval_flex(newm, form, 1, 1); } diff --git a/test/deprecation_exec.jl b/test/deprecation_exec.jl index 633a65d0a66c5..86ae275dcb0ec 100644 --- a/test/deprecation_exec.jl +++ b/test/deprecation_exec.jl @@ -209,6 +209,18 @@ end # #6080 @test_deprecated r"Syntax `&argument`.*is deprecated" Meta.lower(@__MODULE__, :(ccall(:a, Cvoid, (Cint,), &x))) + @test_logs eval(:(module DotEqualsDep + a=[1,2] + a.=3 + 0 + end)) + @test_logs include_string(@__MODULE__, """ + a=[1,2] + a.=3 + 0""") + @test_deprecated include_string(@__MODULE__, """ + a=[1,2] + a.=3""") end module LogTest From c7da5379d034eb53745215f557279f72d22c016b Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 5 Mar 2018 12:01:08 -0500 Subject: [PATCH 28/28] fix an optimizer bug in `invoke` with non-constant functions (#26301) In this case inlining was able to convert an `invoke` call to an `:invoke` Expr, but we had not inferred the target method instance, which led us to hit the fallback path in `jl_invoke`, which does not support this case yet. --- base/compiler/tfuncs.jl | 17 ++++++++++++----- src/gf.c | 4 ++++ test/core.jl | 17 +++++++++++++++++ 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index 54a22b0b11266..658323b444992 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -729,12 +729,15 @@ function apply_type_tfunc(@nospecialize(headtypetype), @nospecialize args...) end add_tfunc(apply_type, 1, INT_INF, apply_type_tfunc, 10) -function invoke_tfunc(@nospecialize(f), @nospecialize(types), @nospecialize(argtype), sv::InferenceState) +function invoke_tfunc(@nospecialize(ft), @nospecialize(types), @nospecialize(argtype), sv::InferenceState) + dt = ccall(:jl_argument_datatype, Any, (Any,), ft) + if dt === nothing || !isdefined(dt.name, :mt) + return Any + end argtype = typeintersect(types, limit_tuple_type(argtype, sv.params)) if argtype === Bottom return Bottom end - ft = Core.Typeof(f) types = rewrap_unionall(Tuple{ft, unwrap_unionall(types).parameters...}, types) argtype = Tuple{ft, argtype.parameters...} entry = ccall(:jl_gf_invoke_lookup, Any, (Any, UInt), types, sv.params.world) @@ -816,8 +819,12 @@ function builtin_tfunction(@nospecialize(f), argtypes::Array{Any,1}, end return Expr elseif f === invoke - if length(argtypes) > 1 && isa(argtypes[1], Const) && sv !== nothing - af = argtypes[1].val + if length(argtypes) > 1 && sv !== nothing && (isa(argtypes[1], Const) || isa(argtypes[1], Type)) + if isa(argtypes[1], Const) + ft = Core.Typeof(argtypes[1].val) + else + ft = argtypes[1] + end sig = argtypes[2] if isa(sig, Const) sigty = sig.val @@ -827,7 +834,7 @@ function builtin_tfunction(@nospecialize(f), argtypes::Array{Any,1}, sigty = nothing end if isa(sigty, Type) && !has_free_typevars(sigty) && sigty <: Tuple - return invoke_tfunc(af, sigty, argtypes_to_type(argtypes[3:end]), sv) + return invoke_tfunc(ft, sigty, argtypes_to_type(argtypes[3:end]), sv) end end return Any diff --git a/src/gf.c b/src/gf.c index 2ee9be971d12c..30ad7173ab765 100644 --- a/src/gf.c +++ b/src/gf.c @@ -48,6 +48,10 @@ JL_DLLEXPORT jl_value_t *jl_invoke(jl_method_instance_t *meth, jl_value_t **args // since it can go through the unrolled caches for this world // and if inference is successful, this meth would get updated anyways, // and we'll get the fast path here next time + + // TODO: if `meth` came from an `invoke` call, we should make sure + // meth->def is called instead of doing normal dispatch. + return jl_apply(args, nargs); } } diff --git a/test/core.jl b/test/core.jl index d2adb82e7f500..f68234ca609fd 100644 --- a/test/core.jl +++ b/test/core.jl @@ -4852,6 +4852,23 @@ f18095(::Number, ::Int) = 0x12 @test_throws MethodError invoke(f18095, Tuple{Int, Any}, 1, 2) @test invoke(f18095, Tuple{Int, Real}, 1, 2) === 0x21 +# `invoke` with non-constant function +struct CassetteLikeWrapper{F} + x + f::F +end +(foo::CassetteLikeWrapper)(args...) = foo.f(args...) +(foo::CassetteLikeWrapper)(x) = invoke(foo, Tuple{Vararg{Any}}, x) +@test CassetteLikeWrapper(1,-)(2) == -2 + +f26301(x) = 1 +f26301(x::Int) = 2 +function g26301() + f = Any[f26301][1] + invoke(f, Tuple{Any}, 0) +end +@test g26301() == 1 + # issue #10981, long argument lists let a = fill(["sdf"], 2*10^6), temp_vcat(x...) = vcat(x...) # we introduce a new function `temp_vcat` to make sure there is no existing