From 488fb5a5978589fec4e703203d333f27b859a4aa Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 7 Oct 2015 16:35:53 -0400 Subject: [PATCH 001/106] preserve inline line numbers during inlining (cherry picked from commit a33cd07f8a0fe2dd4ef3fecf809add2bb2a493c9) ref #13491 --- base/inference.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index dc07af2f2e5f5..840da1b351f5c 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -2245,8 +2245,7 @@ function inlineable(f::ANY, e::Expr, atype::ANY, sv::StaticVarInfo, enclosing_as end body = Expr(:block) - body.args = filter(x->!((isa(x,Expr) && is(x.head,:line)) || isa(x,LineNumberNode)), - ast.args[3].args::Array{Any,1}) + body.args = ast.args[3].args::Array{Any,1} cost::Int = 1000 if incompletematch cost *= 4 From b8a6d771042add982a6a8739994c6f7dba2f4461 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 7 Oct 2015 19:22:01 -0400 Subject: [PATCH 002/106] fix #922 (wrong line numbers in error expressions) and remove old hacks around this issue (cherry picked from commit af81d6c7fe09f57ab268ccd731bc2d2f4aee9a95) --- src/builtins.c | 6 ------ src/cgutils.cpp | 14 +++++-------- src/codegen.cpp | 52 ++++++++++++++++++----------------------------- src/julia.h | 3 --- src/task.c | 5 ----- test/backtrace.jl | 3 ++- 6 files changed, 27 insertions(+), 56 deletions(-) diff --git a/src/builtins.c b/src/builtins.c index 8495f0261a746..f1a3d6dd538e5 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -103,12 +103,6 @@ void NORETURN jl_type_error_rt(const char *fname, const char *context, jl_throw(ex); } -void NORETURN jl_type_error_rt_line(const char *fname, const char *context, - jl_value_t *ty, jl_value_t *got, int line) -{ - jl_type_error_rt(fname, context, ty, got); -} - void NORETURN jl_type_error(const char *fname, jl_value_t *expected, jl_value_t *got) { jl_type_error_rt(fname, "", expected, got); diff --git a/src/cgutils.cpp b/src/cgutils.cpp index a04b992f075fd..67bd851a2be81 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -1059,11 +1059,9 @@ static void raise_exception_unless(Value *cond, Value *exc, jl_codectx_t *ctx) builder.CreateCondBr(cond, passBB, failBB); builder.SetInsertPoint(failBB); #ifdef LLVM37 - builder.CreateCall(prepare_call(jlthrow_line_func), { exc, - ConstantInt::get(T_int32, ctx->lineno) }); + builder.CreateCall(prepare_call(jlthrow_func), { exc }); #else - builder.CreateCall2(prepare_call(jlthrow_line_func), exc, - ConstantInt::get(T_int32, ctx->lineno)); + builder.CreateCall(prepare_call(jlthrow_func), exc); #endif builder.CreateUnreachable(); ctx->f->getBasicBlockList().push_back(passBB); @@ -1107,13 +1105,11 @@ static void emit_type_error(Value *x, jl_value_t *type, const std::string &msg, #ifdef LLVM37 builder.CreateCall(prepare_call(jltypeerror_func), { fname_val, msg_val, - literal_pointer_val(type), boxed(x,ctx), - ConstantInt::get(T_int32, ctx->lineno) }); + literal_pointer_val(type), boxed(x,ctx)}); #else - builder.CreateCall5(prepare_call(jltypeerror_func), + builder.CreateCall4(prepare_call(jltypeerror_func), fname_val, msg_val, - literal_pointer_val(type), boxed(x,ctx), - ConstantInt::get(T_int32, ctx->lineno)); + literal_pointer_val(type), boxed(x,ctx)); #endif } diff --git a/src/codegen.cpp b/src/codegen.cpp index efcac59c47309..969a96fe2ac0b 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -298,7 +298,6 @@ extern RTDyldMemoryManager* createRTDyldMemoryManagerOSX(); // important functions static Function *jlnew_func; static Function *jlthrow_func; -static Function *jlthrow_line_func; static Function *jlerror_func; static Function *jltypeerror_func; static Function *jlundefvarerror_func; @@ -468,7 +467,6 @@ typedef struct { bool vaStack; // varargs stack-allocated bool sret; int nReqArgs; - int lineno; std::vector boundsCheck; jl_gcinfo_t gc; @@ -1272,7 +1270,7 @@ extern "C" void jl_write_malloc_log(void) static void show_source_loc(JL_STREAM *out, jl_codectx_t *ctx) { if (ctx == NULL) return; - jl_printf(out, "in %s at %s:%d", ctx->linfo->name->name, ctx->linfo->file->name, ctx->lineno); + jl_printf(out, "in %s at %s", ctx->linfo->name->name, ctx->linfo->file->name); } extern "C" void jl_binding_deprecation_warning(jl_binding_t *b); @@ -4185,7 +4183,6 @@ static Function *emit_function(jl_lambda_info_t *lam) } } } - ctx.lineno = lno; int toplineno = lno; DIBuilder dbuilder(*m); @@ -4197,6 +4194,7 @@ static Function *emit_function(jl_lambda_info_t *lam) DIFile topfile; DISubprogram SP; #endif + DebugLoc inlineLoc; BasicBlock *b0 = BasicBlock::Create(jl_LLVMContext, "top", f); builder.SetInsertPoint(b0); @@ -4273,7 +4271,8 @@ static Function *emit_function(jl_lambda_info_t *lam) true, // isOptimized f); // Fn // set initial line number - builder.SetCurrentDebugLocation(DebugLoc::get(lno, 0, (MDNode*)SP, NULL)); + inlineLoc = DebugLoc::get(lno, 0, (MDNode*)SP, NULL); + builder.SetCurrentDebugLocation(inlineLoc); #ifndef LLVM37 assert(SP.Verify() && SP.describes(f) && SP.getFunction() == f); #endif @@ -4290,7 +4289,7 @@ static Function *emit_function(jl_lambda_info_t *lam) argname->name, // Variable name ctx.sret + i + 1, // Argument number (1-based) topfile, // File - ctx.lineno == -1 ? 0 : ctx.lineno, // Line + toplineno == -1 ? 0 : toplineno, // Line // Variable type julia_type_to_di(varinfo.declType,ctx.dbuilder,specsig)); #else @@ -4299,7 +4298,7 @@ static Function *emit_function(jl_lambda_info_t *lam) SP, // Scope (current function will be fill in later) argname->name, // Variable name topfile, // File - ctx.lineno == -1 ? 0 : ctx.lineno, // Line (for now, use lineno of the function) + toplineno == -1 ? 0 : toplineno, // Line (for now, use lineno of the function) julia_type_to_di(varinfo.declType,ctx.dbuilder,specsig), // Variable type false, // May be optimized out 0, // Flags (TODO: Do we need any) @@ -4313,7 +4312,7 @@ static Function *emit_function(jl_lambda_info_t *lam) ctx.vaName->name, // Variable name ctx.sret + nreq + 1, // Argument number (1-based) topfile, // File - ctx.lineno == -1 ? 0 : ctx.lineno, // Line (for now, use lineno of the function) + toplineno == -1 ? 0 : toplineno, // Line (for now, use lineno of the function) julia_type_to_di(ctx.vars[ctx.vaName].declType,ctx.dbuilder,false)); #else ctx.vars[ctx.vaName].dinfo = ctx.dbuilder->createLocalVariable( @@ -4321,7 +4320,7 @@ static Function *emit_function(jl_lambda_info_t *lam) SP, // Scope (current function will be fill in later) ctx.vaName->name, // Variable name topfile, // File - ctx.lineno == -1 ? 0 : ctx.lineno, // Line (for now, use lineno of the function) + toplineno == -1 ? 0 : toplineno, // Line (for now, use lineno of the function) julia_type_to_di(ctx.vars[ctx.vaName].declType,ctx.dbuilder,false), // Variable type false, // May be optimized out 0, // Flags (TODO: Do we need any) @@ -4342,7 +4341,7 @@ static Function *emit_function(jl_lambda_info_t *lam) SP, // Scope (current function will be fill in later) s->name, // Variable name topfile, // File - ctx.lineno == -1 ? 0 : ctx.lineno, // Line (for now, use lineno of the function) + toplineno == -1 ? 0 : toplineno, // Line (for now, use lineno of the function) julia_type_to_di(varinfo.declType,ctx.dbuilder,specsig), // Variable type false, // May be optimized out 0 // Flags (TODO: Do we need any) @@ -4366,7 +4365,7 @@ static Function *emit_function(jl_lambda_info_t *lam) SP, // Scope (current function will be filled in later) vname->name, // Variable name topfile, // File - ctx.lineno == -1 ? 0 : ctx.lineno, // Line (for now, use lineno of the function) + toplineno == -1 ? 0 : toplineno, // Line (for now, use lineno of the function) julia_type_to_di(varinfo.declType,ctx.dbuilder,specsig), // Variable type false, // May be optimized out 0 // Flags (TODO: Do we need any) @@ -4732,7 +4731,6 @@ static Function *emit_function(jl_lambda_info_t *lam) } DebugLoc loc; if (ctx.debug_enabled) { - MDNode *funcscope = (MDNode*)dbuilder.createLexicalBlockFile(SP, topfile); MDNode *scope; if ((dfil == topfile || dfil == NULL) && lno >= toplineno) @@ -4740,19 +4738,17 @@ static Function *emit_function(jl_lambda_info_t *lam) // for sequentially-defined code, // set location to line in top file. // TODO: improve handling of nested inlines - loc = DebugLoc::get(lno, 1, SP, NULL); + loc = inlineLoc = DebugLoc::get(lno, 1, SP, NULL); } else { // otherwise, we are compiling inlined code, // so set the DebugLoc "inlinedAt" parameter // to the current line, then use source loc. #ifdef LLVM37 scope = (MDNode*)dbuilder.createLexicalBlockFile(SP,dfil); - MDNode *inlineLocMd = DebugLoc::get(toplineno, 1, funcscope, NULL). - getAsMDNode(); + MDNode *inlineLocMd = inlineLoc.getAsMDNode(); #else scope = (MDNode*)dbuilder.createLexicalBlockFile(SP,DIFile(dfil)); - MDNode *inlineLocMd = DebugLoc::get(toplineno, 1, funcscope, NULL). - getAsMDNode(jl_LLVMContext); + MDNode *inlineLocMd = inlineLoc.getAsMDNode(jl_LLVMContext); #endif loc = DebugLoc::get(lno, 1, scope, inlineLocMd); } @@ -4760,7 +4756,6 @@ static Function *emit_function(jl_lambda_info_t *lam) } if (do_coverage) coverageVisitLine(filename, lno); - ctx.lineno = lno; // NOO TOUCHIE; NO TOUCH! See #922 } if (jl_is_labelnode(stmt)) { if (prevlabel) continue; @@ -5199,15 +5194,6 @@ static void init_julia_llvm_env(Module *m) jluboundserror_func->setDoesNotReturn(); add_named_global(jluboundserror_func, (void*)&jl_bounds_error_unboxed_int); - std::vector args2_throw(0); - args2_throw.push_back(jl_pvalue_llvmt); - args2_throw.push_back(T_int32); - jlthrow_line_func = - (Function*)m->getOrInsertFunction("jl_throw_with_superfluous_argument", - FunctionType::get(T_void, args2_throw, false)); - jlthrow_line_func->setDoesNotReturn(); - add_named_global(jlthrow_line_func, (void*)&jl_throw_with_superfluous_argument); - jlnew_func = Function::Create(jl_func_sig, Function::ExternalLinkage, "jl_new_structv", m); @@ -5238,13 +5224,12 @@ static void init_julia_llvm_env(Module *m) te_args.push_back(T_pint8); te_args.push_back(jl_pvalue_llvmt); te_args.push_back(jl_pvalue_llvmt); - te_args.push_back(T_int32); jltypeerror_func = Function::Create(FunctionType::get(T_void, te_args, false), Function::ExternalLinkage, - "jl_type_error_rt_line", m); + "jl_type_error_rt", m); jltypeerror_func->setDoesNotReturn(); - add_named_global(jltypeerror_func, (void*)&jl_type_error_rt_line); + add_named_global(jltypeerror_func, (void*)&jl_type_error_rt); std::vector args_2ptrs(0); args_2ptrs.push_back(jl_pvalue_llvmt); @@ -5686,13 +5671,16 @@ static inline SmallVector getTargetFeatures() { extern "C" void jl_init_codegen(void) { + const char *const argv_tailmerge[] = {"", "-enable-tail-merge=0"}; // NOO TOUCHIE; NO TOUCH! See #922 + cl::ParseCommandLineOptions(sizeof(argv_tailmerge)/sizeof(argv_tailmerge[0]), argv_tailmerge, "disable-tail-merge\n"); #if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_) - const char *const argv[] = {"", "-disable-copyprop"}; // llvm bug 21743 - cl::ParseCommandLineOptions(sizeof(argv)/sizeof(argv[0]), argv, "disable-copyprop\n"); + const char *const argv_copyprop[] = {"", "-disable-copyprop"}; // llvm bug 21743 + cl::ParseCommandLineOptions(sizeof(argv_copyprop)/sizeof(argv_copyprop[0]), argv_copyprop, "disable-copyprop\n"); #endif #ifdef JL_DEBUG_BUILD cl::ParseEnvironmentOptions("Julia", "JULIA_LLVM_ARGS"); #endif + #if defined(_CPU_PPC_) || defined(_CPU_PPC64_) imaging_mode = true; // LLVM seems to JIT bad TOC tables for the optimizations we attempt in non-imaging_mode #else diff --git a/src/julia.h b/src/julia.h index 29407e9b8055f..fce506f7d7914 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1146,8 +1146,6 @@ DLLEXPORT void NORETURN jl_too_many_args(const char *fname, int max); DLLEXPORT void NORETURN jl_type_error(const char *fname, jl_value_t *expected, jl_value_t *got); DLLEXPORT void NORETURN jl_type_error_rt(const char *fname, const char *context, jl_value_t *ty, jl_value_t *got); -DLLEXPORT void NORETURN jl_type_error_rt_line(const char *fname, const char *context, - jl_value_t *ty, jl_value_t *got, int line); DLLEXPORT void NORETURN jl_undefined_var_error(jl_sym_t *var); DLLEXPORT void NORETURN jl_bounds_error(jl_value_t *v, jl_value_t *t); DLLEXPORT void NORETURN jl_bounds_error_v(jl_value_t *v, jl_value_t **idxs, size_t nidxs); @@ -1401,7 +1399,6 @@ extern DLLEXPORT JL_THREAD jl_value_t *jl_exception_in_transit; DLLEXPORT jl_task_t *jl_new_task(jl_function_t *start, size_t ssize); DLLEXPORT jl_value_t *jl_switchto(jl_task_t *t, jl_value_t *arg); DLLEXPORT void NORETURN jl_throw(jl_value_t *e); -DLLEXPORT void NORETURN jl_throw_with_superfluous_argument(jl_value_t *e, int); DLLEXPORT void NORETURN jl_rethrow(void); DLLEXPORT void NORETURN jl_rethrow_other(jl_value_t *e); diff --git a/src/task.c b/src/task.c index 31c3dc8b91085..cf9f3715befdc 100644 --- a/src/task.c +++ b/src/task.c @@ -828,11 +828,6 @@ DLLEXPORT void jl_rethrow_other(jl_value_t *e) throw_internal(e); } -DLLEXPORT void jl_throw_with_superfluous_argument(jl_value_t *e, int line) -{ - jl_throw(e); -} - DLLEXPORT jl_task_t *jl_new_task(jl_function_t *start, size_t ssize) { size_t pagesz = jl_page_size; diff --git a/test/backtrace.jl b/test/backtrace.jl index d5b9f3ad97c5f..4f6b2eb6d194b 100644 --- a/test/backtrace.jl +++ b/test/backtrace.jl @@ -99,5 +99,6 @@ let ind2 = find(:test_throw_commoning .== map(b->code_loc(b)[1], b2)) @test !isempty(ind1) @test !isempty(ind2) - @test code_loc(b1[ind1[1]])[3] != code_loc(b2[ind2[1]])[3] + @test code_loc(b1[ind1[1]])[3]::Int == code_loc(b2[ind2[1]])[3]::Int && # source line, for example: essentials.jl:58 + code_loc(b1[ind1[1]])[5]::Int != code_loc(b2[ind2[1]])[5]::Int # inlined line, for example: backtrace.jl:82 end From e1a37492ff1053b114f8cb1fc2d135d25e3669a1 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Wed, 28 Oct 2015 10:07:03 -0500 Subject: [PATCH 003/106] Use promote_op in broadcasting and matrix multiplication This makes it easier to support these operations on AbstractArrays with generic eltypes (cherry picked from commit 82f9a210aad41d81636b82618ac7f8923ade6c79) ref #13803 remove _pure_meta for backport also qualify Base.MulFun --- base/abstractarray.jl | 9 +++++++++ base/bool.jl | 2 ++ base/broadcast.jl | 34 +++++++++++---------------------- base/complex.jl | 7 +++++++ base/functors.jl | 4 ++++ base/int.jl | 2 ++ base/linalg.jl | 1 + base/linalg/matmul.jl | 38 ++++++++++++++++++------------------- base/promotion.jl | 3 +++ base/sparse/sparsematrix.jl | 2 +- test/arrayops.jl | 8 ++++++-- 11 files changed, 65 insertions(+), 45 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index ba7721dc5ce8c..e78eb6108d40d 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1273,6 +1273,15 @@ function map_promote(f, A::AbstractArray) return promote_to!(f, 2, dest, A) end +# These are needed because map(eltype, As) is not inferrable +promote_eltype_op(::Any) = Bottom +promote_eltype_op{T}(op, ::AbstractArray{T}) = promote_op(op, T) +promote_eltype_op{T}(op, ::T ) = promote_op(op, T) +promote_eltype_op{R,S}(op, ::AbstractArray{R}, ::AbstractArray{S}) = promote_op(op, R, S) +promote_eltype_op{R,S}(op, ::AbstractArray{R}, ::S) = promote_op(op, R, S) +promote_eltype_op{R,S}(op, ::R, ::AbstractArray{S}) = promote_op(op, R, S) +promote_eltype_op(op, A, B, C, D...) = promote_op(op, eltype(A), promote_eltype_op(op, B, C, D...)) + ## 1 argument map!{F}(f::F, A::AbstractArray) = map!(f, A, A) function map!{F}(f::F, dest::AbstractArray, A::AbstractArray) diff --git a/base/bool.jl b/base/bool.jl index 95df1e3494cb3..915d67a97bb3f 100644 --- a/base/bool.jl +++ b/base/bool.jl @@ -59,3 +59,5 @@ fld(x::Bool, y::Bool) = div(x,y) cld(x::Bool, y::Bool) = div(x,y) rem(x::Bool, y::Bool) = y ? false : throw(DivideError()) mod(x::Bool, y::Bool) = rem(x,y) + +promote_op(op, ::Type{Bool}, ::Type{Bool}) = typeof(op(true, true)) diff --git a/base/broadcast.jl b/base/broadcast.jl index de593d46e0c47..32666ed6a32c8 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -3,9 +3,8 @@ module Broadcast using ..Cartesian -import Base.promote_eltype -import Base.@get! -import Base.num_bit_chunks, Base._msk_end, Base.unsafe_bitgetindex +using Base: promote_op, promote_eltype, promote_eltype_op, @get!, _msk_end, unsafe_bitgetindex +using Base: AddFun, SubFun, MulFun, LDivFun, RDivFun, PowFun import Base: .+, .-, .*, ./, .\, .//, .==, .<, .!=, .<=, .%, .<<, .>>, .^ export broadcast, broadcast!, broadcast_function, broadcast!_function, bitbroadcast export broadcast_getindex, broadcast_setindex! @@ -232,7 +231,7 @@ for (Bsig, Asig, gbf, gbb) in end -broadcast(f, As...) = broadcast!(f, Array(promote_eltype(As...), broadcast_shape(As...)), As...) +broadcast(f, As...) = broadcast!(f, Array(promote_eltype_op(f, As...), broadcast_shape(As...)), As...) bitbroadcast(f, As...) = broadcast!(f, BitArray(broadcast_shape(As...)), As...) @@ -286,35 +285,28 @@ end ## elementwise operators ## -.*(As::AbstractArray...) = broadcast(*, As...) .%(A::AbstractArray, B::AbstractArray) = broadcast(%, A, B) .<<(A::AbstractArray, B::AbstractArray) = broadcast(<<, A, B) .>>(A::AbstractArray, B::AbstractArray) = broadcast(>>, A, B) -eltype_plus(As::AbstractArray...) = promote_eltype(As...) -eltype_plus(As::AbstractArray{Bool}...) = typeof(true+true) +eltype_plus(As::AbstractArray...) = promote_eltype_op(AddFun(), As...) .+(As::AbstractArray...) = broadcast!(+, Array(eltype_plus(As...), broadcast_shape(As...)), As...) -type_minus(T, S) = promote_type(T, S) -type_minus(::Type{Bool}, ::Type{Bool}) = typeof(true-true) - function .-(A::AbstractArray, B::AbstractArray) - broadcast!(-, Array(type_minus(eltype(A), eltype(B)), broadcast_shape(A,B)), A, B) + broadcast!(-, Array(promote_op(SubFun(), eltype(A), eltype(B)), broadcast_shape(A,B)), A, B) end -type_div(T,S) = promote_type(T,S) -type_div{T<:Integer,S<:Integer}(::Type{T},::Type{S}) = typeof(one(T)/one(S)) -type_div{T,S}(::Type{Complex{T}},::Type{Complex{S}}) = Complex{type_div(T,S)} -type_div{T,S}(::Type{Complex{T}},::Type{S}) = Complex{type_div(T,S)} -type_div{T,S}(::Type{T},::Type{Complex{S}}) = Complex{type_div(T,S)} +eltype_mul(As::AbstractArray...) = promote_eltype_op(MulFun(), As...) + +.*(As::AbstractArray...) = broadcast!(*, Array(eltype_mul(As...), broadcast_shape(As...)), As...) function ./(A::AbstractArray, B::AbstractArray) - broadcast!(/, Array(type_div(eltype(A), eltype(B)), broadcast_shape(A, B)), A, B) + broadcast!(/, Array(promote_op(RDivFun(), eltype(A), eltype(B)), broadcast_shape(A, B)), A, B) end function .\(A::AbstractArray, B::AbstractArray) - broadcast!(\, Array(type_div(eltype(A), eltype(B)), broadcast_shape(A, B)), A, B) + broadcast!(\, Array(promote_op(LDivFun(), eltype(A), eltype(B)), broadcast_shape(A, B)), A, B) end typealias RatIntT{T<:Integer} Union{Type{Rational{T}},Type{T}} @@ -327,12 +319,8 @@ function .//(A::AbstractArray, B::AbstractArray) broadcast!(//, Array(type_rdiv(eltype(A), eltype(B)), broadcast_shape(A, B)), A, B) end -type_pow(T,S) = promote_type(T,S) -type_pow{S<:Integer}(::Type{Bool},::Type{S}) = Bool -type_pow{S}(T,::Type{Rational{S}}) = type_pow(T, type_div(S, S)) - function .^(A::AbstractArray, B::AbstractArray) - broadcast!(^, Array(type_pow(eltype(A), eltype(B)), broadcast_shape(A, B)), A, B) + broadcast!(^, Array(promote_op(PowFun(), eltype(A), eltype(B)), broadcast_shape(A, B)), A, B) end ## element-wise comparison operators returning BitArray ## diff --git a/base/complex.jl b/base/complex.jl index 99cc4d2cd29fd..88151b0ace75b 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -26,6 +26,13 @@ promote_rule{T<:Real,S<:Real}(::Type{Complex{T}}, ::Type{S}) = promote_rule{T<:Real,S<:Real}(::Type{Complex{T}}, ::Type{Complex{S}}) = Complex{promote_type(T,S)} +promote_op{T<:Real,S<:Real}(op, ::Type{Complex{T}}, ::Type{Complex{S}}) = + Complex{promote_op(op,T,S)} +promote_op{T<:Real,S<:Real}(op, ::Type{Complex{T}}, ::Type{S}) = + Complex{promote_op(op,T,S)} +promote_op{T<:Real,S<:Real}(op, ::Type{T}, ::Type{Complex{S}}) = + Complex{promote_op(op,T,S)} + widen{T}(::Type{Complex{T}}) = Complex{widen(T)} real(z::Complex) = z.re diff --git a/base/functors.jl b/base/functors.jl index 613698192b7ba..ba8aa4e354344 100644 --- a/base/functors.jl +++ b/base/functors.jl @@ -120,6 +120,10 @@ EqX{T}(x::T) = EqX{T}(x) call(f::EqX, y) = f.x == y +# More promote_op rules + +promote_op{T<:Integer}(::PowFun, ::Type{Bool}, ::Type{T}) = Bool + #### Bitwise operators #### # BitFunctors are functions that behave in the same bit-wise manner when applied diff --git a/base/int.jl b/base/int.jl index 2ace89965c3dd..0ca47800f043c 100644 --- a/base/int.jl +++ b/base/int.jl @@ -340,6 +340,8 @@ promote_rule(::Type{UInt128}, ::Type{Int32} ) = UInt128 promote_rule(::Type{UInt128}, ::Type{Int64} ) = UInt128 promote_rule(::Type{UInt128}, ::Type{Int128}) = UInt128 +promote_op{R<:Integer,S<:Integer}(op, ::Type{R}, ::Type{S}) = typeof(op(one(R), one(S))) + ## traits ## typemin(::Type{Int8 }) = Int8(-128) diff --git a/base/linalg.jl b/base/linalg.jl index 5947cd6d59d6f..27227a221f8b1 100644 --- a/base/linalg.jl +++ b/base/linalg.jl @@ -7,6 +7,7 @@ importall ..Base.Operators import Base: USE_BLAS64, size, copy, copy_transpose!, power_by_squaring, print_matrix, transpose!, unsafe_getindex, unsafe_setindex!, isapprox +using Base: promote_op, MulFun export # Modules diff --git a/base/linalg/matmul.jl b/base/linalg/matmul.jl index 2066ff3603efe..816170429b88f 100644 --- a/base/linalg/matmul.jl +++ b/base/linalg/matmul.jl @@ -38,8 +38,8 @@ function scale!(C::AbstractMatrix, b::AbstractVector, A::AbstractMatrix) end C end -scale(A::Matrix, b::Vector) = scale!(similar(A, promote_type(eltype(A),eltype(b))), A, b) -scale(b::Vector, A::Matrix) = scale!(similar(b, promote_type(eltype(A),eltype(b)), size(A)), b, A) +scale(A::Matrix, b::Vector) = scale!(similar(A, promote_op(MulFun(),eltype(A),eltype(b))), A, b) +scale(b::Vector, A::Matrix) = scale!(similar(b, promote_op(MulFun(),eltype(b),eltype(A)), size(A)), b, A) # Dot products @@ -78,11 +78,11 @@ At_mul_B{T<:BlasComplex}(x::StridedVector{T}, y::StridedVector{T}) = [BLAS.dotu( # Matrix-vector multiplication function (*){T<:BlasFloat,S}(A::StridedMatrix{T}, x::StridedVector{S}) - TS = promote_type(arithtype(T),arithtype(S)) + TS = promote_op(MulFun(),arithtype(T),arithtype(S)) A_mul_B!(similar(x, TS, size(A,1)), A, convert(AbstractVector{TS}, x)) end function (*){T,S}(A::AbstractMatrix{T}, x::AbstractVector{S}) - TS = promote_type(arithtype(T),arithtype(S)) + TS = promote_op(MulFun(),arithtype(T),arithtype(S)) A_mul_B!(similar(x,TS,size(A,1)),A,x) end (*)(A::AbstractVector, B::AbstractMatrix) = reshape(A,length(A),1)*B @@ -101,22 +101,22 @@ end A_mul_B!(y::StridedVector, A::StridedVecOrMat, x::StridedVector) = generic_matvecmul!(y, 'N', A, x) function At_mul_B{T<:BlasFloat,S}(A::StridedMatrix{T}, x::StridedVector{S}) - TS = promote_type(arithtype(T),arithtype(S)) + TS = promote_op(MulFun(),arithtype(T),arithtype(S)) At_mul_B!(similar(x,TS,size(A,2)), A, convert(AbstractVector{TS}, x)) end function At_mul_B{T,S}(A::StridedMatrix{T}, x::StridedVector{S}) - TS = promote_type(arithtype(T),arithtype(S)) + TS = promote_op(MulFun(),arithtype(T),arithtype(S)) At_mul_B!(similar(x,TS,size(A,2)), A, x) end At_mul_B!{T<:BlasFloat}(y::StridedVector{T}, A::StridedVecOrMat{T}, x::StridedVector{T}) = gemv!(y, 'T', A, x) At_mul_B!(y::StridedVector, A::StridedVecOrMat, x::StridedVector) = generic_matvecmul!(y, 'T', A, x) function Ac_mul_B{T<:BlasFloat,S}(A::StridedMatrix{T}, x::StridedVector{S}) - TS = promote_type(arithtype(T),arithtype(S)) + TS = promote_op(MulFun(),arithtype(T),arithtype(S)) Ac_mul_B!(similar(x,TS,size(A,2)),A,convert(AbstractVector{TS},x)) end function Ac_mul_B{T,S}(A::StridedMatrix{T}, x::StridedVector{S}) - TS = promote_type(arithtype(T),arithtype(S)) + TS = promote_op(MulFun(),arithtype(T),arithtype(S)) Ac_mul_B!(similar(x,TS,size(A,2)), A, x) end @@ -127,7 +127,7 @@ Ac_mul_B!(y::StridedVector, A::StridedVecOrMat, x::StridedVector) = generic_matv # Matrix-matrix multiplication function (*){T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) - TS = promote_type(arithtype(T), arithtype(S)) + TS = promote_op(MulFun(), arithtype(T), arithtype(S)) A_mul_B!(similar(B, TS, (size(A,1), size(B,2))), A, B) end A_mul_B!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = gemm_wrapper!(C, 'N', 'N', A, B) @@ -144,14 +144,14 @@ end A_mul_B!(C::StridedMatrix, A::StridedVecOrMat, B::StridedVecOrMat) = generic_matmatmul!(C, 'N', 'N', A, B) function At_mul_B{T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) - TS = promote_type(arithtype(T), arithtype(S)) + TS = promote_op(MulFun(),arithtype(T), arithtype(S)) At_mul_B!(similar(B, TS, (size(A,2), size(B,2))), A, B) end At_mul_B!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = is(A,B) ? syrk_wrapper!(C, 'T', A) : gemm_wrapper!(C, 'T', 'N', A, B) At_mul_B!(C::StridedMatrix, A::StridedVecOrMat, B::StridedVecOrMat) = generic_matmatmul!(C, 'T', 'N', A, B) function A_mul_Bt{T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) - TS = promote_type(arithtype(T), arithtype(S)) + TS = promote_op(MulFun(),arithtype(T), arithtype(S)) A_mul_Bt!(similar(B, TS, (size(A,1), size(B,1))), A, B) end A_mul_Bt!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = is(A,B) ? syrk_wrapper!(C, 'N', A) : gemm_wrapper!(C, 'N', 'T', A, B) @@ -168,7 +168,7 @@ end A_mul_Bt!(C::StridedVecOrMat, A::StridedVecOrMat, B::StridedVecOrMat) = generic_matmatmul!(C, 'N', 'T', A, B) function At_mul_Bt{T,S}(A::AbstractMatrix{T}, B::StridedVecOrMat{S}) - TS = promote_type(arithtype(T), arithtype(S)) + TS = promote_op(MulFun(),arithtype(T), arithtype(S)) At_mul_Bt!(similar(B, TS, (size(A,2), size(B,1))), A, B) end At_mul_Bt!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = gemm_wrapper!(C, 'T', 'T', A, B) @@ -177,7 +177,7 @@ At_mul_Bt!(C::StridedMatrix, A::StridedVecOrMat, B::StridedVecOrMat) = generic_m Ac_mul_B{T<:BlasReal}(A::StridedMatrix{T}, B::StridedMatrix{T}) = At_mul_B(A, B) Ac_mul_B!{T<:BlasReal}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = At_mul_B!(C, A, B) function Ac_mul_B{T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) - TS = promote_type(arithtype(T), arithtype(S)) + TS = promote_op(MulFun(),arithtype(T), arithtype(S)) Ac_mul_B!(similar(B, TS, (size(A,2), size(B,2))), A, B) end Ac_mul_B!{T<:BlasComplex}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = is(A,B) ? herk_wrapper!(C,'C',A) : gemm_wrapper!(C,'C', 'N', A, B) @@ -186,16 +186,16 @@ Ac_mul_B!(C::StridedMatrix, A::StridedVecOrMat, B::StridedVecOrMat) = generic_ma A_mul_Bc{T<:BlasFloat,S<:BlasReal}(A::StridedMatrix{T}, B::StridedMatrix{S}) = A_mul_Bt(A, B) A_mul_Bc!{T<:BlasFloat,S<:BlasReal}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{S}) = A_mul_Bt!(C, A, B) function A_mul_Bc{T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) - TS = promote_type(arithtype(T),arithtype(S)) + TS = promote_op(MulFun(),arithtype(T),arithtype(S)) A_mul_Bc!(similar(B,TS,(size(A,1),size(B,1))),A,B) end A_mul_Bc!{T<:BlasComplex}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = is(A,B) ? herk_wrapper!(C, 'N', A) : gemm_wrapper!(C, 'N', 'C', A, B) A_mul_Bc!(C::StridedMatrix, A::StridedVecOrMat, B::StridedVecOrMat) = generic_matmatmul!(C, 'N', 'C', A, B) -Ac_mul_Bc{T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) = Ac_mul_Bc!(similar(B, promote_type(arithtype(T), arithtype(S)), (size(A,2), size(B,1))), A, B) +Ac_mul_Bc{T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) = Ac_mul_Bc!(similar(B, promote_op(MulFun(),arithtype(T), arithtype(S)), (size(A,2), size(B,1))), A, B) Ac_mul_Bc!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = gemm_wrapper!(C, 'C', 'C', A, B) Ac_mul_Bc!(C::StridedMatrix, A::StridedVecOrMat, B::StridedVecOrMat) = generic_matmatmul!(C, 'C', 'C', A, B) -Ac_mul_Bt{T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) = Ac_mul_Bt(similar(B, promote_type(arithtype(A), arithtype(B)), (size(A,2), size(B,1))), A, B) +Ac_mul_Bt{T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) = Ac_mul_Bt(similar(B, promote_op(MulFun(),arithtype(A), arithtype(B)), (size(A,2), size(B,1))), A, B) Ac_mul_Bt!(C::StridedMatrix, A::StridedVecOrMat, B::StridedVecOrMat) = generic_matmatmul!(C, 'C', 'T', A, B) # Supporting functions for matrix multiplication @@ -420,7 +420,7 @@ end function generic_matmatmul{T,S}(tA, tB, A::AbstractVecOrMat{T}, B::AbstractMatrix{S}) mA, nA = lapack_size(tA, A) mB, nB = lapack_size(tB, B) - C = similar(B, promote_type(arithtype(T),arithtype(S)), mA, nB) + C = similar(B, promote_op(MulFun(),arithtype(T),arithtype(S)), mA, nB) generic_matmatmul!(C, tA, tB, A, B) end @@ -625,7 +625,7 @@ end # multiply 2x2 matrices function matmul2x2{T,S}(tA, tB, A::AbstractMatrix{T}, B::AbstractMatrix{S}) - matmul2x2!(similar(B, promote_type(T,S), 2, 2), tA, tB, A, B) + matmul2x2!(similar(B, promote_op(MulFun(),T,S), 2, 2), tA, tB, A, B) end function matmul2x2!{T,S,R}(C::AbstractMatrix{R}, tA, tB, A::AbstractMatrix{T}, B::AbstractMatrix{S}) @@ -654,7 +654,7 @@ end # Multiply 3x3 matrices function matmul3x3{T,S}(tA, tB, A::AbstractMatrix{T}, B::AbstractMatrix{S}) - matmul3x3!(similar(B, promote_type(T,S), 3, 3), tA, tB, A, B) + matmul3x3!(similar(B, promote_op(MulFun(),T,S), 3, 3), tA, tB, A, B) end function matmul3x3!{T,S,R}(C::AbstractMatrix{R}, tA, tB, A::AbstractMatrix{T}, B::AbstractMatrix{S}) diff --git a/base/promotion.jl b/base/promotion.jl index 63e3b9a3d7606..f9a38a0f86c75 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -203,7 +203,10 @@ checked_mul(x::Integer, y::Integer) = checked_mul(promote(x,y)...) # as needed. For example, if you need to provide a custom result type # for the multiplication of two types, # promote_op{R<:MyType,S<:MyType}(::MulFun, ::Type{R}, ::Type{S}) = MyType{multype(R,S)} +promote_op(::Any) = Bottom +promote_op(::Any, T) = T promote_op{R,S}(::Any, ::Type{R}, ::Type{S}) = promote_type(R, S) +promote_op(op, T, S, U, V...) = promote_op(op, T, promote_op(op, S, U, V...)) ## catch-alls to prevent infinite recursion when definitions are missing ## diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index ec0f8f4c1aa71..37291f1061541 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -1023,7 +1023,7 @@ end # macro (.-)(A::Number, B::SparseMatrixCSC) = A .- full(B) ( -)(A::Array , B::SparseMatrixCSC) = A - full(B) -(.*)(A::AbstractArray, B::AbstractArray) = broadcast_zpreserving(*, A, B) +(.*)(A::AbstractArray, B::AbstractArray) = broadcast_zpreserving(Base.MulFun(), A, B) (.*)(A::SparseMatrixCSC, B::Number) = SparseMatrixCSC(A.m, A.n, copy(A.colptr), copy(A.rowval), A.nzval .* B) (.*)(A::Number, B::SparseMatrixCSC) = SparseMatrixCSC(B.m, B.n, copy(B.colptr), copy(B.rowval), A .* B.nzval) diff --git a/test/arrayops.jl b/test/arrayops.jl index ccccea049ee6c..0c41c798795dc 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -1233,7 +1233,7 @@ b = rand(6,7) # return type declarations (promote_op) module RetTypeDecl using Base.Test - import Base: +, *, .* + import Base: +, *, .*, zero immutable MeterUnits{T,P} <: Number val::T @@ -1243,9 +1243,11 @@ module RetTypeDecl m = MeterUnits(1.0, 1) # 1.0 meter, i.e. units of length m2 = MeterUnits(1.0, 2) # 1.0 meter^2, i.e. units of area - (+){T}(x::MeterUnits{T,1}, y::MeterUnits{T,1}) = MeterUnits{T,1}(x.val+y.val) + (+){T,pow}(x::MeterUnits{T,pow}, y::MeterUnits{T,pow}) = MeterUnits{T,pow}(x.val+y.val) + (*){T,pow}(x::Int, y::MeterUnits{T,pow}) = MeterUnits{typeof(x*one(T)),pow}(x*y.val) (*){T}(x::MeterUnits{T,1}, y::MeterUnits{T,1}) = MeterUnits{T,2}(x.val*y.val) (.*){T}(x::MeterUnits{T,1}, y::MeterUnits{T,1}) = MeterUnits{T,2}(x.val*y.val) + zero{T,pow}(x::MeterUnits{T,pow}) = MeterUnits{T,pow}(zero(T)) Base.promote_op{R,S}(::Base.AddFun, ::Type{MeterUnits{R,1}}, ::Type{MeterUnits{S,1}}) = MeterUnits{promote_type(R,S),1} Base.promote_op{R,S}(::Base.MulFun, ::Type{MeterUnits{R,1}}, ::Type{MeterUnits{S,1}}) = MeterUnits{promote_type(R,S),2} @@ -1255,6 +1257,8 @@ module RetTypeDecl @test @inferred([m,m]+m) == [m+m,m+m] @test @inferred(m.*[m,m]) == [m2,m2] @test @inferred([m,m].*m) == [m2,m2] + @test @inferred([m 2m; m m]*[m,m]) == [3m2,2m2] + @test @inferred([m m].*[m,m]) == [m2 m2; m2 m2] end # range, range ops From 617db6b7625acebb22361c63ab1d898fa3f1e1bc Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sun, 11 Oct 2015 16:56:52 -0400 Subject: [PATCH 004/106] Ignore line number node when counting expressions for inlining. Fix #13551 (cherry picked from commit 5206bcaf5cdedda465c15f6cce2a3aecaa1604c1) ref #13553 --- base/inference.jl | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 840da1b351f5c..36ddda51cfea6 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -1925,6 +1925,7 @@ end function occurs_more(e::ANY, pred, n) if isa(e,Expr) e = e::Expr + e.head === :line && return 0 c = 0 for a = e.args c += occurs_more(a, pred, n) @@ -2612,10 +2613,17 @@ function inline_worthy(body::Expr, cost::Integer=1000) # precondition: 0 < cost; return false end symlim = 1000 + 5_000_000 ÷ cost - if length(body.args) < (symlim + 500) ÷ 1000 + nargs = 0 + for arg in body.args + if (!isa(arg, LineNumberNode) && + !(isa(arg, Expr) && (arg::Expr).head === :line)) + nargs += 1 + end + end + if nargs < (symlim + 500) ÷ 1000 symlim *= 16 symlim ÷= 1000 - if occurs_more(body, e->true, symlim) < symlim + if occurs_more(body, e->(!isa(e, LineNumberNode)), symlim) < symlim return true end end @@ -2653,7 +2661,7 @@ end const corenumtype = Union{Int32,Int64,Float32,Float64} function inlining_pass(e::Expr, sv, ast) - if e.head == :method + if e.head === :method # avoid running the inlining pass on function definitions return (e,()) end From d8b91c6e42d6fa5aaec0f7c302539545db6fd354 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sun, 29 Nov 2015 14:21:35 -0500 Subject: [PATCH 005/106] Fix doctests --- base/docs/helpdb.jl | 1 + doc/devdocs/types.rst | 8 ++++++-- doc/manual/complex-and-rational-numbers.rst | 3 +++ doc/manual/constructors.rst | 2 ++ doc/manual/control-flow.rst | 7 +++++++ doc/manual/conversion-and-promotion.rst | 8 ++++++-- doc/manual/strings.rst | 2 ++ doc/manual/types.rst | 1 + doc/stdlib/collections.rst | 1 + 9 files changed, 29 insertions(+), 4 deletions(-) diff --git a/base/docs/helpdb.jl b/base/docs/helpdb.jl index f508e7399d081..f1fdd5ef068fb 100644 --- a/base/docs/helpdb.jl +++ b/base/docs/helpdb.jl @@ -6733,6 +6733,7 @@ julia> deleteat!([6, 5, 4, 3, 2, 1], 1:2:5) julia> deleteat!([6, 5, 4, 3, 2, 1], (2, 2)) ERROR: ArgumentError: indices must be unique and sorted + [inlined code] from essentials.jl:59 in deleteat! at array.jl:546 ``` """ diff --git a/doc/devdocs/types.rst b/doc/devdocs/types.rst index 1310a2e2161d5..48898e1cd2977 100644 --- a/doc/devdocs/types.rst +++ b/doc/devdocs/types.rst @@ -359,15 +359,19 @@ type: julia> MyType.name.cache svec(MyType{Float32,5},MyType{Int64,2},Evaluation succeeded, but an error occurred while showing value of type SimpleVector: ERROR: UndefRefError: access to undefined reference + [inlined code] from ./essentials.jl:30 in getindex at ./essentials.jl:211 + [inlined code] from essentials.jl:218 in show_delim_array at show.jl:229 + [inlined code] from int.jl:360 in show at show.jl:257 in anonymous at show.jl:1294 in with_output_limit at ./show.jl:1271 in showlimited at show.jl:1293 + [inlined code] from replutil.jl:4 in display at multimedia.jl:120 - [inlined code] from multimedia.jl:151 - in display at multimedia.jl:162 + [inlined code] from operators.jl:313 + in display at multimedia.jl:163 (The error is triggered because the cache is pre-allocated to have length 8, but only the first two entries are populated.) diff --git a/doc/manual/complex-and-rational-numbers.rst b/doc/manual/complex-and-rational-numbers.rst index 8274529a89b50..6d0479bc2eeb6 100644 --- a/doc/manual/complex-and-rational-numbers.rst +++ b/doc/manual/complex-and-rational-numbers.rst @@ -159,6 +159,7 @@ versus ``-1 + 0im`` even though ``-1 == -1 + 0im``: julia> sqrt(-1) ERROR: DomainError: sqrt will only return a complex result if called with a complex argument. Try sqrt(complex(x)). + [inlined code] from math.jl:144 in sqrt at math.jl:146 julia> sqrt(-1 + 0im) @@ -303,7 +304,9 @@ Trying to construct a :const:`NaN` rational value, however, is not: julia> 0//0 ERROR: ArgumentError: invalid rational: zero(Int64)//zero(Int64) + [inlined code] from strings/io.jl:43 in call at rational.jl:8 + [inlined code] from rational.jl:13 in // at rational.jl:22 As usual, the promotion system makes interactions with other numeric diff --git a/doc/manual/constructors.rst b/doc/manual/constructors.rst index 15fab79f4956d..8983e8c8c1dda 100644 --- a/doc/manual/constructors.rst +++ b/doc/manual/constructors.rst @@ -121,6 +121,7 @@ Now ``OrderedPair`` objects can only be constructed such that julia> OrderedPair(2,1) ERROR: out of order + [inlined code] from error.jl:21 in call at none:5 You can still reach in and directly change the field values to violate @@ -339,6 +340,7 @@ types of the arguments given to the constructor. Here are some examples: julia> Point{Int64}(1.0,2.5) ERROR: InexactError() + [inlined code] from int.jl:209 in call at none:2 julia> Point{Float64}(1.0,2.5) diff --git a/doc/manual/control-flow.rst b/doc/manual/control-flow.rst index 143f0de971bf7..4b56a3fb47564 100644 --- a/doc/manual/control-flow.rst +++ b/doc/manual/control-flow.rst @@ -162,6 +162,7 @@ the above function results in a runtime error julia> test(2,1) ERROR: UndefVarError: relation not defined + [inlined code] from strings/io.jl:28 in test at none:7 ``if`` blocks also return a value, which may seem unintuitive to users @@ -365,6 +366,7 @@ For example, a recursive factorial routine could be defined like this: julia> factorial(-1) ERROR: n must be non-negative + [inlined code] from error.jl:21 in factorial at none:2 @@ -661,6 +663,7 @@ negative real value: julia> sqrt(-1) ERROR: DomainError: sqrt will only return a complex result if called with a complex argument. Try sqrt(complex(x)). + [inlined code] from math.jl:144 in sqrt at math.jl:146 You may define your own exceptions in the following way: @@ -686,6 +689,7 @@ if the argument is negative: julia> f(-1) ERROR: DomainError: + [inlined code] from essentials.jl:23 in f at none:1 Note that :exc:`DomainError` without parentheses is not an exception, but a type of @@ -737,6 +741,7 @@ the :func:`sqrt` function that raises an error if its argument is negative: julia> fussy_sqrt(-1) ERROR: negative x not allowed + [inlined code] from error.jl:21 in fussy_sqrt at none:1 If ``fussy_sqrt`` is called with a negative value from another function, @@ -762,6 +767,7 @@ session: julia> verbose_fussy_sqrt(-1) before fussy_sqrt ERROR: negative x not allowed + [inlined code] from error.jl:21 in verbose_fussy_sqrt at none:3 Warnings and informational messages @@ -842,6 +848,7 @@ assumes ``x`` is a real number and returns its square root: julia> sqrt_second(-9) ERROR: DomainError: + [inlined code] from math.jl:144 in sqrt_second at none:7 Note that the symbol following ``catch`` will always be interpreted as a diff --git a/doc/manual/conversion-and-promotion.rst b/doc/manual/conversion-and-promotion.rst index 89412562dc5d1..c001da1f97484 100644 --- a/doc/manual/conversion-and-promotion.rst +++ b/doc/manual/conversion-and-promotion.rst @@ -146,7 +146,8 @@ to one and zero: julia> convert(Bool, 1im) ERROR: InexactError() - in convert at complex.jl:18 + [inlined code] from essentials.jl:25 + in convert at complex.jl:38 julia> convert(Bool, 0im) false @@ -159,9 +160,12 @@ This is the actual implementation in julia:: convert{T<:Real}(::Type{T}, z::Complex) = (imag(z)==0 ? convert(T,real(z)) : throw(InexactError())) +.. doctest:: + julia> convert(Bool, 1im) ERROR: InexactError() - in convert at complex.jl:18 + [inlined code] from essentials.jl:25 + in convert at complex.jl:38 Case Study: Rational Conversions diff --git a/doc/manual/strings.rst b/doc/manual/strings.rst index 48844b93dd290..27c019ba3e1ae 100644 --- a/doc/manual/strings.rst +++ b/doc/manual/strings.rst @@ -291,11 +291,13 @@ such an invalid byte index, an error is thrown: julia> s[2] ERROR: UnicodeError: invalid character index + [inlined code] from ./int.jl:187 in next at ./unicode/utf8.jl:65 in getindex at strings/basic.jl:37 julia> s[3] ERROR: UnicodeError: invalid character index + [inlined code] from ./int.jl:187 in next at ./unicode/utf8.jl:65 in getindex at strings/basic.jl:37 diff --git a/doc/manual/types.rst b/doc/manual/types.rst index 549b052eac272..e6640457f9094 100644 --- a/doc/manual/types.rst +++ b/doc/manual/types.rst @@ -401,6 +401,7 @@ However, the value for ``baz`` must be convertible to :class:`Int`: julia> Foo((), 23.5, 1) ERROR: InexactError() + [inlined code] from float.jl:24 in call at none:2 You may find a list of field names using the ``fieldnames`` function. diff --git a/doc/stdlib/collections.rst b/doc/stdlib/collections.rst index bcb3ab2ab2e49..9a07f313cd0d6 100644 --- a/doc/stdlib/collections.rst +++ b/doc/stdlib/collections.rst @@ -1161,6 +1161,7 @@ Dequeues julia> deleteat!([6, 5, 4, 3, 2, 1], (2, 2)) ERROR: ArgumentError: indices must be unique and sorted + [inlined code] from essentials.jl:59 in deleteat! at array.jl:546 .. function:: splice!(collection, index, [replacement]) -> item From a85dd9f9d99bc159bf3d714c7a2f03916d6a6960 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Fri, 6 Nov 2015 21:34:25 -0500 Subject: [PATCH 006/106] Non-mutating version of split_decl_rst and more restricted signature matching in genstdlib.jl Fix #13906 (cherry picked from commit 1def88912bba5b8a6897f6e42ee23cc623844087) ref #13907 --- doc/genstdlib.jl | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/doc/genstdlib.jl b/doc/genstdlib.jl index 1bf108b9f3020..04bd624d471c6 100644 --- a/doc/genstdlib.jl +++ b/doc/genstdlib.jl @@ -133,7 +133,7 @@ function tryrst(md, remove_decl) return Markdown.rst(md) catch e warn("Error converting docstring:") -# display(md) + # display(md) println(e) return end @@ -141,7 +141,7 @@ end torst(md,remove_decl) = isrst(md) ? flatten(md).content[1].code : tryrst(md, remove_decl) -function split_decl_rst(md, decl) +function split_decl_rst(md) if isrst(md) rst_text = flatten(md).content[1].code ls = split(rst_text, "\n") @@ -158,14 +158,17 @@ function split_decl_rst(md, decl) end return decl, join(ls[body_start:end], "\n") end - return decl, rst_text else if isa(md.content[1], Markdown.Code) && md.content[1].language == "" - decl = ".. function:: " * replace(shift!(md.content).code, "\n", + sigs = shift!(md.content) + decl = ".. function:: " * replace(sigs.code, "\n", "\n ") + body = Markdown.rst(md) + unshift!(md.content, sigs) + return decl, body end - return decl, Markdown.rst(md) end + return "", "" end # Disable by default since it is hard to eliminate false positives @@ -239,17 +242,19 @@ function translate(file) end end doc = nothing + decl = nothing + body = nothing for mdoc in getdoc(mod, funcname) - trst = tryrst(mdoc, false) - trst !== nothing || continue - if contains(replace(trst, r"[\n ][\n ]+", " "), - " " * replace(full, r"[\n ][\n ]+", " ")) + mdecl, mbody = split_decl_rst(mdoc) + if contains(replace(mdecl, r"[\n ][\n ]+", " "), + replace(".. function:: " * full, + r"[\n ][\n ]+", " ")) if doc != nothing error("duplicate $full $l") end doc = mdoc - else - #@show trst full + decl = mdecl + body = mbody end end if doc == nothing || torst(doc, false) == nothing @@ -262,7 +267,6 @@ function translate(file) delete!(all_docs, doc) doccing = true start_func_doc(full) - decl, body = split_decl_rst(doc, l) println(io, decl) println(io) println(io, " .. Docstring generated from Julia source\n") From f02e71dd2d97a5b7875b25f86056a5ed02d9d9d7 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 8 Nov 2015 06:39:11 -0600 Subject: [PATCH 007/106] Ensure the backtrace is shown even if we can't show method candidates (cherry picked from commit 4778f17162cbe1bf56e510c91ab02883a62d79c8) ref #13904 --- base/replutil.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/base/replutil.jl b/base/replutil.jl index fa9eacda8d615..15ebf7622f1ee 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -188,7 +188,11 @@ function showerror(io::IO, ex::MethodError) print(io, "This may have arisen from a call to the constructor $construct_type(...),", "\nsince type constructors fall back to convert methods.") end - show_method_candidates(io, ex) + try + show_method_candidates(io, ex) + catch + warn("Unable to show method candidates") + end end #Show an error by directly calling jl_printf. From 931cfbed4366ad160a5f0a7bab0f7220535d6490 Mon Sep 17 00:00:00 2001 From: dhoegh Date: Mon, 12 Oct 2015 18:21:23 +0200 Subject: [PATCH 008/106] Method completion using inference to determine the input types to remove non matching methods. Add test for the new functionality, fix #6338. (cherry picked from commit f8196cc1ca623457686101bf90f7b5f968463026) ref #11679 --- base/REPLCompletions.jl | 54 +++++++++++++++++++++++++++++++++++++++-- test/replcompletions.jl | 50 +++++++++++++++++++++++++++++++++----- 2 files changed, 96 insertions(+), 8 deletions(-) diff --git a/base/REPLCompletions.jl b/base/REPLCompletions.jl index 967340b779bf3..736288e8f3e6c 100644 --- a/base/REPLCompletions.jl +++ b/base/REPLCompletions.jl @@ -222,14 +222,64 @@ get_value(sym::Symbol, fn) = isdefined(fn, sym) ? (fn.(sym), true) : (nothing, f get_value(sym::QuoteNode, fn) = isdefined(fn, sym.value) ? (fn.(sym.value), true) : (nothing, false) get_value(sym, fn) = sym, true +# Return the value of a getfield call expression +function get_value_getfield(ex::Expr, fn) + # Example :((top(getfield))(Base,:max)) + val, found = get_value_getfield(ex.args[2],fn) #Look up Base in Main and returns the module + found || return (nothing, false) + get_value_getfield(ex.args[3],val) #Look up max in Base and returns the function if found. +end +get_value_getfield(sym, fn) = get_value(sym, fn) +# Determines the return type with Base.return_types of a function call using the type information of the arguments. +function get_type_call(expr::Expr) + f_name = expr.args[1] + # The if statement should find the f function. How f is found depends on how f is referenced + if isa(f_name, TopNode) + f = Base.(f_name.name) + found = true + elseif isa(f_name, Expr) && f_name.args[1] === TopNode(:getfield) + f, found = get_value_getfield(f_name, Main) + else + f, found = get_value(f_name, Main) + end + found || return (Any, false) # If the function f is not found return Any. + args = Any[] + for ex in expr.args[2:end] # Find the type of the function arguments + typ, found = get_type(ex, Main) + found ? push!(args, typ) : push!(args, Any) + end + return_types = Base.return_types(f,Tuple{args...}) + length(return_types) == 1 || return (Any, false) + return (return_types[1], true) +end +# Returns the return type. example: get_type(:(Base.strip("",' ')),Main) returns (ASCIIString,true) +function get_type(sym::Expr, fn) + sym=expand(sym) + val, found = get_value(sym, fn) + found && return Base.typesof(val).parameters[1], found + if sym.head === :call + # getfield call is special cased as the evaluation of getfield provides good type information, + # is inexpensive and it is also performed in the complete_symbol function. + if sym.args[1] === TopNode(:getfield) + val, found = get_value_getfield(sym, Main) + return found ? Base.typesof(val).parameters[1] : Any, found + end + return get_type_call(sym) + end + (Any, false) +end +function get_type(sym, fn) + val, found = get_value(sym, fn) + return found ? Base.typesof(val).parameters[1] : Any, found +end # Method completion on function call expression that look like :(max(1)) function complete_methods(ex_org::Expr) args_ex = DataType[] func, found = get_value(ex_org.args[1], Main) (!found || (found && !isgeneric(func))) && return UTF8String[] for ex in ex_org.args[2:end] - val, found = get_value(ex, Main) - found ? push!(args_ex, Base.typesof(val).parameters[1]) : push!(args_ex, Any) + val, found = get_type(ex, Main) + push!(args_ex, val) end out = UTF8String[] t_in = Tuple{args_ex...} # Input types diff --git a/test/replcompletions.jl b/test/replcompletions.jl index 7e9f55e7ae305..0048a3c66bdd3 100644 --- a/test/replcompletions.jl +++ b/test/replcompletions.jl @@ -33,7 +33,15 @@ module CompletionFoo test3(x::AbstractArray{Int}, y::Int) = pass test3(x::AbstractArray{Float64}, y::Float64) = pass + test4(x::AbstractString, y::AbstractString) = pass + test4(x::AbstractString, y::Regex) = pass + + test5(x::Array{Bool,1}) = pass + test5(x::BitArray{1}) = pass + test5(x::Float64) = pass + array = [1, 1] + varfloat = 0.1 end function temp_pkg_dir(fn::Function) @@ -186,7 +194,7 @@ c, r, res = test_complete(s) @test r == 1:3 @test s[r] == "max" -# Test completion of methods with input args +# Test completion of methods with input concrete args and args where typeinference determine their type s = "CompletionFoo.test(1,1, " c, r, res = test_complete(s) @test !res @@ -239,24 +247,54 @@ for (T, arg) in [(ASCIIString,"\")\""),(Char, "')'")] @test s[r] == "CompletionFoo.test2" end -# This cannot find the correct method due to the backticks expands to a macro in the parser. -# Then the function argument is an expression which is not handled by current method completion logic. s = "(1, CompletionFoo.test2(`)`," c, r, res = test_complete(s) -@test length(c) == 3 +@test c[1] == string(methods(CompletionFoo.test2, Tuple{Cmd})[1]) +@test length(c) == 1 -s = "CompletionFoo.test3([1.,2.]," +s = "CompletionFoo.test3([1, 2] + CompletionFoo.varfloat," c, r, res = test_complete(s) @test !res -@test length(c) == 2 +@test c[1] == string(methods(CompletionFoo.test3, Tuple{Array{Float64, 1}, Float64})[1]) +@test length(c) == 1 s = "CompletionFoo.test3([1.,2.], 1.," c, r, res = test_complete(s) @test !res @test c[1] == string(methods(CompletionFoo.test3, Tuple{Array{Float64, 1}, Float64})[1]) @test r == 1:19 +@test length(c) == 1 @test s[r] == "CompletionFoo.test3" +s = "CompletionFoo.test4(\"e\",r\" \"," +c, r, res = test_complete(s) +@test !res +@test c[1] == string(methods(CompletionFoo.test4, Tuple{ASCIIString, Regex})[1]) +@test r == 1:19 +@test length(c) == 1 +@test s[r] == "CompletionFoo.test4" + +s = "CompletionFoo.test5(push!(Base.split(\"\",' '),\"\",\"\").==\"\"," +c, r, res = test_complete(s) +@test !res +@test length(c) == 1 +@test c[1] == string(methods(CompletionFoo.test5, Tuple{BitArray{1}})[1]) + +########## Test where the current inference logic fails ######## +# Fails due to inferrence fails to determine a concrete type from the map +# But it returns AbstractArray{T,N} and hence is able to remove test5(x::Float64) from the suggestions +s = "CompletionFoo.test5(map(x-> x==\"\",push!(Base.split(\"\",' '),\"\",\"\"))," +c, r, res = test_complete(s) +@test !res +@test length(c) == 2 + +# equivalent to above but due to the time macro the completion fails to find the concrete type +s = "CompletionFoo.test3(@time([1, 2] + CompletionFoo.varfloat)," +c, r, res = test_complete(s) +@test !res +@test length(c) == 2 +################################################################# + # Test completion in multi-line comments s = "#=\n\\alpha" c, r, res = test_complete(s) From 18000c73f43c3368e3d503279a1b72c969985915 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 8 Nov 2015 17:03:37 -0600 Subject: [PATCH 009/106] Direct warning to io (cherry picked from commit 3e7a4019b90ebaee3dda338a90fb5510f69839cc) ref #13921 --- base/replutil.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/replutil.jl b/base/replutil.jl index 15ebf7622f1ee..3fc381fcbbc34 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -191,7 +191,7 @@ function showerror(io::IO, ex::MethodError) try show_method_candidates(io, ex) catch - warn("Unable to show method candidates") + warn(io, "Error showing method candidates, aborted") end end From d2c63f4263fff109a00c120b6dfbe2a36f8afeae Mon Sep 17 00:00:00 2001 From: Jaehyung Lee Date: Tue, 10 Nov 2015 00:11:16 +0900 Subject: [PATCH 010/106] doc: fix outdated output msg in the assert example [av skip] (cherry picked from commit e10e0393a29265c0c4a3858453c68465091bdd0c) ref #13928 --- doc/manual/metaprogramming.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual/metaprogramming.rst b/doc/manual/metaprogramming.rst index 6cbeaa42c0c8d..de3cdbafd91cc 100644 --- a/doc/manual/metaprogramming.rst +++ b/doc/manual/metaprogramming.rst @@ -545,7 +545,7 @@ This macro can be used like this: julia> @assert 1==1.0 julia> @assert 1==0 - ERROR: AssertionError: 1 == 0 + ERROR: Assertion failed: 1 == 0 In place of the written syntax, the macro call is expanded at parse time to its returned result. This is equivalent to writing:: From 81a214f70324140cf88794c0a416a94a3a9045ad Mon Sep 17 00:00:00 2001 From: Jaehyung Lee Date: Tue, 10 Nov 2015 01:30:09 +0900 Subject: [PATCH 011/106] doc: fix the assert example to be consistent with doctest output [av skip] (cherry picked from commit 8f21bd3e18efbcda6f4dcdd6b754db20ec9debab) --- doc/manual/metaprogramming.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/manual/metaprogramming.rst b/doc/manual/metaprogramming.rst index de3cdbafd91cc..128f174c05001 100644 --- a/doc/manual/metaprogramming.rst +++ b/doc/manual/metaprogramming.rst @@ -535,7 +535,7 @@ Building an advanced macro Here is a simplified definition of Julia's :obj:`@assert` macro:: macro assert(ex) - return :($ex ? nothing : error("Assertion failed: ", $(string(ex)))) + return :( $ex ? nothing : throw(AssertionError($(string(ex)))) ) end This macro can be used like this: @@ -545,13 +545,13 @@ This macro can be used like this: julia> @assert 1==1.0 julia> @assert 1==0 - ERROR: Assertion failed: 1 == 0 + ERROR: AssertionError: 1 == 0 In place of the written syntax, the macro call is expanded at parse time to its returned result. This is equivalent to writing:: - 1==1.0 ? nothing : error("Assertion failed: ", "1==1.0") - 1==0 ? nothing : error("Assertion failed: ", "1==0") + 1==1.0 ? nothing : throw(AssertionError("1==1.0")) + 1==0 ? nothing : throw(AssertionError("1==0")) That is, in the first call, the expression ``:(1==1.0)`` is spliced into the test condition slot, while the value of ``string(:(1==1.0))`` is @@ -572,8 +572,8 @@ ellipses following the last argument:: macro assert(ex, msgs...) msg_body = isempty(msgs) ? ex : msgs[1] - msg = string("assertion failed: ", msg_body) - return :($ex ? nothing : error($msg)) + msg = string(msg_body) + return :($ex ? nothing : throw(AssertionError($msg))) end Now :obj:`@assert` has two modes of operation, depending upon the number of From 6e7268733e3e5de9543e82138b3125aae72af7ed Mon Sep 17 00:00:00 2001 From: Katie Hyatt Date: Mon, 9 Nov 2015 15:33:32 -0800 Subject: [PATCH 012/106] Added tests for methodshow functions (cherry picked from commit 74980690819d27bdb1b7ec5cbd8ed49eb212b2fb) ref #13933 --- test/show.jl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/show.jl b/test/show.jl index 0fb185acbc365..8410cbb88eb6c 100644 --- a/test/show.jl +++ b/test/show.jl @@ -302,3 +302,12 @@ function f13127() takebuf_string(buf) end @test f13127() == "f" + +#test methodshow.jl functions +@test Base.inbase(Base) +@test Base.inbase(LinAlg) + +@test contains(sprint(io -> writemime(io,"text/plain",methods(Base.inbase))),"inbase(m::Module)") +@test contains(sprint(io -> writemime(io,"text/html",methods(Base.inbase))),"inbase(m::Module)") + +@test contains(Base.url(methods(eigs).defs),"https://github.com/JuliaLang/julia/tree/$(Base.GIT_VERSION_INFO.commit)/base/linalg/arnoldi.jl#L") From 5efe36c326bced3a704bb729f9590dcc0399c2f0 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Mon, 9 Nov 2015 06:30:40 -0800 Subject: [PATCH 013/106] Add release preparation script [av skip] (cherry picked from commit 59c3328e07aa0b7c50adf5becd50fd9ff9faee02) ref #13927 --- contrib/prepare_release.sh | 56 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100755 contrib/prepare_release.sh diff --git a/contrib/prepare_release.sh b/contrib/prepare_release.sh new file mode 100755 index 0000000000000..a54bfac61dd9a --- /dev/null +++ b/contrib/prepare_release.sh @@ -0,0 +1,56 @@ +#!/bin/sh +# script to prepare binaries and source tarballs for a Julia release +# aka "bucket dance" julianightlies -> julialang +set -e # stop on failure +cd "$(dirname "$0")"/.. # run in top-level directory + +shashort=$(git rev-parse --short=10 HEAD) +tag=$(git tag --points-at $shashort) +if [ -z "$tag" ]; then + echo "error: this script must be run with a tagged commit checked out" >&2 + exit 1 +fi +version=$(cat VERSION) +majmin=$(echo $version | cut -d. -f1-2) +if [ "$tag" != "v$version" ]; then + echo "error: tagged commit does not match content of VERSION file" >&2 + exit 1 +fi + +# create full-source-dist and light-source-dist tarballs from a separate +# clone to ensure the directory name in them is julia-$version +git clone https://github.com/JuliaLang/julia -b $tag julia-$version +cd julia-$version +make full-source-dist +make light-source-dist +mv julia-${version}_$shashort-full.tar.gz ../julia-$version-full.tar.gz +mv julia-${version}_$shashort.tar.gz ../julia-$version.tar.gz +cd .. +rm -rf julia-$version + +# download and rename binaries, with -latest copies +julianightlies="https://s3.amazonaws.com/julianightlies/bin" +curl -L -o julia-$version-linux-x86_64.tar.gz \ + $julianightlies/linux/x64/$majmin/julia-$version-$shashort-linux64.tar.gz +cp julia-$version-linux-x86_64.tar.gz julia-$majmin-latest-linux-x86_64.tar.gz +curl -L -o julia-$version-linux-i686.tar.gz \ + $julianightlies/linux/x86/$majmin/julia-$version-$shashort-linux32.tar.gz +cp julia-$version-linux-i686.tar.gz julia-$majmin-latest-linux-i686.tar.gz +curl -L -o "julia-$version-osx10.7 .dmg" \ + $julianightlies/osx/x64/$majmin/julia-$version-$shashort-osx.dmg +cp "julia-$version-osx10.7 .dmg" "julia-$majmin-latest-osx10.7 .dmg" +curl -L -o julia-$version-win64.exe \ + $julianightlies/winnt/x64/$majmin/julia-$version-$shashort-win64.exe +cp julia-$version-win64.exe julia-$majmin-latest-win64.exe +curl -L -o julia-$version-win32.exe \ + $julianightlies/winnt/x86/$majmin/julia-$version-$shashort-win32.exe +cp julia-$version-win32.exe julia-$majmin-latest-win32.exe + +shasum -a 256 julia-$version* | grep -v sha256 | grep -v md5 > julia-$version.sha256 +md5sum julia-$version* | grep -v sha256 | grep -v md5 > julia-$version.md5 + +echo "All files prepared. Attach julia-$version.tar.gz and julia-$version-full.tar.gz" +echo "to github releases, upload all binaries and checksums to julialang S3. Be sure" +echo "to set all S3 uploads to publicly readable, and replace $majmin-latest binaries." +# TODO: also automate uploads via aws cli and github api? +# gpg signing of linux binaries and source tarballs? From d460c68316ecf427954dfb96a11829a480c68105 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Mon, 9 Nov 2015 10:52:44 -0800 Subject: [PATCH 014/106] Add gpg signing commands You'll need access to the key and passphrase, talk to me or Elliot if the need arises [av skip] (cherry picked from commit c75d1465c590fefd46c01f976edddb93ec9e081b) --- contrib/prepare_release.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/contrib/prepare_release.sh b/contrib/prepare_release.sh index a54bfac61dd9a..4f820789417f4 100755 --- a/contrib/prepare_release.sh +++ b/contrib/prepare_release.sh @@ -11,7 +11,7 @@ if [ -z "$tag" ]; then exit 1 fi version=$(cat VERSION) -majmin=$(echo $version | cut -d. -f1-2) +majmin=$(cut -d. -f1-2 VERSION) if [ "$tag" != "v$version" ]; then echo "error: tagged commit does not match content of VERSION file" >&2 exit 1 @@ -49,8 +49,12 @@ cp julia-$version-win32.exe julia-$majmin-latest-win32.exe shasum -a 256 julia-$version* | grep -v sha256 | grep -v md5 > julia-$version.sha256 md5sum julia-$version* | grep -v sha256 | grep -v md5 > julia-$version.md5 +gpg -u julia --armor --detach-sig julia-$version-full.tar.gz +gpg -u julia --armor --detach-sig julia-$version.tar.gz +gpg -u julia --armor --detach-sig julia-$version-linux-x86_64.tar.gz +gpg -u julia --armor --detach-sig julia-$version-linux-i686.tar.gz + echo "All files prepared. Attach julia-$version.tar.gz and julia-$version-full.tar.gz" echo "to github releases, upload all binaries and checksums to julialang S3. Be sure" echo "to set all S3 uploads to publicly readable, and replace $majmin-latest binaries." # TODO: also automate uploads via aws cli and github api? -# gpg signing of linux binaries and source tarballs? From 08d9c7f022c768cce0b1bb6398c8138da10b7eb7 Mon Sep 17 00:00:00 2001 From: Peter Colberg Date: Mon, 9 Nov 2015 23:56:56 -0500 Subject: [PATCH 015/106] Fix socket test on read-only file system The socket test hangs if the directory containing the tests is not writable to the user running the tests. Create socket in a temporary directory that is removed upon exiting the scope. (cherry picked from commit 7149d1a580b902f6d33c58bd574eefb673688807) ref #13934 --- test/socket.jl | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/test/socket.jl b/test/socket.jl index 1810dfac1f1d7..a07022aea43fd 100644 --- a/test/socket.jl +++ b/test/socket.jl @@ -86,22 +86,22 @@ wait(port) @test readall(connect(fetch(port))) == "Hello World\n" * ("a1\n"^100) wait(tsk) -socketname = (@windows ? "\\\\.\\pipe\\uv-test" : "testsocket") * "-" * randstring(6) -@unix_only isfile(socketname) && Base.FS.unlink(socketname) - -c=Base.Condition() -for T in (ASCIIString, UTF8String, UTF16String) # test for issue #9435 - tsk = @async begin - s = listen(T(socketname)) - Base.notify(c) - sock = accept(s) - write(sock,"Hello World\n") - close(s) - close(sock) +mktempdir() do tmpdir + socketname = @windows ? ("\\\\.\\pipe\\uv-test-" * randstring(6)) : joinpath(tmpdir, "socket") + c = Base.Condition() + for T in (ASCIIString, UTF8String, UTF16String) # test for issue #9435 + tsk = @async begin + s = listen(T(socketname)) + Base.notify(c) + sock = accept(s) + write(sock,"Hello World\n") + close(s) + close(sock) + end + wait(c) + @test readall(connect(socketname)) == "Hello World\n" + wait(tsk) end - wait(c) - @test readall(connect(socketname)) == "Hello World\n" - wait(tsk) end @test_throws Base.UVError getaddrinfo(".invalid") From ebe11ae74c90f40c1d0a8277c8bcb64ce8c6d335 Mon Sep 17 00:00:00 2001 From: Katie Hyatt Date: Tue, 10 Nov 2015 16:14:13 -0800 Subject: [PATCH 016/106] Pair IO test (cherry picked from commit c829f84a5712a2ebf2f831810e1f2b384b5a4549) ref #13943 --- test/show.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/show.jl b/test/show.jl index 8410cbb88eb6c..6a93bbd81a9d5 100644 --- a/test/show.jl +++ b/test/show.jl @@ -303,6 +303,13 @@ function f13127() end @test f13127() == "f" +let a = Pair(1.0,2.0) + @test sprint(show,a) == "1.0=>2.0" +end +let a = Pair(Pair(1,2),Pair(3,4)) + @test sprint(show,a) == "(1=>2)=>(3=>4)" +end + #test methodshow.jl functions @test Base.inbase(Base) @test Base.inbase(LinAlg) From 6d2b7664652de2c4bf053a892a64b7a4795e1a9a Mon Sep 17 00:00:00 2001 From: Marius Hoch Date: Sat, 25 Jul 2015 05:36:52 +0200 Subject: [PATCH 017/106] Also complete commands (files in the env path) in REPL shell mode Tested on Fedora only. (cherry picked from commit 5b12348c1ea39f590ae9de48376af6e80a274db0) ref #12307 --- base/REPLCompletions.jl | 39 ++++++++++++++++++++++++++++++++++++--- test/replcompletions.jl | 18 ++++++++++++++++++ 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/base/REPLCompletions.jl b/base/REPLCompletions.jl index 736288e8f3e6c..03b4d89f47f34 100644 --- a/base/REPLCompletions.jl +++ b/base/REPLCompletions.jl @@ -109,7 +109,7 @@ function complete_keyword(s::ByteString) sorted_keywords[r] end -function complete_path(path::AbstractString, pos) +function complete_path(path::AbstractString, pos; use_envpath=false) if Base.is_unix(OS_NAME) && ismatch(r"^~(?:/|$)", path) # if the path is just "~", don't consider the expanded username as a prefix if path == "~" @@ -141,6 +141,38 @@ function complete_path(path::AbstractString, pos) push!(matches, id ? file * (@windows? "\\\\" : "/") : file) end end + + if use_envpath && length(dir) == 0 + # Look for files in PATH as well + local pathdirs = split(ENV["PATH"], @unix? ":" : ";") + + for pathdir in pathdirs + local actualpath + try + actualpath = realpath(pathdir) + catch + # Bash doesn't expect every folder in PATH to exist, so neither shall we + continue + end + + if actualpath != pathdir && in(actualpath,pathdirs) + # Remove paths which (after resolving links) are in the env path twice. + # Many distros eg. point /bin to /usr/bin but have both in the env path. + continue + end + + local filesinpath = readdir(pathdir) + + for file in filesinpath + # In a perfect world, we would filter on whether the file is executable + # here, or even on whether the current user can execute the file in question. + if startswith(file, prefix) && isfile(joinpath(pathdir, file)) + push!(matches, file) + end + end + end + end + matches = UTF8String[replace(s, r"\s", "\\ ") for s in matches] startpos = pos - endof(prefix) + 1 - length(matchall(r" ", prefix)) # The pos - endof(prefix) + 1 is correct due to `endof(prefix)-endof(prefix)==0`, @@ -440,8 +472,9 @@ function shell_completions(string, pos) isempty(args.args[end].args) && return UTF8String[], 0:-1, false arg = args.args[end].args[end] if all(s -> isa(s, AbstractString), args.args[end].args) - # Treat this as a path (perhaps give a list of commands in the future as well?) - return complete_path(join(args.args[end].args), pos) + # Treat this as a path + # Also try looking into the env path if the user wants to complete the first argument + return complete_path(join(args.args[end].args), pos, use_envpath=length(args.args) < 2) elseif isexpr(arg, :escape) && (isexpr(arg.args[1], :incomplete) || isexpr(arg.args[1], :error)) r = first(last_parse):prevind(last_parse, last(last_parse)) partial = scs[r] diff --git a/test/replcompletions.jl b/test/replcompletions.jl index 0048a3c66bdd3..a7b5d4c2450b1 100644 --- a/test/replcompletions.jl +++ b/test/replcompletions.jl @@ -446,6 +446,24 @@ c, r, res = test_scomplete(s) c,r = test_complete(s) rm(dir) end + + # Tests detecting of files in the env path (in shell mode) + let + oldpath = ENV["PATH"] + path = tempdir() + ENV["PATH"] = path + file = joinpath(path, "tmp-executable") + touch(file) + chmod(file, 0o755) + s = "tmp-execu" + c,r = test_scomplete(s) + @test "tmp-executable" in c + @test r == 1:9 + @test s[r] == "tmp-execu" + rm(file) + ENV["PATH"] = oldpath + end + end let #test that it can auto complete with spaces in file/path From 9ee16ff35852f7d64f2652167411e9307e6a1419 Mon Sep 17 00:00:00 2001 From: Carlo Baldassi Date: Tue, 10 Nov 2015 23:53:48 -0500 Subject: [PATCH 018/106] Inline set_index!(::BitArray, ::Any, ::Int) Addresses #13914 (cherry picked from commit 73242ec0e10ee7c0b4b012cc1ee5abf004276131) ref #13946 --- base/bitarray.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/bitarray.jl b/base/bitarray.jl index 68cccfa435f17..aa56d91830b0b 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -367,7 +367,7 @@ end end end -setindex!(B::BitArray, x, i::Int) = (checkbounds(B, i); unsafe_setindex!(B, x, i)) +@inline setindex!(B::BitArray, x, i::Int) = (checkbounds(B, i); unsafe_setindex!(B, x, i)) @inline function unsafe_setindex!(B::BitArray, x, i::Int) unsafe_bitsetindex!(B.chunks, convert(Bool, x), i) return B From fc193543cb986405b991e2700630d36991390d86 Mon Sep 17 00:00:00 2001 From: Carlo Baldassi Date: Thu, 12 Nov 2015 00:09:30 -0500 Subject: [PATCH 019/106] Speed up BitArray packing Changes in convert(::BitArray, ::AbstractArray) and dumpbitcache(): * avoid branches in for loops * pack 8 Bools at a time * use inbounds (cherry picked from commit d7cd0235259128a6eef8aa8087ce43a0aa2dc86e) --- base/bitarray.jl | 8 ++------ base/broadcast.jl | 28 +++++++++++++++++++++++----- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/base/bitarray.jl b/base/bitarray.jl index aa56d91830b0b..bc3e283a011b0 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -310,21 +310,17 @@ function convert{T,N}(::Type{BitArray{N}}, A::AbstractArray{T,N}) ind = 1 @inbounds begin for i = 1:length(Bc)-1 - u = UInt64(1) c = UInt64(0) for j = 0:63 - A[ind]!=0 && (c |= u) + c |= (UInt64(A[ind] != 0) << j) ind += 1 - u <<= 1 end Bc[i] = c end - u = UInt64(1) c = UInt64(0) for j = 0:_mod64(l-1) - A[ind]!=0 && (c |= u) + c |= (UInt64(A[ind] != 0) << j) ind += 1 - u <<= 1 end Bc[end] = c end diff --git a/base/broadcast.jl b/base/broadcast.jl index 32666ed6a32c8..efb0eb1173c5b 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -103,16 +103,34 @@ end const bitcache_chunks = 64 # this can be changed const bitcache_size = 64 * bitcache_chunks # do not change this +function bpack(z::UInt64) + z |= z >>> 7 + z |= z >>> 14 + z |= z >>> 28 + z &= 0xFF + return z +end + function dumpbitcache(Bc::Vector{UInt64}, bind::Int, C::Vector{Bool}) ind = 1 nc = min(bitcache_chunks, length(Bc)-bind+1) - for i = 1:nc - u = UInt64(1) + C8 = reinterpret(UInt64, C) + nc8 = (nc >>> 3) << 3 + @inbounds for i = 1:nc8 + c = UInt64(0) + for j = 0:8:63 + c |= (bpack(C8[ind]) << j) + ind += 1 + end + Bc[bind] = c + bind += 1 + end + ind = (ind-1) << 3 + 1 + @inbounds for i = (nc8+1):nc c = UInt64(0) - for j = 1:64 - C[ind] && (c |= u) + for j = 0:63 + c |= (UInt64(C[ind]) << j) ind += 1 - u <<= 1 end Bc[bind] = c bind += 1 From 1b6b76198a9c9ca58a00a1aede7d4e71672d6944 Mon Sep 17 00:00:00 2001 From: Carlo Baldassi Date: Thu, 12 Nov 2015 01:39:48 -0500 Subject: [PATCH 020/106] Avoid branching in unsafe_bitsetindex! (cherry picked from commit 7fee9ab31e5ef1812279b13c036da620755b93f6) --- base/bitarray.jl | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/base/bitarray.jl b/base/bitarray.jl index bc3e283a011b0..9e4c8b0c38ea8 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -355,11 +355,8 @@ end i1, i2 = get_chunks_id(i) u = UInt64(1) << i2 @inbounds begin - if x - Bc[i1] |= u - else - Bc[i1] &= ~u - end + c = Bc[i1] + Bc[i1] = ifelse(x, c | u, c & ~u) end end @@ -413,11 +410,7 @@ function unsafe_setindex!(B::BitArray, X::AbstractArray, I::BitArray) if Imsk & u != 0 lx < c && throw_setindex_mismatch(X, c) x = convert(Bool, unsafe_getindex(X, c)) - if x - C |= u - else - C &= ~u - end + C = ifelse(x, C | u, C & ~u) c += 1 end u <<= 1 From 53706c3e30991d418a241b9d8145584fa1abb4a4 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Wed, 11 Nov 2015 17:18:25 -0500 Subject: [PATCH 021/106] Fix url(::Method) for no-git builds might be able to come up with better options for builds of prereleases? (cherry picked from commit 0f2f4513c83b0bbe8b6b7520cfb7288bf4c72c2e) ref #13953 --- base/methodshow.jl | 7 ++++++- test/show.jl | 6 +++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/base/methodshow.jl b/base/methodshow.jl index 815d1510cff9e..a9d303534a16f 100644 --- a/base/methodshow.jl +++ b/base/methodshow.jl @@ -97,7 +97,12 @@ function url(m::Method) line = m.func.code.line line <= 0 || ismatch(r"In\[[0-9]+\]", file) && return "" if inbase(M) - return "https://github.com/JuliaLang/julia/tree/$(Base.GIT_VERSION_INFO.commit)/base/$file#L$line" + if isempty(Base.GIT_VERSION_INFO.commit) + # this url will only work if we're on a tagged release + return "https://github.com/JuliaLang/julia/tree/v$VERSION/base/$file#L$line" + else + return "https://github.com/JuliaLang/julia/tree/$(Base.GIT_VERSION_INFO.commit)/base/$file#L$line" + end else try d = dirname(file) diff --git a/test/show.jl b/test/show.jl index 6a93bbd81a9d5..80f473abdd6d1 100644 --- a/test/show.jl +++ b/test/show.jl @@ -317,4 +317,8 @@ end @test contains(sprint(io -> writemime(io,"text/plain",methods(Base.inbase))),"inbase(m::Module)") @test contains(sprint(io -> writemime(io,"text/html",methods(Base.inbase))),"inbase(m::Module)") -@test contains(Base.url(methods(eigs).defs),"https://github.com/JuliaLang/julia/tree/$(Base.GIT_VERSION_INFO.commit)/base/linalg/arnoldi.jl#L") +if isempty(Base.GIT_VERSION_INFO.commit) + @test contains(Base.url(methods(eigs).defs),"https://github.com/JuliaLang/julia/tree/v$VERSION/base/linalg/arnoldi.jl#L") +else + @test contains(Base.url(methods(eigs).defs),"https://github.com/JuliaLang/julia/tree/$(Base.GIT_VERSION_INFO.commit)/base/linalg/arnoldi.jl#L") +end From e880b3bdc188e44ae3801dd2ae095946b3be5cb6 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sun, 29 Nov 2015 16:00:22 -0500 Subject: [PATCH 022/106] add license to prepare_release.sh --- contrib/prepare_release.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contrib/prepare_release.sh b/contrib/prepare_release.sh index 4f820789417f4..0d564ab163f07 100755 --- a/contrib/prepare_release.sh +++ b/contrib/prepare_release.sh @@ -1,4 +1,6 @@ #!/bin/sh +# This file is a part of Julia. License is MIT: http://julialang.org/license + # script to prepare binaries and source tarballs for a Julia release # aka "bucket dance" julianightlies -> julialang set -e # stop on failure From cc31d44afe5e713c8b72c92a0b9a94a191984a65 Mon Sep 17 00:00:00 2001 From: Katie Hyatt Date: Fri, 13 Nov 2015 18:33:38 -0800 Subject: [PATCH 023/106] Few more math tests (cherry picked from commit 3a9e9941fa460a4e0fcb142e7c0939c5d07a2f84) ref #13985 --- test/math.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/math.jl b/test/math.jl index c7781daa89e25..9c53689e75ff5 100644 --- a/test/math.jl +++ b/test/math.jl @@ -166,12 +166,15 @@ for T in (Float32, Float64) @test isnan(log1p(convert(T,NaN))) @test_throws DomainError log1p(convert(T,-2.0)) end +@test_approx_eq exp10(5) exp10(5.0) for T in (Int, Float64, BigFloat) @test_approx_eq deg2rad(T(180)) 1pi @test_approx_eq deg2rad(T[45, 60]) [pi/T(4), pi/T(3)] @test_approx_eq rad2deg([pi/T(4), pi/T(3)]) [45, 60] @test_approx_eq rad2deg(T(1)*pi) 180 + @test_approx_eq rad2deg(T(1)) rad2deg(true) + @test_approx_eq deg2rad(T(1)) deg2rad(true) end # degree-based trig functions From 80724ac1ef04e3da7f2d55aa9fe14c0048f7346b Mon Sep 17 00:00:00 2001 From: Katie Hyatt Date: Fri, 13 Nov 2015 18:34:02 -0800 Subject: [PATCH 024/106] Show and intersection tests (cherry picked from commit adff4be374695f5ab1a5378e0f47611075fdd132) --- test/ranges.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/ranges.jl b/test/ranges.jl index a4a53ed49cc02..e0cdd346ffdb3 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -108,6 +108,12 @@ end @test intersect(reverse(typemin(Int):2:typemax(Int)),typemin(Int):2:typemax(Int)) == reverse(typemin(Int):2:typemax(Int)) @test intersect(typemin(Int):2:typemax(Int),reverse(typemin(Int):2:typemax(Int))) == typemin(Int):2:typemax(Int) +@test intersect(UnitRange(1,2),3) == UnitRange(3,2) +@test intersect(UnitRange(1,2), UnitRange(1,5), UnitRange(3,7), UnitRange(4,6)) == UnitRange(4,3) + +@test sort(UnitRange(1,2)) == UnitRange(1,2) +@test sort!(UnitRange(1,2)) == UnitRange(1,2) + @test 0 in UInt(0):100:typemax(UInt) @test last(UInt(0):100:typemax(UInt)) in UInt(0):100:typemax(UInt) @test -9223372036854775790 in -9223372036854775790:100:9223372036854775710 @@ -237,6 +243,7 @@ end @test (1:2:6) + 0.3 == 1+0.3:2:5+0.3 @test (1:2:6) - 1 == 0:2:4 @test (1:2:6) - 0.3 == 1-0.3:2:5-0.3 +@test 2 .- (1:3) == 1:-1:-1 # operations between ranges and arrays @test all(([1:5;] + (5:-1:1)) .== 6) @@ -517,6 +524,8 @@ end @test convert(StepRange, 0:5) === 0:1:5 @test convert(StepRange{Int128,Int128}, 0.:5) === Int128(0):Int128(1):Int128(5) +@test_throws ArgumentError StepRange(1.1,1,5.1) + @test promote(0f0:inv(3f0):1f0, 0.:2.:5.) === (0:1/3:1, 0.:2.:5.) @test convert(FloatRange{Float64}, 0:1/3:1) === 0:1/3:1 @test convert(FloatRange{Float64}, 0f0:inv(3f0):1f0) === 0:1/3:1 @@ -544,6 +553,9 @@ for x in r end @test i == 7 +@test sprint(io -> show(io,UnitRange(1,2))) == "1:2" +@test sprint(io -> show(io,StepRange(1,2,5))) == "1:2:5" + # Issue 11049 and related @test promote(linspace(0f0, 1f0, 3), linspace(0., 5., 2)) === (linspace(0., 1., 3), linspace(0., 5., 2)) From cd06a1fffb039e19da55052d095f5207be75fe68 Mon Sep 17 00:00:00 2001 From: Katie Hyatt Date: Fri, 13 Nov 2015 18:34:11 -0800 Subject: [PATCH 025/106] isprime for various int types (cherry picked from commit b2459a64da9e6b3832168915bb63dd46701ba6f6) --- test/numbers.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/numbers.jl b/test/numbers.jl index 907157acf52c4..e58d16d6cd14b 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -2126,6 +2126,11 @@ end @test !isprime(0xffffffffffffffc7) @test !isprime(0xffffffffffffffc9) +for T in [Int8,UInt8,Int16,UInt16,Int128,UInt128] + @test isprime(T(2)) + @test !isprime(T(4)) +end + # issue #5210 @test prod([ k^v for (k,v) in factor(typemax(UInt32)) ]) == typemax(UInt32) @test prod([ k^v for (k,v) in factor(typemax(Int8)) ]) == typemax(Int8) From 4affae3adaa01f3500c2012714ac493a4620278c Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Fri, 13 Nov 2015 12:44:29 -0500 Subject: [PATCH 026/106] Fix type instability in push! (cherry picked from commit c017f2486068dfb6c59232e208a2b961c35332a3) ref #13977 --- base/array.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/array.jl b/base/array.jl index 51ffb9e055735..4b0d387847cd3 100644 --- a/base/array.jl +++ b/base/array.jl @@ -429,9 +429,9 @@ end function push!{T}(a::Array{T,1}, item) # convert first so we don't grow the array if the assignment won't work - item = convert(T, item) + itemT = convert(T, item) ccall(:jl_array_grow_end, Void, (Any, UInt), a, 1) - a[end] = item + a[end] = itemT return a end From 5b48286996e36bec7324c497cee7d73b31bd3065 Mon Sep 17 00:00:00 2001 From: Andreas Scheidegger Date: Fri, 13 Nov 2015 19:51:32 +0100 Subject: [PATCH 027/106] correct sub2ind_loop() example (cherry picked from commit 627e68168b5cbba15f1c2305f01538353e43388c) ref #13978 --- doc/manual/metaprogramming.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual/metaprogramming.rst b/doc/manual/metaprogramming.rst index 128f174c05001..0b193eb099d27 100644 --- a/doc/manual/metaprogramming.rst +++ b/doc/manual/metaprogramming.rst @@ -1036,7 +1036,7 @@ indices - in other words, to calculate the index ``i`` that can be used to index into an array ``A`` using ``A[i]``, instead of ``A[x,y,z,...]``. One possible implementation is the following:: - function sub2ind_loop(dims::NTuple{N}, I::Integer...) + function sub2ind_loop{N}(dims::NTuple{N}, I::Integer...) ind = I[N] - 1 for i = N-1:-1:1 ind = I[i]-1 + dims[i]*ind From 11cb84906e657621141b0a0eb45efbf447985a1d Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sat, 14 Nov 2015 08:05:42 -0500 Subject: [PATCH 028/106] Also check finalizer_list_marked list in jl_finalize. Fix #13986 (cherry picked from commit 820601f766329be357b1bd8cb95354b47fdf696e) ref #13988 --- src/gc.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/gc.c b/src/gc.c index c02bbbd20a2c3..32b6b704649c4 100644 --- a/src/gc.c +++ b/src/gc.c @@ -333,26 +333,26 @@ static void run_finalizer(jl_value_t *o, jl_value_t *ff) } } -static int finalize_object(jl_value_t *o) +static void finalize_object(arraylist_t *list, jl_value_t *o) { - int success = 0; + /* int success = 0; */ jl_value_t *f = NULL; JL_GC_PUSH1(&f); - for(int i = 0; i < finalizer_list.len; i+=2) { - if (o == (jl_value_t*)finalizer_list.items[i]) { - f = (jl_value_t*)finalizer_list.items[i+1]; - if (i < finalizer_list.len - 2) { - finalizer_list.items[i] = finalizer_list.items[finalizer_list.len-2]; - finalizer_list.items[i+1] = finalizer_list.items[finalizer_list.len-1]; + for(int i = 0; i < list->len; i+=2) { + if (o == (jl_value_t*)list->items[i]) { + f = (jl_value_t*)list->items[i+1]; + if (i < list->len - 2) { + list->items[i] = list->items[list->len-2]; + list->items[i+1] = list->items[list->len-1]; i -= 2; } - finalizer_list.len -= 2; + list->len -= 2; run_finalizer(o, f); - success = 1; + /* success = 1; */ } } JL_GC_POP(); - return success; + /* return success; */ } static void run_finalizers(void) @@ -404,7 +404,10 @@ DLLEXPORT void jl_gc_add_finalizer(jl_value_t *v, jl_function_t *f) void jl_finalize(jl_value_t *o) { - (void)finalize_object(o); + // No need to check the to_finalize list since the user is apparently + // still holding a reference to the object + finalize_object(&finalizer_list, o); + finalize_object(&finalizer_list_marked, o); } static region_t *find_region(void *ptr, int maybe) From 2df6a670779b030fe69564f62444d02f9366ca76 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sat, 14 Nov 2015 08:43:22 -0500 Subject: [PATCH 029/106] Add test for old gen finalizer (cherry picked from commit 7ddd164a5e5830f001d3e09635d206a36f8b79d0) also pull in a new test in test/core.jl because why not, it seems to pass --- test/core.jl | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/core.jl b/test/core.jl index eaaf75a998fa5..ecae3a3a8f1ca 100644 --- a/test/core.jl +++ b/test/core.jl @@ -3415,3 +3415,29 @@ f11327{T}(::Type{T},x::T) = x let T=TypeVar(:T,true) @test typeintersect(Tuple{Type{T},T}, Tuple{Type{Type{Float64}},Type{Int}}) === Union{} end + +# issue 13855 +@eval @noinline function foo13855(x) + $(Expr(:localize, :(() -> () -> x))) +end +@test foo13855(Base.AddFun())() == Base.AddFun() +@test foo13855(Base.MulFun())() == Base.MulFun() + +# check if finalizers for the old gen can be triggered manually +# issue #13986 +let + obj = Ref(1) + finalized = 0 + finalizer(obj, (obj) -> (finalized = 1)) + # obj should be marked for promotion after the second gc and be promoted + # after the third GC + # GC_CLEAN; age = 0 + gc(false) + # GC_CLEAN; age = 1 + gc(false) + # GC_QUEUED; age = 1 + gc(false) + # GC_MARKED; age = 1 + finalize(obj) + @test finalized == 1 +end From 15bf60d40e37fb9ff490d24990ffc9733a29edde Mon Sep 17 00:00:00 2001 From: kshyatt Date: Sat, 14 Nov 2015 13:51:04 -0800 Subject: [PATCH 030/106] Tests for OS symbols and windows versions (cherry picked from commit fc1c9be8a260acb2e17d5d3c4fe03d8f9e257b17) ref #13992 --- test/misc.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/misc.jl b/test/misc.jl index 2c76e387ace96..67b9d42837d7e 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -193,3 +193,8 @@ catch ex end @test isa(ex, ErrorException) && ex.msg == "cannot assign variables in other modules" end + +@test Base.is_unix(:Darwin) +@test Base.is_unix(:FreeBSD) +@test_throws ArgumentError Base.is_unix(:BeOS) +@unix_only @test Base.windows_version() == (0,0) From a534db044ad196f3e249fcf879233653da03e9e7 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Sat, 14 Nov 2015 13:51:22 -0800 Subject: [PATCH 031/106] Tests for issparse and indtype (cherry picked from commit 572780aadb6a4cd346f1b376a428c0c2c0933dc5) use SparseMatrix rather than SparseArrays for release-0.4 --- test/sparsedir/sparse.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/sparsedir/sparse.jl b/test/sparsedir/sparse.jl index 4cbba2adfc14c..8483fefcbdb51 100644 --- a/test/sparsedir/sparse.jl +++ b/test/sparsedir/sparse.jl @@ -2,6 +2,10 @@ using Base.Test +@test issparse(sparse(ones(5,5))) +@test !issparse(ones(5,5)) +@test Base.SparseMatrix.indtype(sparse(ones(Int8,2),ones(Int8,2),rand(2))) == Int8 + # check sparse matrix construction @test isequal(full(sparse(complex(ones(5,5),ones(5,5)))), complex(ones(5,5),ones(5,5))) From cb2aa46c794c5338178e8753f929d8cbb9ec0b1d Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Fri, 13 Nov 2015 07:04:06 -0600 Subject: [PATCH 032/106] Add a brief summary of the process of submitting Pkg PRs This is in addition to, not a replacement of, the detailed description. Hopefully having something brief will lower the barrier to contributions. (cherry picked from commit 47d4569e8a8372ca03c557f19c43a09f33f271e4) ref #13973 --- doc/manual/packages.rst | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/doc/manual/packages.rst b/doc/manual/packages.rst index 6b652024ba70c..9e485a32bf093 100644 --- a/doc/manual/packages.rst +++ b/doc/manual/packages.rst @@ -370,9 +370,35 @@ want to make (this is your *commit message*), and then hit "Propose file change." Your changes will be submitted for consideration by the package owner(s) and collaborators. +For larger documentation changes---and especially ones that you expect +to have to update in response to feedback---you might find it easier +to use the procedure for code changes described below. + Code changes ~~~~~~~~~~~~ +Executive summary +^^^^^^^^^^^^^^^^^ + +Here we assume you've already set up git on your local machine and +have a GitHub account (see above). Let's imagine you're fixing a bug +in the Images package:: + + Pkg.checkout("Images") # check out the master branch + + cd(Pkg.dir("Images")) + ;git checkout -b myfixes # create a branch for your changes + # be sure to add a test for your bug + Pkg.test("Images") # make sure everything works now + ;git commit -a -m "Fix foo by calling bar" # write a descriptive message + Pkg.submit("Images") + +The last line will present you with a link to submit a pull request +to incorporate your changes. + +Detailed description +^^^^^^^^^^^^^^^^^^^^ + If you want to fix a bug or add new functionality, you want to be able to test your changes before you submit them for consideration. You also need to have an easy way to update your proposal in response to From bb90989b504edd9a25f0fbe466a6270ef8ad7c10 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 28 Sep 2015 02:22:38 -0400 Subject: [PATCH 033/106] avoid running finish_task inside of throw_internal if throw_internal is running from the segv_handler, there might not be enough stack to run arbitrary functions this change, therefore, makes stack overflow in tasks more reliable (cherry picked from commit ca9d5e7d1fd219f8799602ce0eee6844635c3272) ref #13963 --- src/task.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/task.c b/src/task.c index cf9f3715befdc..f2cde6166ae61 100644 --- a/src/task.c +++ b/src/task.c @@ -232,12 +232,26 @@ static void throw_if_exception_set(jl_task_t *t) } } -static void NOINLINE NORETURN start_task() +static void record_backtrace(void); +static void NOINLINE NORETURN start_task(void) { // this runs the first time we switch to a task jl_task_t *t = jl_current_task; - throw_if_exception_set(t); - jl_value_t *res = jl_apply(t->start, NULL, 0); + jl_value_t *res; + if (t->exception != NULL && t->exception != jl_nothing) { + record_backtrace(); + res = t->exception; + } + else { + JL_TRY { + res = jl_apply(t->start, NULL, 0); + } + JL_CATCH { + res = jl_exception_in_transit; + t->exception = res; + jl_gc_wb(t, res); + } + } finish_task(t, res); abort(); } @@ -795,17 +809,11 @@ void NORETURN throw_internal(jl_value_t *e) jl_longjmp(jl_current_task->eh->eh_ctx, 1); } else { - if (jl_current_task == jl_root_task) { - jl_printf(JL_STDERR, "fatal: error thrown and no exception handler available.\n"); - jl_static_show(JL_STDERR, e); - jl_printf(JL_STDERR, "\n"); - jlbacktrace(); - jl_exit(1); - } - jl_current_task->exception = e; - jl_gc_wb(jl_current_task, e); - finish_task(jl_current_task, e); - assert(0); + jl_printf(JL_STDERR, "fatal: error thrown and no exception handler available.\n"); + jl_static_show(JL_STDERR, e); + jl_printf(JL_STDERR, "\n"); + jlbacktrace(); + jl_exit(1); } assert(0); } From 2ceec969c38dad2a2902963761af1fa79bb44026 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Sat, 14 Nov 2015 17:21:06 +0100 Subject: [PATCH 034/106] Fix zip() to return a tuple even when passed a single argument This wasn't the case since eaf5a959. Returning a tuple in all cases is required to allow handling all cases with the same code. Also add tests since a large portion of the Zip code was not covered. (cherry picked from commit f58149cadb0e9d6f6f0e0f0bf0de45804683ca7a) ref #13990 --- base/iterator.jl | 14 +++++++++++++- test/functional.jl | 16 ++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/base/iterator.jl b/base/iterator.jl index d3f76c1e83f0c..9e00c94ec2a9d 100644 --- a/base/iterator.jl +++ b/base/iterator.jl @@ -23,11 +23,23 @@ eltype{I}(::Type{Enumerate{I}}) = Tuple{Int, eltype(I)} abstract AbstractZipIterator +immutable Zip1{I} <: AbstractZipIterator + a::I +end +zip(a) = Zip1(a) +length(z::Zip1) = length(z.a) +eltype{I}(::Type{Zip1{I}}) = Tuple{eltype(I)} +start(z::Zip1) = (start(z.a),) +function next(z::Zip1, st) + n = next(z.a,st[1]) + return ((n[1],), (n[2],)) +end +done(z::Zip1, st) = done(z.a,st[1]) + immutable Zip2{I1, I2} <: AbstractZipIterator a::I1 b::I2 end -zip(a) = a zip(a, b) = Zip2(a, b) length(z::Zip2) = min(length(z.a), length(z.b)) eltype{I1,I2}(::Type{Zip2{I1,I2}}) = Tuple{eltype(I1), eltype(I2)} diff --git a/test/functional.jl b/test/functional.jl index 9df37f2d4c52f..5c80224004123 100644 --- a/test/functional.jl +++ b/test/functional.jl @@ -42,6 +42,22 @@ end # issue #4718 @test collect(filter(x->x[1], zip([true, false, true, false],"abcd"))) == [(true,'a'),(true,'c')] +let z = zip(1:2) + @test collect(z) == [(1,), (2,)] + # Issue #13979 + @test eltype(z) == Tuple{Int} +end + +let z = zip(1:2, 3:4) + @test collect(z) == [(1,3), (2,4)] + @test eltype(z) == Tuple{Int,Int} +end + +let z = zip(1:2, 3:4, 5:6) + @test collect(z) == [(1,3,5), (2,4,6)] + @test eltype(z) == Tuple{Int,Int,Int} +end + # enumerate (issue #6284) let b = IOBuffer("1\n2\n3\n"), a = [] for (i,x) in enumerate(eachline(b)) From 0e5231f725f71399be8723f689aab53c7281006f Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Mon, 16 Nov 2015 12:26:07 -0500 Subject: [PATCH 035/106] Do not use system libunwind (0.99) on Travis Linux This seems to fix the lin32 SegFault after the ReadOnlyMemoryError() test. (cherry picked from commit 74d01baab59d079a178985805c3f011029f116e3) ref #14020 --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 20c1212e75fd5..1388c63a907cc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,7 +26,7 @@ before_install: sudo apt-get install jq -y; contrib/travis_fastfail.sh || exit 1; BUILDOPTS="-j3 USEGCC=1 LLVM_CONFIG=llvm-config-3.3 VERBOSE=1 USE_BLAS64=0 FORCE_ASSERTIONS=1 STAGE2_DEPS=utf8proc"; - for lib in LLVM SUITESPARSE ARPACK BLAS FFTW LAPACK GMP MPFR LIBUNWIND OPENLIBM; do + for lib in LLVM SUITESPARSE ARPACK BLAS FFTW LAPACK GMP MPFR OPENLIBM; do export BUILDOPTS="$BUILDOPTS USE_SYSTEM_$lib=1"; done; sudo add-apt-repository ppa:staticfloat/julia-deps -y; @@ -35,9 +35,9 @@ before_install: export BUILDOPTS="$BUILDOPTS MARCH=pentium4"; sudo apt-get remove libblas3gf liblapack3gf libarmadillo2 -y; sudo apt-get install binutils:i386 -y; - sudo apt-get install gcc:i386 g++:i386 make:i386 cpp:i386 g++-4.6:i386 gcc-4.6:i386 libssl-dev:i386 patchelf:i386 gfortran:i386 llvm-3.3-dev:i386 libsuitesparse-dev:i386 libopenblas-dev:i386 libopenblas-base:i386 libblas-dev:i386 liblapack-dev:i386 liblapack3:i386 libarpack2-dev:i386 libarpack2:i386 libfftw3-dev:i386 libgmp-dev:i386 libpcre3-dev:i386 libunwind7-dev:i386 libopenlibm-dev:i386 libmpfr-dev:i386 -y; + sudo apt-get install gcc:i386 g++:i386 make:i386 cpp:i386 g++-4.6:i386 gcc-4.6:i386 libssl-dev:i386 patchelf:i386 gfortran:i386 llvm-3.3-dev:i386 libsuitesparse-dev:i386 libopenblas-dev:i386 libopenblas-base:i386 libblas-dev:i386 liblapack-dev:i386 liblapack3:i386 libarpack2-dev:i386 libarpack2:i386 libfftw3-dev:i386 libgmp-dev:i386 libpcre3-dev:i386 libopenlibm-dev:i386 libmpfr-dev:i386 -y; else - sudo apt-get install patchelf gfortran llvm-3.3-dev libsuitesparse-dev libopenblas-dev liblapack-dev libarpack2-dev libfftw3-dev libgmp-dev libpcre3-dev libunwind7-dev libopenlibm-dev libmpfr-dev -y; + sudo apt-get install patchelf gfortran llvm-3.3-dev libsuitesparse-dev libopenblas-dev liblapack-dev libarpack2-dev libfftw3-dev libgmp-dev libpcre3-dev libopenlibm-dev libmpfr-dev -y; fi; elif [ `uname` = "Darwin" ]; then brew tap staticfloat/julia; From 3f76dc2b9a8c1cb810864832a6c3f55e7f63b66d Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sat, 27 Jun 2015 21:07:36 -0400 Subject: [PATCH 036/106] Revert "Disable test for ReadOnlyMemoryError for now since it seems to cause some corruption on 32bit linux #11691" This reverts commit 224829ec1d73ff0a042952a9d9543ee583fd7f23. (cherry picked from commit c65bff9aabaa11a8f685a1c92874cde8b9a362a7) --- test/mmap.jl | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/test/mmap.jl b/test/mmap.jl index 2a7b493bd1b68..35f2024a8c525 100644 --- a/test/mmap.jl +++ b/test/mmap.jl @@ -89,11 +89,10 @@ m = Mmap.mmap(file, Vector{UInt8}, 1, sz+1) @test m[1] == 0x00 finalize(m); m=nothing; gc() -# Uncomment out once #11351 is resolved -# s = open(file, "r") -# m = Mmap.mmap(s) -# @test_throws ReadOnlyMemoryError m[5] = Vector{UInt8}('x') # tries to setindex! on read-only array -# finalize(m); m=nothing; gc() +s = open(file, "r") +m = Mmap.mmap(s) +@test_throws ReadOnlyMemoryError m[5] = UInt8('x') # tries to setindex! on read-only array +finalize(m); m=nothing; gc() s = open(file, "w") do f write(f, "Hello World\n") @@ -284,4 +283,4 @@ n = similar(m, (2,2)) n = similar(m, 12) @test length(n) == 12 @test size(n) == (12,) -finalize(m); m = nothing; gc() \ No newline at end of file +finalize(m); m = nothing; gc() From 8623f56dd6a5cfb9629836c4240f9cc24e869b60 Mon Sep 17 00:00:00 2001 From: Marius Hoch Date: Thu, 12 Nov 2015 14:48:59 +0100 Subject: [PATCH 037/106] REPLCompletions: Allow dirs in PATH that can't be read As bash allows this (without complaining), we should as well support that. (cherry picked from commit d3a013b0dc0d26b39cbb719cba3bbe92cdf928d3) ref #13959 --- base/REPLCompletions.jl | 13 ++++++++++++- test/replcompletions.jl | 10 +++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/base/REPLCompletions.jl b/base/REPLCompletions.jl index 03b4d89f47f34..00cddf2c9d0bf 100644 --- a/base/REPLCompletions.jl +++ b/base/REPLCompletions.jl @@ -161,7 +161,18 @@ function complete_path(path::AbstractString, pos; use_envpath=false) continue end - local filesinpath = readdir(pathdir) + local filesinpath + try + filesinpath = readdir(pathdir) + catch e + # Bash allows dirs in PATH that can't be read, so we should as well. + if isa(e, SystemError) + continue + else + # We only handle SystemErrors here + rethrow(e) + end + end for file in filesinpath # In a perfect world, we would filter on whether the file is executable diff --git a/test/replcompletions.jl b/test/replcompletions.jl index a7b5d4c2450b1..bac4a54771cc9 100644 --- a/test/replcompletions.jl +++ b/test/replcompletions.jl @@ -451,16 +451,24 @@ c, r, res = test_scomplete(s) let oldpath = ENV["PATH"] path = tempdir() - ENV["PATH"] = path + # PATH can also contain folders which we aren't actually allowed to read. + unreadable = joinpath(tempdir(), "replcompletion-unreadable") + ENV["PATH"] = string(path, ":", unreadable) + file = joinpath(path, "tmp-executable") touch(file) chmod(file, 0o755) + mkdir(unreadable) + chmod(unreadable, 0o000) + s = "tmp-execu" c,r = test_scomplete(s) @test "tmp-executable" in c @test r == 1:9 @test s[r] == "tmp-execu" + rm(file) + rm(unreadable) ENV["PATH"] = oldpath end From 6f5177cc7b120e9a3edd6f95c6819c4bdce2d0ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=B8egh?= Date: Mon, 16 Nov 2015 19:29:32 +0100 Subject: [PATCH 038/106] Fix build_sysimg on OSX by changing to use cc instead of ld to link sysimg. (cherry picked from commit e0d46c28c45ff76360938ce199738f63741d9f57) ref #14018 --- contrib/build_sysimg.jl | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/contrib/build_sysimg.jl b/contrib/build_sysimg.jl index 3aad063b88516..7021031affdc4 100644 --- a/contrib/build_sysimg.jl +++ b/contrib/build_sysimg.jl @@ -26,7 +26,7 @@ function build_sysimg(sysimg_path=default_sysimg_path, cpu_target="native", user base_dir = dirname(Base.find_source_file("sysimg.jl")) cd(base_dir) do julia = joinpath(JULIA_HOME, "julia") - ld = find_system_linker() + cc = find_system_compiler() # Ensure we have write-permissions to wherever we're trying to write to try @@ -65,8 +65,8 @@ function build_sysimg(sysimg_path=default_sysimg_path, cpu_target="native", user println("$julia -C $cpu_target --output-ji $sysimg_path.ji --output-o $sysimg_path.o -J $inference_path.ji --startup-file=no sysimg.jl") run(`$julia -C $cpu_target --output-ji $sysimg_path.ji --output-o $sysimg_path.o -J $inference_path.ji --startup-file=no sysimg.jl`) - if ld != nothing - link_sysimg(sysimg_path, ld) + if cc != nothing + link_sysimg(sysimg_path, cc) else info("System image successfully built at $sysimg_path.ji") end @@ -89,18 +89,18 @@ function build_sysimg(sysimg_path=default_sysimg_path, cpu_target="native", user end end -# Search for a linker to link sys.o into sys.dl_ext. Honor LD environment variable. -function find_system_linker() - if haskey( ENV, "LD" ) - if !success(`$(ENV["LD"]) -v`) - warn("Using linker override $(ENV["LD"]), but unable to run `$(ENV["LD"]) -v`") +# Search for a compiler to link sys.o into sys.dl_ext. Honor LD environment variable. +function find_system_compiler() + if haskey( ENV, "CC" ) + if !success(`$(ENV["CC"]) -v`) + warn("Using compiler override $(ENV["CC"]), but unable to run `$(ENV["CC"]) -v`") end - return ENV["LD"] + return ENV["CC"] end # On Windows, check to see if WinRPM is installed, and if so, see if gcc is installed @windows_only try - require("WinRPM") + eval(Main, :(using WinRPM)) winrpmgcc = joinpath(WinRPM.installdir,"usr","$(Sys.ARCH)-w64-mingw32", "sys-root","mingw","bin","gcc.exe") if success(`$winrpmgcc --version`) @@ -113,33 +113,28 @@ function find_system_linker() end - # See if `ld` exists + # See if `cc` exists try - if success(`ld -v`) - return "ld" + if success(`cc -v`) + return "cc" end end - warn( "No supported linker found; startup times will be longer" ) + warn( "No supported compiler found; startup times will be longer" ) end # Link sys.o into sys.$(dlext) -function link_sysimg(sysimg_path=default_sysimg_path, ld=find_system_linker()) +function link_sysimg(sysimg_path=default_sysimg_path, cc=find_system_compiler()) julia_libdir = dirname(Libdl.dlpath("libjulia")) FLAGS = ["-L$julia_libdir"] - if OS_NAME == :Darwin - push!(FLAGS, "-dylib") - push!(FLAGS, "-macosx_version_min") - push!(FLAGS, "10.7") - else - push!(FLAGS, "-shared") - end + + push!(FLAGS, "-shared") push!(FLAGS, "-ljulia") @windows_only push!(FLAGS, "-lssp") info("Linking sys.$(Libdl.dlext)") - run(`$ld $FLAGS -o $sysimg_path.$(Libdl.dlext) $sysimg_path.o`) + run(`$cc $FLAGS -o $sysimg_path.$(Libdl.dlext) $sysimg_path.o`) info("System image successfully built at $sysimg_path.$(Libdl.dlext)") @windows_only begin From f40a6111f5bc2973abab58f416d8ef270317efec Mon Sep 17 00:00:00 2001 From: Marius Hoch Date: Thu, 12 Nov 2015 02:13:52 +0100 Subject: [PATCH 039/106] Fix handling of trailing spaces in REPL shell mode As Base.shell_parse throws away trailing spaces (unless they are escaped) we need to special case that for completions in REPL shell mode. Prior to this any trailing spaces were ignored for completions, which led to problems as we tried to complete the word before the space. For example in case of `"ls /tmp "` (note the trailing space) hitting tab would have made us try to complete `tmp`. Also because the offsets are wrong in that case, the input value would have changed to `"ls /ttmp/"` (note the double tt, the trailing space is gone). This also adds a regression test for completing paths with spaces in them as I was afraid to break that. (cherry picked from commit 95851f1ba8f66bcfe75f074cb58bc2d858958b3b) ref #13956 --- base/REPLCompletions.jl | 11 ++++++++++- test/replcompletions.jl | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/base/REPLCompletions.jl b/base/REPLCompletions.jl index 00cddf2c9d0bf..420424dba1b9b 100644 --- a/base/REPLCompletions.jl +++ b/base/REPLCompletions.jl @@ -484,8 +484,17 @@ function shell_completions(string, pos) arg = args.args[end].args[end] if all(s -> isa(s, AbstractString), args.args[end].args) # Treat this as a path + + # As Base.shell_parse throws away trailing spaces (unless they are escaped), + # we need to special case here. + # If the last char was a space, but shell_parse ignored it search on "". + ignore_last_word = arg != " " && scs[end] == ' ' + prefix = ignore_last_word ? "" : join(args.args[end].args) + # Also try looking into the env path if the user wants to complete the first argument - return complete_path(join(args.args[end].args), pos, use_envpath=length(args.args) < 2) + use_envpath = !ignore_last_word && length(args.args) < 2 + + return complete_path(prefix, pos, use_envpath=use_envpath) elseif isexpr(arg, :escape) && (isexpr(arg.args[1], :incomplete) || isexpr(arg.args[1], :error)) r = first(last_parse):prevind(last_parse, last(last_parse)) partial = scs[r] diff --git a/test/replcompletions.jl b/test/replcompletions.jl index bac4a54771cc9..a84c0097b2147 100644 --- a/test/replcompletions.jl +++ b/test/replcompletions.jl @@ -431,6 +431,28 @@ c, r, res = test_scomplete(s) @test r == 6:7 @test s[r] == "Pk" + # Pressing tab after having entered "/tmp " should not + # attempt to complete "/tmp" but rather work on the current + # working directory again. + + let + file = joinpath(path, "repl completions") + s = "/tmp " + c,r = test_scomplete(s) + @test r == 6:5 + end + + # Test completing paths with an escaped trailing space + let + file = joinpath(tempdir(), "repl completions") + touch(file) + s = string(tempdir(), "/repl\\ ") + c,r = test_scomplete(s) + @test ["repl\\ completions"] == c + @test s[r] == "repl\\ " + rm(file) + end + # Tests homedir expansion let path = homedir() From 8662eec429924df77340510556f69db62ae77895 Mon Sep 17 00:00:00 2001 From: Hessam Mehr Date: Fri, 16 Oct 2015 12:44:39 -0400 Subject: [PATCH 040/106] Fixing #13559 with more limited impact. Performance should be identical to baseline. Fixed infinite loop in previous fix for #13559. Do not throw EOFError if buffer already contains n bytes. #13559 (cherry picked from commit 68442e2d7876ffdc42ca1a5e2106954aef4c8c70) ref #13638 --- src/sys.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/sys.c b/src/sys.c index 4d88301b8aed3..6826d2f0c8694 100644 --- a/src/sys.c +++ b/src/sys.c @@ -301,9 +301,13 @@ static void NORETURN throw_eof_error(void) DLLEXPORT uint64_t jl_ios_get_nbyte_int(ios_t *s, const size_t n) { assert(n <= 8); - size_t ret = ios_readprep(s, n); - if (ret < n) - throw_eof_error(); + size_t space, ret; + do { + space = s->size - s->bpos; + ret = ios_readprep(s, n); + if (space == ret && ret < n) + throw_eof_error(); + } while(ret < n); uint64_t x = 0; uint8_t *buf = (uint8_t*)&s->buf[s->bpos]; if (n == 8) { From b411724abfa051993e76a302e73a24ff440ff409 Mon Sep 17 00:00:00 2001 From: Hessam Mehr Date: Fri, 16 Oct 2015 23:09:52 -0400 Subject: [PATCH 041/106] Unit test for #13559. Uses the qualified path to launch julia (cherry picked from commit 0a79189a1ea287586056dbafe55859bbe0a7ac97) --- test/file.jl | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/file.jl b/test/file.jl index ed3a385229bbd..d359eb7ace627 100644 --- a/test/file.jl +++ b/test/file.jl @@ -922,3 +922,25 @@ test_12992() test2_12992() test2_12992() test2_12992() + +# issue 13559 + +function test_13559() + fn = tempname() + run(`mkfifo $fn`) + # use subprocess to write 127 bytes to FIFO + writer_cmds = "x=open(\"$fn\", \"w\"); for i=1:127 write(x,0xaa); flush(x); sleep(0.1) end; close(x); quit()" + open(`$(Base.julia_cmd()) -e $writer_cmds`) + #quickly read FIFO, draining it and blocking but not failing with EOFError yet + r = open(fn, "r") + # 15 proper reads + for i=1:15 + @test read(r, Int64) == -6148914691236517206 + end + # last read should throw EOFError when FIFO closes, since there are only 7 bytes available. + @test_throws EOFError read(r, Int64) + close(r) + rm(fn) +end + +@unix_only test_13559() From 51aefcd2e7f3f09455a71bdf3ea7b266d8ae92e6 Mon Sep 17 00:00:00 2001 From: Hessam Mehr Date: Sat, 17 Oct 2015 20:45:24 -0700 Subject: [PATCH 042/106] Cross-platform test coverage for n-byte reads and throwing EOF on insufficient bytes read. (cherry picked from commit 9ef294921425b0dc6e730294e8ebfef421561ad7) --- test/file.jl | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/test/file.jl b/test/file.jl index d359eb7ace627..bd08ef3215f49 100644 --- a/test/file.jl +++ b/test/file.jl @@ -942,5 +942,51 @@ function test_13559() close(r) rm(fn) end - @unix_only test_13559() + +function test_read_nbyte() + fn = tempname() + # Write one byte. One byte read should work once + # but 2-byte read should throw EOFError. + f = open(fn, "w+") do f + write(f, 0x55) + flush(f) + seek(f, 0) + @test read(f, UInt8) == 0x55 + @test_throws EOFError read(f, UInt8) + seek(f, 0) + @test_throws EOFError read(f, UInt16) + end + # Write 2 more bytes. Now 2-byte read should work once + # but 4-byte read should fail with EOFError. + open(fn, "a+") do f + write(f, 0x4444) + flush(f) + seek(f, 0) + @test read(f, UInt16) == 0x4455 + @test_throws EOFError read(f, UInt16) + seek(f,0) + @test_throws EOFError read(f, UInt32) + end + # Write 4 more bytes. Now 4-byte read should work once + # but 8-byte read should fail with EOFError. + open(fn, "a+") do f + write(f, 0x33333333) + flush(f) + seek(f, 0) + @test read(f, UInt32) == 0x33444455 + @test_throws EOFError read(f, UInt32) + seek(f,0) + @test_throws EOFError read(f, UInt64) + end + # Writing one more byte should allow an 8-byte + # read to proceed. + open(fn, "a+") do f + write(f, 0x22) + flush(f) + seek(f, 0) + @test read(f, UInt64) == 0x2233333333444455 + end + rm(fn) +end +test_read_nbyte() From 0958a89ff015bcb9defffa4095cdf6938514ccb3 Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Sun, 25 Oct 2015 15:57:54 +0900 Subject: [PATCH 043/106] fix the read and write methods of DevNull (cherry picked from commit 18706cbda833576a9b08426d393b2ccd042aedeb) ref #13758 --- base/process.jl | 4 ++-- test/file.jl | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/base/process.jl b/base/process.jl index c9af9053f9d7d..a4b4544ec6cdf 100644 --- a/base/process.jl +++ b/base/process.jl @@ -91,8 +91,8 @@ const DevNull = DevNullStream() isreadable(::DevNullStream) = false iswritable(::DevNullStream) = true isopen(::DevNullStream) = true -read{T<:DevNullStream}(::T, args...) = throw(EOFErorr()) -write{T<:DevNullStream}(::T, args...) = 0 +read(::DevNullStream, ::Type{UInt8}) = throw(EOFError()) +write(::DevNullStream, ::UInt8) = 0 close(::DevNullStream) = nothing flush(::DevNullStream) = nothing copy(::DevNullStream) = DevNull diff --git a/test/file.jl b/test/file.jl index bd08ef3215f49..811e1d5b6b155 100644 --- a/test/file.jl +++ b/test/file.jl @@ -990,3 +990,16 @@ function test_read_nbyte() rm(fn) end test_read_nbyte() + +# DevNull +@test !isreadable(DevNull) +@test iswritable(DevNull) +@test isopen(DevNull) +@test write(DevNull, 0xff) == 0 +@test write(DevNull, 1234) == 0 +@test_throws EOFError read(DevNull, UInt8) +@test close(DevNull) === nothing +@test flush(DevNull) === nothing +@test copy(DevNull) === DevNull +@test eof(DevNull) +@test print(DevNull, "go to /dev/null") === nothing From d4977944704af9191c55c635e3e1a2b5b0f27bec Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Tue, 27 Oct 2015 01:01:06 +0900 Subject: [PATCH 044/106] count the number of bytes written to DevNull (cherry picked from commit b9aa3003b14b07de806f05622611aea6bdd94e6c) --- base/process.jl | 2 +- test/file.jl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/base/process.jl b/base/process.jl index a4b4544ec6cdf..63af2e30cc4dc 100644 --- a/base/process.jl +++ b/base/process.jl @@ -92,7 +92,7 @@ isreadable(::DevNullStream) = false iswritable(::DevNullStream) = true isopen(::DevNullStream) = true read(::DevNullStream, ::Type{UInt8}) = throw(EOFError()) -write(::DevNullStream, ::UInt8) = 0 +write(::DevNullStream, ::UInt8) = 1 close(::DevNullStream) = nothing flush(::DevNullStream) = nothing copy(::DevNullStream) = DevNull diff --git a/test/file.jl b/test/file.jl index 811e1d5b6b155..4fc1880b136b6 100644 --- a/test/file.jl +++ b/test/file.jl @@ -995,8 +995,8 @@ test_read_nbyte() @test !isreadable(DevNull) @test iswritable(DevNull) @test isopen(DevNull) -@test write(DevNull, 0xff) == 0 -@test write(DevNull, 1234) == 0 +@test write(DevNull, 0xff) === 1 +@test write(DevNull, Int32(1234)) === 4 @test_throws EOFError read(DevNull, UInt8) @test close(DevNull) === nothing @test flush(DevNull) === nothing From 6462964cc89d953344fda021e28614765077b5d5 Mon Sep 17 00:00:00 2001 From: Xander Dunn Date: Thu, 19 Nov 2015 12:08:13 -0800 Subject: [PATCH 045/106] Fix typo (cherry picked from commit ed07eb2d084aef2dd39e12132b76cd79be0a06ad) ref #14062 --- doc/manual/strings.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual/strings.rst b/doc/manual/strings.rst index 27c019ba3e1ae..cced6c679253b 100644 --- a/doc/manual/strings.rst +++ b/doc/manual/strings.rst @@ -692,7 +692,7 @@ You can extract the following info from a :obj:`RegexMatch` object: For when a capture doesn't match, instead of a substring, ``m.captures`` contains ``nothing`` in that position, and ``m.offsets`` has a zero offset (recall that indices in Julia are 1-based, so a zero offset into -a string is invalid). Here's is a pair of somewhat contrived examples:: +a string is invalid). Here is a pair of somewhat contrived examples:: julia> m = match(r"(a|b)(c)?(d)", "acd") RegexMatch("acd", 1="a", 2="c", 3="d") From 231dd4a7faaf44a3c79613eeb601bdc1ba786ade Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Wed, 18 Nov 2015 15:07:53 -0500 Subject: [PATCH 046/106] =?UTF-8?q?improve=20deprecation=20warning=20for?= =?UTF-8?q?=20non-integer=20indexing:=20suggest=20replacing=20i/j=20with?= =?UTF-8?q?=20i=C3=B7j=20(see=20#10458)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit d2ad66c18af9face68d33ba06ee2a5d44ab6e367) ref #14049 --- base/deprecated.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 92010f064fc80..b5f59f0287291 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -444,7 +444,7 @@ end to_index_nodep(i::Real) = convert(Int,i)::Int @noinline function to_index(i::Real) - depwarn("indexing with non Integer Reals is deprecated", :to_index) + depwarn("Indexing with non-Integer Reals is deprecated. It may be that your index arose from an integer division of the form i/j, in which case you should consider using i÷j or div(i,j) instead.", :to_index) to_index_nodep(i) end From 8d7683e4e96e5f7921ac625bce114d93e8224f0b Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Fri, 20 Nov 2015 12:07:11 -0500 Subject: [PATCH 047/106] normalize literal \r and \r\n chars in string literals to \n (fixes #11988) (cherry picked from commit fdec6bc780b2282340814fbf29bac033c93be637) ref #14073 --- src/julia-parser.scm | 8 ++++++++ test/parse.jl | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 0c43298b0da8d..f91e9176d88bf 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -1831,6 +1831,14 @@ (list* ex (tostr custom b) e) 0))) + ; convert literal \r and \r\n in strings to \n (issue #11988) + ((eqv? c #\return) ; \r + (begin + (if (eqv? (peek-char p) #\linefeed) ; \r\n + (read-char p)) + (write-char #\newline b) + (loop (read-char p) b e 0))) + (else (write-char (not-eof-3 c) b) (loop (read-char p) b e 0))))) diff --git a/test/parse.jl b/test/parse.jl index 333bdc4dc2e15..1de89d9c5b071 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -304,3 +304,7 @@ let p = parse("try @test p.args[2] === false @test p.args[3].args[end] == parse("b,c = t") end + +# issue #11988 -- normalize \r and \r\n in literal strings to \n +@test "foo\nbar" == parse("\"\"\"\r\nfoo\r\nbar\"\"\"") == parse("\"\"\"\nfoo\nbar\"\"\"") == parse("\"\"\"\rfoo\rbar\"\"\"") == parse("\"foo\r\nbar\"") == parse("\"foo\rbar\"") == parse("\"foo\nbar\"") +@test '\r' == first("\r") == first("\r\n") # still allow explicit \r From 1896a57626fadf99a26fc76f0904405492a6c0e8 Mon Sep 17 00:00:00 2001 From: "Dr. Zygmunt L. Szpak" Date: Sat, 21 Nov 2015 13:30:48 +1030 Subject: [PATCH 048/106] Add tests for `convert` Added tests for `convert(::Type{Int128}, x::Float16)` and `convert(::Type{UInt128}, x::Float16)` which validate type and check that `InexactError` is thrown for some cases where it should be thrown e.g.: `@test_throws InexactError convert(UInt128, Float16(3.5))` and `@test_throws InexactError convert(UInt128, Float16(-1))` (cherry picked from commit 809eda99b1a30b1bb2665773ec1ec81b69c8849a) ref #14080 --- test/float16.jl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/float16.jl b/test/float16.jl index 2cdd1b4a98f99..54bd3461759e8 100644 --- a/test/float16.jl +++ b/test/float16.jl @@ -23,6 +23,16 @@ g = Float16(1.) @test convert(Int128,Float16(-2.0)) == Int128(-2) @test convert(UInt128,Float16(2.0)) == UInt128(2) +# convert(::Type{Int128}, x::Float16) +@test convert(Int128, Float16(1.0)) === Int128(1.0) +@test convert(Int128, Float16(-1.0)) === Int128(-1.0) +@test_throws InexactError convert(Int128, Float16(3.5)) + +# convert(::Type{UInt128}, x::Float16) +@test convert(UInt128, Float16(1.0)) === UInt128(1.0) +@test_throws InexactError convert(UInt128, Float16(3.5)) +@test_throws InexactError convert(UInt128, Float16(-1)) + x = Float32(rand()) y = Float32(rand()) z = Float32(rand()) From eccf2316ec689d81bf26dbfbf0d7a1341bebfa5d Mon Sep 17 00:00:00 2001 From: "Arch D. Robison" Date: Fri, 20 Nov 2015 13:41:47 -0600 Subject: [PATCH 049/106] Add manual section about numerical conversions. (cherry picked from commit 7345a14342ba90c947bbba3121604a57b24ddc8f) ref #14075 --- doc/manual/mathematical-operations.rst | 69 ++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/doc/manual/mathematical-operations.rst b/doc/manual/mathematical-operations.rst index 64e6f1e223b37..fe8ee11f527b9 100644 --- a/doc/manual/mathematical-operations.rst +++ b/doc/manual/mathematical-operations.rst @@ -347,6 +347,73 @@ Control flow ``&&`` followed by ``||`` followed by ``?`` Assignments ``= += -= *= /= //= \= ^= ÷= %= |= &= $= <<= >>= >>>=`` and ``.+= .-= .*= ./= .//= .\= .^= .÷= .%=`` ================= ============================================================================================= +.. _man-numerical-conversions: + +Numerical Conversions +--------------------- + +Julia supports three forms of numerical conversion, which differ in their +handling of inexact conversions. + +- The notation ``T(x)`` or ``convert(T,x)`` converts ``x`` to a value of type ``T``. + + - If ``T`` is a floating-point type, the result is the nearest representable + value, which could be positive or negative infinity. + + - If ``T`` is an integer type, an ``InexactError`` is raised if ``x`` + is not representable by ``T``. + + +- ``x % T`` converts an integer ``x`` to a value of integer type ``T`` + congruent to ``x`` modulo ``2^n``, where ``n`` is the number of bits in ``T``. + In other words, the binary representation is truncated to fit. + +- The :ref:`man-rounding-functions` take a type ``T`` as an optional argument. + For example, ``round(Int,x)`` is a shorthand for ``Int(round(x))``. + +The following examples show the different forms. + +.. doctest:: + + julia> Int8(127) + 127 + + julia> Int8(128) + ERROR: InexactError() + in call at ./essentials.jl:58 + in eval at ./boot.jl:263 + + julia> Int8(127.0) + 127 + + julia> Int8(3.14) + ERROR: InexactError() + in call at ./essentials.jl:58 + in eval at ./boot.jl:263 + + julia> Int8(128.0) + ERROR: InexactError() + in call at ./essentials.jl:58 + in eval at ./boot.jl:263 + + julia> 127 % Int8 + 127 + + julia> 128 % Int8 + -128 + + julia> round(Int8,127.4) + 127 + + julia> round(Int8,127.6) + ERROR: InexactError() + in trunc at ./float.jl:357 + in round at ./float.jl:177 + in eval at ./boot.jl:263 + +See :ref:`man-conversion-and-promotion` for how to define your own +conversions and promotions. + .. _man-elementary-functions: Elementary Functions @@ -358,6 +425,8 @@ class of numerical values as permit sensible definitions, including integers, floating-point numbers, rationals, and complexes, wherever such definitions make sense. +.. _man-rounding-functions: + Rounding functions ~~~~~~~~~~~~~~~~~~ From 6d5a8598fb0d8d0f284376f74ab8a00d5f4178df Mon Sep 17 00:00:00 2001 From: "Dr. Zygmunt L. Szpak" Date: Sat, 21 Nov 2015 00:05:02 +1030 Subject: [PATCH 050/106] Add more tests for copysign Added numerous test cases for copysign function. Discovered bug with copysign when the second argument of copysign is NaN or Inf; e.g. @test isinf(copysign(1,1/0)) and @test isinf(copysign(-1,1/0)). Added these two tests but have currently commented them out. (cherry picked from commit e7b7aa4f71f804ce3328a299f5a5eec08ff706f9) ref #14069 --- test/numbers.jl | 121 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/test/numbers.jl b/test/numbers.jl index e58d16d6cd14b..592d2f667df8b 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -473,6 +473,127 @@ end @test copysign(big(1.0),big(-2.0)) == big(-1.0) +#copysign +@test copysign(-1,1) == 1 +@test copysign(1,-1) == -1 + +@test copysign(-1,1.0) == 1 +@test copysign(1,-1.0) == -1 + +@test copysign(-1,1//2) == 1 +@test copysign(1,-1//2) == -1 + +@test copysign(1.0,-1) == -1.0 +@test copysign(-1.0,1) == 1.0 + +@test copysign(1.0,-1.0) == -1.0 +@test copysign(-1.0,1.0) == 1.0 + +@test copysign(1.0,-1//2) == -1.0 +@test copysign(-1.0,1//2) == 1.0 + +@test copysign(1//2,-1) == -1//2 +@test copysign(-1//2,1) == 1//2 + +@test copysign(1//2,-1//2) == -1//2 +@test copysign(-1//2,1//2) == 1//2 + +@test copysign(1//2,-1.0) == -1//2 +@test copysign(-1//2,1.0) == 1//2 + +# verify type stability with integer (x is negative) +@test eltype(copysign(-1,1)) <: Integer +@test eltype(copysign(-1,BigInt(1))) <: Integer +@test eltype(copysign(-1,1.0)) <: Integer +@test eltype(copysign(-1,1//2)) <: Integer +@test eltype(copysign(-BigInt(1),1)) <: Integer +@test eltype(copysign(-BigInt(1),1.0)) <: Integer +@test eltype(copysign(-BigInt(1),1//2)) <: Integer +@test eltype(copysign(-BigInt(1),BigInt(1))) <: Integer +@test eltype(copysign(-1,-1)) <: Integer +@test eltype(copysign(-1,-BigInt(1))) <: Integer +@test eltype(copysign(-1,-1.0)) <: Integer +@test eltype(copysign(-1,-1//2)) <: Integer +@test eltype(copysign(-BigInt(1),-1)) <: Integer +@test eltype(copysign(-BigInt(1),-1.0)) <: Integer +@test eltype(copysign(-BigInt(1),-1//2)) <: Integer +@test eltype(copysign(-BigInt(1),-BigInt(1))) <: Integer + +# verify type stability with integer (x is positive) +@test eltype(copysign(1,1)) <: Integer +@test eltype(copysign(1,BigInt(1))) <: Integer +@test eltype(copysign(1,1.0)) <: Integer +@test eltype(copysign(1,1//2)) <: Integer +@test eltype(copysign(BigInt(1),1)) <: Integer +@test eltype(copysign(BigInt(1),1.0)) <: Integer +@test eltype(copysign(BigInt(1),1//2)) <: Integer +@test eltype(copysign(BigInt(1),BigInt(1))) <: Integer +@test eltype(copysign(1,-1)) <: Integer +@test eltype(copysign(1,-BigInt(1))) <: Integer +@test eltype(copysign(1,-1.0)) <: Integer +@test eltype(copysign(1,-1//2)) <: Integer +@test eltype(copysign(BigInt(1),-1)) <: Integer +@test eltype(copysign(BigInt(1),-1.0)) <: Integer +@test eltype(copysign(BigInt(1),-1//2)) <: Integer +@test eltype(copysign(BigInt(1),-BigInt(1))) <: Integer + +# verify type stability with real (x is negative) +@test eltype(copysign(-1.0,1)) <: Real +@test eltype(copysign(-1.0,BigInt(1))) <: Real +@test eltype(copysign(-1.0,1.0)) <: Real +@test eltype(copysign(-1.0,1//2)) <: Real +@test eltype(copysign(-1.0,-1)) <: Real +@test eltype(copysign(-1.0,-BigInt(1))) <: Real +@test eltype(copysign(-1.0,-1.0)) <: Real +@test eltype(copysign(-1.0,-1//2)) <: Real + +# Verify type stability with real (x is positive) +@test eltype(copysign(1.0,1)) <: Real +@test eltype(copysign(1.0,BigInt(1))) <: Real +@test eltype(copysign(1.0,1.0)) <: Real +@test eltype(copysign(1.0,1//2)) <: Real +@test eltype(copysign(1.0,-1)) <: Real +@test eltype(copysign(1.0,-BigInt(1))) <: Real +@test eltype(copysign(1.0,-1.0)) <: Real +@test eltype(copysign(1.0,-1//2)) <: Real + +# Verify type stability with rational (x is negative) +@test eltype(copysign(-1//2,1)) <: Rational +@test eltype(copysign(-1//2,BigInt(1))) <: Rational +@test eltype(copysign(-1//2,1.0)) <: Rational +@test eltype(copysign(-1//2,1//2)) <: Rational +@test eltype(copysign(-1//2,-1)) <: Rational +@test eltype(copysign(-1//2,-BigInt(1))) <: Rational +@test eltype(copysign(-1//2,-1.0)) <: Rational +@test eltype(copysign(-1//2,-1//2)) <: Rational + +# Verify type stability with rational (x is positive) +@test eltype(copysign(-1//2,1)) <: Rational +@test eltype(copysign(-1//2,BigInt(1))) <: Rational +@test eltype(copysign(-1//2,1.0)) <: Rational +@test eltype(copysign(-1//2,1//2)) <: Rational +@test eltype(copysign(-1//2,-1)) <: Rational +@test eltype(copysign(-1//2,-BigInt(1))) <: Rational +@test eltype(copysign(-1//2,-1.0)) <: Rational +@test eltype(copysign(-1//2,-1//2)) <: Rational + +# test x = NaN +@test isnan(copysign(0/0,1)) +@test isnan(copysign(0/0,-1)) + +# test x = Inf +@test isinf(copysign(1/0,1)) +@test isinf(copysign(1/0,-1)) + +# test y = NaN (BUG Julia 0.4.1 20/11/2015) +#@test isnan(copysign(1,0.0)) +#@test isnan(copysign(-1,0.0)) + +# test y = Inf (BUG Julia 0.4.1 20/11/2015) +#@test isinf(copysign(1,1/0)) +#@test isinf(copysign(-1,1/0)) + + @test isnan(1) == false @test isnan(1.0) == false @test isnan(-1.0) == false From 0445b3a23614028167d1c71aa532bee22b770876 Mon Sep 17 00:00:00 2001 From: "Dr. Zygmunt L. Szpak" Date: Sat, 21 Nov 2015 01:05:35 +1030 Subject: [PATCH 051/106] Remove trailing white-space Attempt at removing trailing white-space to avoid build failure. (cherry picked from commit 4d1ced8b56dfe4f63551442dc61ceef91a23fd7e) --- test/numbers.jl | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/test/numbers.jl b/test/numbers.jl index 592d2f667df8b..c5b6ac451103e 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -474,31 +474,31 @@ end @test copysign(big(1.0),big(-2.0)) == big(-1.0) #copysign -@test copysign(-1,1) == 1 +@test copysign(-1,1) == 1 @test copysign(1,-1) == -1 -@test copysign(-1,1.0) == 1 +@test copysign(-1,1.0) == 1 @test copysign(1,-1.0) == -1 -@test copysign(-1,1//2) == 1 +@test copysign(-1,1//2) == 1 @test copysign(1,-1//2) == -1 -@test copysign(1.0,-1) == -1.0 +@test copysign(1.0,-1) == -1.0 @test copysign(-1.0,1) == 1.0 -@test copysign(1.0,-1.0) == -1.0 +@test copysign(1.0,-1.0) == -1.0 @test copysign(-1.0,1.0) == 1.0 -@test copysign(1.0,-1//2) == -1.0 +@test copysign(1.0,-1//2) == -1.0 @test copysign(-1.0,1//2) == 1.0 - -@test copysign(1//2,-1) == -1//2 + +@test copysign(1//2,-1) == -1//2 @test copysign(-1//2,1) == 1//2 -@test copysign(1//2,-1//2) == -1//2 +@test copysign(1//2,-1//2) == -1//2 @test copysign(-1//2,1//2) == 1//2 -@test copysign(1//2,-1.0) == -1//2 +@test copysign(1//2,-1.0) == -1//2 @test copysign(-1//2,1.0) == 1//2 # verify type stability with integer (x is negative) @@ -578,19 +578,19 @@ end @test eltype(copysign(-1//2,-1//2)) <: Rational # test x = NaN -@test isnan(copysign(0/0,1)) +@test isnan(copysign(0/0,1)) @test isnan(copysign(0/0,-1)) # test x = Inf -@test isinf(copysign(1/0,1)) -@test isinf(copysign(1/0,-1)) +@test isinf(copysign(1/0,1)) +@test isinf(copysign(1/0,-1)) # test y = NaN (BUG Julia 0.4.1 20/11/2015) -#@test isnan(copysign(1,0.0)) +#@test isnan(copysign(1,0.0)) #@test isnan(copysign(-1,0.0)) # test y = Inf (BUG Julia 0.4.1 20/11/2015) -#@test isinf(copysign(1,1/0)) +#@test isinf(copysign(1,1/0)) #@test isinf(copysign(-1,1/0)) From 92ad0611123b72eb88bf25e2782ad14ebdc1e8ff Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Fri, 20 Nov 2015 13:09:53 -0500 Subject: [PATCH 052/106] remove commented out copysign tests (cherry picked from commit a419fda050036ba3203dbdd93a117627d9cc9ede) --- test/numbers.jl | 9 --------- 1 file changed, 9 deletions(-) diff --git a/test/numbers.jl b/test/numbers.jl index c5b6ac451103e..425472e1ceb42 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -585,15 +585,6 @@ end @test isinf(copysign(1/0,1)) @test isinf(copysign(1/0,-1)) -# test y = NaN (BUG Julia 0.4.1 20/11/2015) -#@test isnan(copysign(1,0.0)) -#@test isnan(copysign(-1,0.0)) - -# test y = Inf (BUG Julia 0.4.1 20/11/2015) -#@test isinf(copysign(1,1/0)) -#@test isinf(copysign(-1,1/0)) - - @test isnan(1) == false @test isnan(1.0) == false @test isnan(-1.0) == false From 90584a9ee01ea5c661d3e035e9d7b306139a9431 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Fri, 20 Nov 2015 16:08:38 -0500 Subject: [PATCH 053/106] document newline normalization in literal strings (#14073) (cherry picked from commit 9ac2fd5e77ed70ac750ebc01f55a37fe36a98c89) ref #14078 --- doc/manual/strings.rst | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/doc/manual/strings.rst b/doc/manual/strings.rst index cced6c679253b..c56657d0c5a5d 100644 --- a/doc/manual/strings.rst +++ b/doc/manual/strings.rst @@ -441,8 +441,8 @@ backslash: julia> print("I have \$100 in my account.\n") I have $100 in my account. -Triple-Quoted Strings Literals ------------------------------- +Triple-Quoted String Literals +----------------------------- When strings are created using triple-quotes (``"""..."""``) they have some special behavior that can be useful for creating longer blocks of text. First, @@ -484,6 +484,12 @@ defining strings within code that is indented. For example: In this case the final (empty) line before the closing ``"""`` sets the indentation level. +Note that line breaks in literal strings, whether single- or triple-quoted, +result in a newline (LF) character ``\n`` in the string, even if your +editor uses a carriage return ``\r`` (CR) or CRLF combination to end lines. +To include a CR in a string, use an explicit escape ``\r``; for example, +you can enter the literal string ``"a CRLF line ending\r\n"``. + Common Operations ----------------- From 7704a2a6200019f578856d32bfa43e9543b09786 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sun, 29 Nov 2015 17:25:34 -0500 Subject: [PATCH 054/106] Make sphinx happy with headings and fix doctests again --- doc/manual/mathematical-operations.rst | 18 +++++++++--------- doc/manual/packages.rst | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/manual/mathematical-operations.rst b/doc/manual/mathematical-operations.rst index fe8ee11f527b9..4242ad55e5fcd 100644 --- a/doc/manual/mathematical-operations.rst +++ b/doc/manual/mathematical-operations.rst @@ -380,21 +380,21 @@ The following examples show the different forms. julia> Int8(128) ERROR: InexactError() - in call at ./essentials.jl:58 - in eval at ./boot.jl:263 + [inlined code] from int.jl:172 + in call at essentials.jl:56 julia> Int8(127.0) 127 julia> Int8(3.14) ERROR: InexactError() - in call at ./essentials.jl:58 - in eval at ./boot.jl:263 + [inlined code] from int.jl:209 + in call at essentials.jl:56 julia> Int8(128.0) ERROR: InexactError() - in call at ./essentials.jl:58 - in eval at ./boot.jl:263 + [inlined code] from int.jl:209 + in call at essentials.jl:56 julia> 127 % Int8 127 @@ -407,9 +407,9 @@ The following examples show the different forms. julia> round(Int8,127.6) ERROR: InexactError() - in trunc at ./float.jl:357 - in round at ./float.jl:177 - in eval at ./boot.jl:263 + [inlined code] from essentials.jl:25 + in trunc at float.jl:357 + in round at float.jl:188 See :ref:`man-conversion-and-promotion` for how to define your own conversions and promotions. diff --git a/doc/manual/packages.rst b/doc/manual/packages.rst index 9e485a32bf093..4cea4040ba90d 100644 --- a/doc/manual/packages.rst +++ b/doc/manual/packages.rst @@ -889,8 +889,8 @@ if they haven't already been, and then opens a pull request to ``METADATA``:: .. _man-manual-publish: -Publishing METADATA manually -============================ +Publishing METADATA Manually +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If :func:`Pkg.publish` fails you can follow these instructions to manually publish your package. From 75c791c64f2fa6c2227002f357e9532442bcd2ca Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Wed, 23 Sep 2015 12:23:02 +0530 Subject: [PATCH 055/106] edit sync write faq entry [ci skip] (cherry picked from commit 62a00d2d5f1524f8b555f75d04a67b0a61c9e1ce) ref #13282 --- doc/manual/faq.rst | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/doc/manual/faq.rst b/doc/manual/faq.rst index a2e6c4880cd3f..dce33384c7523 100644 --- a/doc/manual/faq.rst +++ b/doc/manual/faq.rst @@ -871,37 +871,35 @@ is fully asynchronous. The following:: @sync for i in 1:3 - @async print(i, " Foo ", " Bar ") + @async write(STDOUT, string(i), " Foo ", " Bar ") end results in:: 123 Foo Foo Foo Bar Bar Bar -This is happening because, while ``print(i, " Foo ", " Bar ")`` is synchronous, -internally, the writing of each argument yields to other tasks while waiting for -that part of the I/O to complete. +This is happening because, while the ``write`` call is synchronous, the writing of +each argument yields to other tasks while waiting for that part of the I/O to complete. -``println`` to asynchronous streams like STDOUT, TCPSockets, "locks" the stream -during a call. Consequently changing ``print`` to ``println`` in the above example -results in:: +``print`` and ``println`` "lock" the stream during a call. Consequently changing ``write`` to +``println`` in the above example results in:: 1 Foo Bar 2 Foo Bar 3 Foo Bar -For other functions and streams, etc, you could lock your writes with a ``ReentrantLock`` -like this:: +You can lock your writes with a ``ReentrantLock`` like this:: l = ReentrantLock() @sync for i in 1:3 @async begin lock(l) try - print(i, " Foo ", " Bar ") + write(STDOUT, string(i), " Foo ", " Bar ") finally unlock(l) end + end end From 7afe152793ce2160b54a9db73cfc8f28ad9f1564 Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Tue, 13 Oct 2015 15:35:16 +0530 Subject: [PATCH 056/106] restart worker during tests depending on resident memory size (cherry picked from commit 17e2e1c42855578ab6c558248365c49bc4d2f55f) ref #13577 --- base/multi.jl | 56 +++-- base/sysinfo.jl | 2 + src/sys.c | 28 ++- test/choosetests.jl | 5 +- test/examples.jl | 9 +- test/parallel.jl | 548 +----------------------------------------- test/parallel_exec.jl | 541 +++++++++++++++++++++++++++++++++++++++++ test/runtests.jl | 40 ++- test/testdefs.jl | 15 +- 9 files changed, 663 insertions(+), 581 deletions(-) create mode 100644 test/parallel_exec.jl diff --git a/base/multi.jl b/base/multi.jl index b56ab8ce6a09f..b1acc583072cc 100644 --- a/base/multi.jl +++ b/base/multi.jl @@ -336,30 +336,35 @@ function rmprocs(args...; waitfor = 0.0) error("only process 1 can add and remove processes") end - rmprocset = [] - for i in vcat(args...) - if i == 1 - warn("rmprocs: process 1 not removed") - else - if haskey(map_pid_wrkr, i) - w = map_pid_wrkr[i] - set_worker_state(w, W_TERMINATING) - kill(w.manager, i, w.config) - push!(rmprocset, w) + lock(worker_lock) + try + rmprocset = [] + for i in vcat(args...) + if i == 1 + warn("rmprocs: process 1 not removed") + else + if haskey(map_pid_wrkr, i) + w = map_pid_wrkr[i] + set_worker_state(w, W_TERMINATING) + kill(w.manager, i, w.config) + push!(rmprocset, w) + end end end - end - start = time() - while (time() - start) < waitfor - if all(w -> w.state == W_TERMINATED, rmprocset) - break; - else - sleep(0.1) + start = time() + while (time() - start) < waitfor + if all(w -> w.state == W_TERMINATED, rmprocset) + break; + else + sleep(0.1) + end end - end - ((waitfor > 0) && any(w -> w.state != W_TERMINATED, rmprocset)) ? :timed_out : :ok + ((waitfor > 0) && any(w -> w.state != W_TERMINATED, rmprocset)) ? :timed_out : :ok + finally + unlock(worker_lock) + end end @@ -1091,7 +1096,20 @@ end # `manager` is of type ClusterManager. The respective managers are responsible # for launching the workers. All keyword arguments (plus a few default values) # are available as a dictionary to the `launch` methods +# +# Only one addprocs can be in progress at any time +# +const worker_lock = ReentrantLock() function addprocs(manager::ClusterManager; kwargs...) + lock(worker_lock) + try + addprocs_locked(manager::ClusterManager; kwargs...) + finally + unlock(worker_lock) + end +end + +function addprocs_locked(manager::ClusterManager; kwargs...) params = merge(default_addprocs_params(), AnyDict(kwargs)) topology(symbol(params[:topology])) diff --git a/base/sysinfo.jl b/base/sysinfo.jl index f02950920c46b..030abfbacca8c 100644 --- a/base/sysinfo.jl +++ b/base/sysinfo.jl @@ -146,4 +146,6 @@ function set_process_title(title::AbstractString) uv_error("set_process_title", err) end +maxrss() = ccall(:jl_maxrss, Csize_t, ()) + end # module Sys diff --git a/src/sys.c b/src/sys.c index 6826d2f0c8694..caa0462c0aab5 100644 --- a/src/sys.c +++ b/src/sys.c @@ -10,7 +10,9 @@ #include #include #include -#ifndef _OS_WINDOWS_ +#ifdef _OS_WINDOWS_ +#include +#else #include #include #include @@ -746,6 +748,30 @@ DLLEXPORT jl_sym_t* jl_get_ARCH() return ARCH; } +DLLEXPORT size_t jl_maxrss() +{ +#if defined(_OS_WINDOWS_) + PROCESS_MEMORY_COUNTERS counter; + GetProcessMemoryInfo( GetCurrentProcess( ), &counter, sizeof(counter) ); + return (size_t)counter.PeakWorkingSetSize; + +#elif defined(_OS_LINUX_) || defined(_OS_DARWIN_) || defined (_OS_FREEBSD_) + struct rusage rusage; + getrusage( RUSAGE_SELF, &rusage ); + +#if defined(_OS_LINUX_) + return (size_t)(rusage.ru_maxrss * 1024); +#else + return (size_t)rusage.ru_maxrss; +#endif + +#else + return (size_t)0; +#endif +} + + + #ifdef __cplusplus } #endif diff --git a/test/choosetests.jl b/test/choosetests.jl index 2a2eecfcbe248..ad3027f08d9a8 100644 --- a/test/choosetests.jl +++ b/test/choosetests.jl @@ -32,7 +32,7 @@ function choosetests(choices = []) "nullable", "meta", "profile", "libgit2", "docs", "markdown", "base64", "serialize", "functors", "misc", "enums", "cmdlineargs", "i18n", "workspace", "libdl", "int", - "intset", "floatfuncs", "compile" + "intset", "floatfuncs", "compile", "parallel" ] if Base.USE_GPL_LIBS @@ -43,9 +43,6 @@ function choosetests(choices = []) push!(testnames, "examples") end - # parallel tests depend on other workers - do them last - push!(testnames, "parallel") - tests = [] skip_tests = [] diff --git a/test/examples.jl b/test/examples.jl index fb64ce6b418ad..ca363b31e6c86 100644 --- a/test/examples.jl +++ b/test/examples.jl @@ -51,11 +51,10 @@ end dc_path = joinpath(dir, "dictchannel.jl") include(dc_path) -w_set=filter!(x->x != myid(), workers()) -pid = length(w_set) > 0 ? w_set[1] : myid() - -remotecall_fetch(pid, f->(include(f); nothing), dc_path) -dc=RemoteRef(()->DictChannel(), pid) +# Run the remote on pid 1, since runtests may terminate workers +# at any time depending on memory usage +remotecall_fetch(1, f->(include(f); nothing), dc_path) +dc=RemoteRef(()->DictChannel(), 1) @test typeof(dc) == RemoteRef{DictChannel} @test isready(dc) == false diff --git a/test/parallel.jl b/test/parallel.jl index 77e58b7461086..777cec5bfc300 100644 --- a/test/parallel.jl +++ b/test/parallel.jl @@ -1,544 +1,14 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license -# NOTE: worker processes cannot add more workers, only the client process can. -using Base.Test +# Run the parallel test outside of the main driver, since it runs off its own +# set of workers. -if nworkers() < 3 - remotecall_fetch(1, () -> addprocs(3 - nworkers())) -end - -id_me = myid() -id_other = filter(x -> x != id_me, procs())[rand(1:(nprocs()-1))] - -@test fetch(@spawnat id_other myid()) == id_other -@test @fetchfrom id_other begin myid() end == id_other -@fetch begin myid() end - -rr=RemoteRef() -@test typeof(rr) == RemoteRef{Channel{Any}} -a = rand(5,5) -put!(rr, a) -@test rr[2,3] == a[2,3] -@test rr[] == a - -rr=RemoteRef(workers()[1]) -@test typeof(rr) == RemoteRef{Channel{Any}} -a = rand(5,5) -put!(rr, a) -@test rr[1,5] == a[1,5] -@test rr[] == a - -dims = (20,20,20) - -@linux_only begin - S = SharedArray(Int64, dims) - @test startswith(S.segname, "/jl") - @test !ispath("/dev/shm" * S.segname) - - S = SharedArray(Int64, dims; pids=[id_other]) - @test startswith(S.segname, "/jl") - @test !ispath("/dev/shm" * S.segname) -end - -# TODO : Need a similar test of shmem cleanup for OSX - -##### SharedArray tests - -function check_pids_all(S::SharedArray) - pidtested = falses(size(S)) - for p in procs(S) - idxes_in_p = remotecall_fetch(p, D -> parentindexes(D.loc_subarr_1d)[1], S) - @test all(sdata(S)[idxes_in_p] .== p) - pidtested[idxes_in_p] = true - end - @test all(pidtested) -end - -d = Base.shmem_rand(1:100, dims) -a = convert(Array, d) - -partsums = Array(Int, length(procs(d))) -@sync begin - for (i, p) in enumerate(procs(d)) - @async partsums[i] = remotecall_fetch(p, D->sum(D.loc_subarr_1d), d) - end -end -@test sum(a) == sum(partsums) - -d = Base.shmem_rand(dims) -for p in procs(d) - idxes_in_p = remotecall_fetch(p, D -> parentindexes(D.loc_subarr_1d)[1], d) - idxf = first(idxes_in_p) - idxl = last(idxes_in_p) - d[idxf] = Float64(idxf) - rv = remotecall_fetch(p, (D,idxf,idxl) -> begin assert(D[idxf] == Float64(idxf)); D[idxl] = Float64(idxl); D[idxl]; end, d,idxf,idxl) - @test d[idxl] == rv -end - -@test ones(10, 10, 10) == Base.shmem_fill(1.0, (10,10,10)) -@test zeros(Int32, 10, 10, 10) == Base.shmem_fill(0, (10,10,10)) +cmd = `$(Base.julia_cmd()) --check-bounds=yes --depwarn=error parallel_exec.jl` -d = Base.shmem_rand(dims) -s = Base.shmem_rand(dims) -copy!(s, d) -@test s == d -s = Base.shmem_rand(dims) -copy!(s, sdata(d)) -@test s == d -a = rand(dims) -@test sdata(a) == a - -d = SharedArray(Int, dims; init = D->fill!(D.loc_subarr_1d, myid())) -for p in procs(d) - idxes_in_p = remotecall_fetch(p, D -> parentindexes(D.loc_subarr_1d)[1], d) - idxf = first(idxes_in_p) - idxl = last(idxes_in_p) - @test d[idxf] == p - @test d[idxl] == p +(strm, proc) = open(cmd) +errors = readall(strm) +wait(proc) +if !success(proc) && ccall(:jl_running_on_valgrind,Cint,()) == 0 + println(errors); + error("Parallel test failed, cmd : $cmd") end - -d = SharedArray(Float64, (2,3)) -@test isa(d[:,2], Vector{Float64}) - -### SharedArrays from a file - -# Mapping an existing file -fn = tempname() -open(fn, "w") do io - write(io, 1:30) -end -sz = (6,5) -Atrue = reshape(1:30, sz) - -S = SharedArray(fn, Int, sz) -@test S == Atrue -@test length(procs(S)) > 1 -@sync begin - for p in procs(S) - @async remotecall_wait(p, D->fill!(D.loc_subarr_1d, myid()), S) - end -end -check_pids_all(S) - -filedata = similar(Atrue) -open(fn, "r") do io - read!(io, filedata) -end -@test filedata == sdata(S) - -# Error for write-only files -@test_throws ArgumentError SharedArray(fn, Int, sz, mode="w") - -# Error for file doesn't exist, but not allowed to create -@test_throws ArgumentError SharedArray(tempname(), Int, sz, mode="r") - -# Creating a new file -fn2 = tempname() -S = SharedArray(fn2, Int, sz, init=D->D[localindexes(D)] = myid()) -@test S == filedata -filedata2 = similar(Atrue) -open(fn2, "r") do io - read!(io, filedata2) -end -@test filedata == filedata2 - -# Appending to a file -fn3 = tempname() -open(fn3, "w") do io - write(io, ones(UInt8, 4)) -end -S = SharedArray(fn3, UInt8, sz, 4, mode="a+", init=D->D[localindexes(D)]=0x02) -len = prod(sz)+4 -@test filesize(fn3) == len -filedata = Array(UInt8, len) -open(fn3, "r") do io - read!(io, filedata) -end -@test all(filedata[1:4] .== 0x01) -@test all(filedata[5:end] .== 0x02) - -@unix_only begin # these give unlink: operation not permitted (EPERM) on Windows - rm(fn); rm(fn2); rm(fn3) -end - -### Utility functions - -# reshape - -d = Base.shmem_fill(1.0, (10,10,10)) -@test ones(100, 10) == reshape(d,(100,10)) -d = Base.shmem_fill(1.0, (10,10,10)) -@test_throws DimensionMismatch reshape(d,(50,)) - -# rand, randn -d = Base.shmem_rand(dims) -@test size(rand!(d)) == dims -d = Base.shmem_fill(1.0, dims) -@test size(randn!(d)) == dims - -# similar -d = Base.shmem_rand(dims) -@test size(similar(d, Complex128)) == dims -@test size(similar(d, dims)) == dims - -# issue #6362 -d = Base.shmem_rand(dims) -s = copy(sdata(d)) -ds = deepcopy(d) -@test ds == d -pids_d = procs(d) -remotecall_fetch(pids_d[findfirst(id->(id != myid()), pids_d)], setindex!, d, 1.0, 1:10) -@test ds != d -@test s != d - - -# SharedArray as an array -# Since the data in d will depend on the nprocs, just test that these operations work -a = d[1:5] -@test_throws BoundsError d[-1:5] -a = d[1,1,1:3:end] -d[2:4] = 7 -d[5,1:2:4,8] = 19 - -AA = rand(4,2) -A = convert(SharedArray, AA) -B = convert(SharedArray, AA') -@test B*A == ctranspose(AA)*AA - -d=SharedArray(Int64, (10,10); init = D->fill!(D.loc_subarr_1d, myid()), pids=[id_me, id_other]) -d2 = map(x->1, d) -@test reduce(+, d2) == 100 - -@test reduce(+, d) == ((50*id_me) + (50*id_other)) -map!(x->1, d) -@test reduce(+, d) == 100 - -@test fill!(d, 1) == ones(10, 10) -@test fill!(d, 2.) == fill(2, 10, 10) -@test d[:] == fill(2, 100) -@test d[:,1] == fill(2, 10) -@test d[1,:] == fill(2, 1, 10) - -# Boundary cases where length(S) <= length(pids) -@test 2.0 == remotecall_fetch(id_other, D->D[2], Base.shmem_fill(2.0, 2; pids=[id_me, id_other])) -@test 3.0 == remotecall_fetch(id_other, D->D[1], Base.shmem_fill(3.0, 1; pids=[id_me, id_other])) - -# Test @parallel load balancing - all processors should get either M or M+1 -# iterations out of the loop range for some M. -workloads = hist(@parallel((a,b)->[a;b], for i=1:7; myid(); end), nprocs())[2] -@test maximum(workloads) - minimum(workloads) <= 1 - -# @parallel reduction should work even with very short ranges -@test @parallel(+, for i=1:2; i; end) == 3 - -# Testing timedwait on multiple channels -@sync begin - rr1 = Channel() - rr2 = Channel() - rr3 = Channel() - - @async begin sleep(0.5); put!(rr1, :ok) end - @async begin sleep(1.0); put!(rr2, :ok) end - @async begin sleep(2.0); put!(rr3, :ok) end - - tic() - timedwait(1.0) do - all(map(isready, [rr1, rr2, rr3])) - end - et=toq() - # assuming that 0.5 seconds is a good enough buffer on a typical modern CPU - try - @test (et >= 1.0) && (et <= 1.5) - @test !isready(rr3) - catch - warn("timedwait tests delayed. et=$et, isready(rr3)=$(isready(rr3))") - end - @test isready(rr1) -end - -@test_throws ArgumentError sleep(-1) -@test_throws ArgumentError timedwait(()->false, 0.1, pollint=-0.5) - -# specify pids for pmap -@test sort(workers()[1:2]) == sort(unique(pmap(x->(sleep(0.1);myid()), 1:10, pids = workers()[1:2]))) - -# Testing buffered and unbuffered reads -# This large array should write directly to the socket -a = ones(10^6) -@test a == remotecall_fetch(id_other, (x)->x, a) - -# Not a bitstype, should be buffered -s = [randstring() for x in 1:10^5] -@test s == remotecall_fetch(id_other, (x)->x, s) - -#large number of small requests -num_small_requests = 10000 -@test fill(id_other, num_small_requests) == [remotecall_fetch(id_other, myid) for i in 1:num_small_requests] - -# test parallel sends of large arrays from multiple tasks to the same remote worker -ntasks = 10 -rr_list = [Channel() for x in 1:ntasks] -a=ones(2*10^5); -for rr in rr_list - @async let rr=rr - try - for i in 1:10 - @test a == remotecall_fetch(id_other, (x)->x, a) - yield() - end - put!(rr, :OK) - catch - put!(rr, :ERROR) - end - end -end - -@test [fetch(rr) for rr in rr_list] == [:OK for x in 1:ntasks] - -function test_channel(c) - put!(c, 1) - put!(c, "Hello") - put!(c, 5.0) - - @test isready(c) == true - @test fetch(c) == 1 - @test fetch(c) == 1 # Should not have been popped previously - @test take!(c) == 1 - @test take!(c) == "Hello" - @test fetch(c) == 5.0 - @test take!(c) == 5.0 - @test isready(c) == false - close(c) -end - -test_channel(Channel(10)) -test_channel(RemoteRef(()->Channel(10))) - -c=Channel{Int}(1) -@test_throws MethodError put!(c, "Hello") - -c=Channel(256) -# Test growth of channel -@test c.szp1 <= 33 -for x in 1:40 - put!(c, x) -end -@test c.szp1 <= 65 -for x in 1:39 - take!(c) -end -for x in 1:64 - put!(c, x) -end -@test (c.szp1 > 65) && (c.szp1 <= 129) -for x in 1:39 - take!(c) -end -@test fetch(c) == 39 -for x in 1:26 - take!(c) -end -@test isready(c) == false - -# test channel iterations -function test_iteration(in_c, out_c) - t=@schedule for v in in_c - put!(out_c, v) - end - - isa(in_c, Channel) && @test isopen(in_c) == true - put!(in_c, 1) - @test take!(out_c) == 1 - put!(in_c, "Hello") - close(in_c) - @test take!(out_c) == "Hello" - isa(in_c, Channel) && @test isopen(in_c) == false - @test_throws InvalidStateException put!(in_c, :foo) - yield() - @test istaskdone(t) == true -end - -test_iteration(Channel(10), Channel(10)) -# make sure exceptions propagate when waiting on Tasks -@test_throws CompositeException (@sync (@async error("oops"))) -try - @sync begin - for i in 1:5 - @async error(i) - end - end - error("unexpected") -catch ex - @test typeof(ex) == CompositeException - @test length(ex) == 5 - @test typeof(ex.exceptions[1]) == CapturedException - @test typeof(ex.exceptions[1].ex) == ErrorException - errors = map(x->x.ex.msg, ex.exceptions) - @test collect(1:5) == sort(map(x->parse(Int, x), errors)) -end - -macro test_remoteexception_thrown(expr) - quote - try - $(esc(expr)) - error("unexpected") - catch ex - @test typeof(ex) == RemoteException - @test typeof(ex.captured) == CapturedException - @test typeof(ex.captured.ex) == ErrorException - @test ex.captured.ex.msg == "foobar" - end - end -end - -for id in [id_other, id_me] - @test_remoteexception_thrown remotecall_fetch(id, ()->throw(ErrorException("foobar"))) - @test_remoteexception_thrown remotecall_wait(id, ()->throw(ErrorException("foobar"))) - @test_remoteexception_thrown wait(remotecall(id, ()->throw(ErrorException("foobar")))) -end - -# The below block of tests are usually run only on local development systems, since: -# - tests which print errors -# - addprocs tests are memory intensive -# - ssh addprocs requires sshd to be running locally with passwordless login enabled. -# The test block is enabled by defining env JULIA_TESTFULL=1 - -DoFullTest = Bool(parse(Int,(get(ENV, "JULIA_TESTFULL", "0")))) - -if DoFullTest - # pmap tests - # needs at least 4 processors dedicated to the below tests - ppids = remotecall_fetch(1, ()->addprocs(4)) - s = "abcdefghijklmnopqrstuvwxyz"; - ups = uppercase(s); - @test ups == bytestring(UInt8[UInt8(c) for c in pmap(x->uppercase(x), s)]) - @test ups == bytestring(UInt8[UInt8(c) for c in pmap(x->uppercase(Char(x)), s.data)]) - - # retry, on error exit - res = pmap(x->(x=='a') ? error("EXPECTED TEST ERROR. TO BE IGNORED.") : (sleep(0.1);uppercase(x)), s; err_retry=true, err_stop=true, pids=ppids); - @test (length(res) < length(ups)) - @test isa(res[1], Exception) - - # no retry, on error exit - res = pmap(x->(x=='a') ? error("EXPECTED TEST ERROR. TO BE IGNORED.") : (sleep(0.1);uppercase(x)), s; err_retry=false, err_stop=true, pids=ppids); - @test (length(res) < length(ups)) - @test isa(res[1], Exception) - - # retry, on error continue - res = pmap(x->iseven(myid()) ? error("EXPECTED TEST ERROR. TO BE IGNORED.") : (sleep(0.1);uppercase(x)), s; err_retry=true, err_stop=false, pids=ppids); - @test length(res) == length(ups) - @test ups == bytestring(UInt8[UInt8(c) for c in res]) - - # no retry, on error continue - res = pmap(x->(x=='a') ? error("EXPECTED TEST ERROR. TO BE IGNORED.") : (sleep(0.1);uppercase(x)), s; err_retry=false, err_stop=false, pids=ppids); - @test length(res) == length(ups) - @test isa(res[1], Exception) - - # Topology tests need to run externally since a given cluster at any - # time can only support a single topology and the current session - # is already running in parallel under the default topology. - script = joinpath(dirname(@__FILE__), "topology.jl") - cmd = `$(joinpath(JULIA_HOME,Base.julia_exename())) $script` - - (strm, proc) = open(cmd) - wait(proc) - if !success(proc) && ccall(:jl_running_on_valgrind,Cint,()) == 0 - println(readall(strm)) - error("Topology tests failed : $cmd") - end - - println("Testing exception printing on remote worker from a `remote_do` call") - println("Please ensure the remote error and backtrace is displayed on screen") - - Base.remote_do(id_other, ()->throw(ErrorException("TESTING EXCEPTION ON REMOTE DO. PLEASE IGNORE"))) - sleep(0.5) # Give some time for the above error to be printed - -@unix_only begin - function test_n_remove_pids(new_pids) - for p in new_pids - w_in_remote = sort(remotecall_fetch(p, workers)) - try - @test intersect(new_pids, w_in_remote) == new_pids - catch e - print("p : $p\n") - print("newpids : $new_pids\n") - print("w_in_remote : $w_in_remote\n") - print("intersect : $(intersect(new_pids, w_in_remote))\n\n\n") - rethrow(e) - end - end - - @test :ok == remotecall_fetch(1, (p)->rmprocs(p; waitfor=5.0), new_pids) - end - - print("\n\nTesting SSHManager. A minimum of 4GB of RAM is recommended.\n") - print("Please ensure sshd is running locally with passwordless login enabled.\n") - - sshflags = `-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR ` - #Issue #9951 - hosts=[] - localhost_aliases = ["localhost", string(getipaddr()), "127.0.0.1"] - num_workers = parse(Int,(get(ENV, "JULIA_ADDPROCS_NUM", "9"))) - - for i in 1:(num_workers/length(localhost_aliases)) - append!(hosts, localhost_aliases) - end - - print("\nTesting SSH addprocs with $(length(hosts)) workers...\n") - new_pids = remotecall_fetch(1, (h, sf) -> addprocs(h; sshflags=sf), hosts, sshflags) - @test length(new_pids) == length(hosts) - test_n_remove_pids(new_pids) - - print("\nMixed ssh addprocs with :auto\n") - new_pids = sort(remotecall_fetch(1, (h, sf) -> addprocs(h; sshflags=sf), ["localhost", ("127.0.0.1", :auto), "localhost"], sshflags)) - @test length(new_pids) == (2 + Sys.CPU_CORES) - test_n_remove_pids(new_pids) - - print("\nMixed ssh addprocs with numeric counts\n") - new_pids = sort(remotecall_fetch(1, (h, sf) -> addprocs(h; sshflags=sf), [("localhost", 2), ("127.0.0.1", 2), "localhost"], sshflags)) - @test length(new_pids) == 5 - test_n_remove_pids(new_pids) - - print("\nssh addprocs with tunnel\n") - new_pids = sort(remotecall_fetch(1, (h, sf) -> addprocs(h; tunnel=true, sshflags=sf), [("localhost", num_workers)], sshflags)) - @test length(new_pids) == num_workers - test_n_remove_pids(new_pids) - -end -end - -# issue #7727 -let A = [], B = [] - t = @task produce(11) - @sync begin - @async for x in t; push!(A,x); end - @async for x in t; push!(B,x); end - end - @test (A == [11]) != (B == [11]) -end - -let t = @task 42 - schedule(t, ErrorException(""), error=true) - @test_throws ErrorException wait(t) -end - -# issue #8207 -let A = Any[] - @parallel (+) for i in (push!(A,1); 1:2) - i - end - @test length(A) == 1 -end - -# issue #13168 -function f13168(n) - val = 0 - for i=1:n val+=sum(rand(n,n)^2) end - val -end -let t = schedule(@task f13168(100)) - @test schedule(t) === t -end - -# issue #13122 -@test remotecall_fetch(workers()[1], identity, C_NULL) === C_NULL diff --git a/test/parallel_exec.jl b/test/parallel_exec.jl new file mode 100644 index 0000000000000..ac88d587c071b --- /dev/null +++ b/test/parallel_exec.jl @@ -0,0 +1,541 @@ +# This file is a part of Julia. License is MIT: http://julialang.org/license + +using Base.Test + +addprocs(3; exeflags=`--check-bounds=yes --depwarn=error`) + +id_me = myid() +id_other = filter(x -> x != id_me, procs())[rand(1:(nprocs()-1))] + +@test fetch(@spawnat id_other myid()) == id_other +@test @fetchfrom id_other begin myid() end == id_other +@fetch begin myid() end + +rr=RemoteRef() +@test typeof(rr) == RemoteRef{Channel{Any}} +a = rand(5,5) +put!(rr, a) +@test rr[2,3] == a[2,3] +@test rr[] == a + +rr=RemoteRef(workers()[1]) +@test typeof(rr) == RemoteRef{Channel{Any}} +a = rand(5,5) +put!(rr, a) +@test rr[1,5] == a[1,5] +@test rr[] == a + +dims = (20,20,20) + +@linux_only begin + S = SharedArray(Int64, dims) + @test startswith(S.segname, "/jl") + @test !ispath("/dev/shm" * S.segname) + + S = SharedArray(Int64, dims; pids=[id_other]) + @test startswith(S.segname, "/jl") + @test !ispath("/dev/shm" * S.segname) +end + +# TODO : Need a similar test of shmem cleanup for OSX + +##### SharedArray tests + +function check_pids_all(S::SharedArray) + pidtested = falses(size(S)) + for p in procs(S) + idxes_in_p = remotecall_fetch(p, D -> parentindexes(D.loc_subarr_1d)[1], S) + @test all(sdata(S)[idxes_in_p] .== p) + pidtested[idxes_in_p] = true + end + @test all(pidtested) +end + +d = Base.shmem_rand(1:100, dims) +a = convert(Array, d) + +partsums = Array(Int, length(procs(d))) +@sync begin + for (i, p) in enumerate(procs(d)) + @async partsums[i] = remotecall_fetch(p, D->sum(D.loc_subarr_1d), d) + end +end +@test sum(a) == sum(partsums) + +d = Base.shmem_rand(dims) +for p in procs(d) + idxes_in_p = remotecall_fetch(p, D -> parentindexes(D.loc_subarr_1d)[1], d) + idxf = first(idxes_in_p) + idxl = last(idxes_in_p) + d[idxf] = Float64(idxf) + rv = remotecall_fetch(p, (D,idxf,idxl) -> begin assert(D[idxf] == Float64(idxf)); D[idxl] = Float64(idxl); D[idxl]; end, d,idxf,idxl) + @test d[idxl] == rv +end + +@test ones(10, 10, 10) == Base.shmem_fill(1.0, (10,10,10)) +@test zeros(Int32, 10, 10, 10) == Base.shmem_fill(0, (10,10,10)) + +d = Base.shmem_rand(dims) +s = Base.shmem_rand(dims) +copy!(s, d) +@test s == d +s = Base.shmem_rand(dims) +copy!(s, sdata(d)) +@test s == d +a = rand(dims) +@test sdata(a) == a + +d = SharedArray(Int, dims; init = D->fill!(D.loc_subarr_1d, myid())) +for p in procs(d) + idxes_in_p = remotecall_fetch(p, D -> parentindexes(D.loc_subarr_1d)[1], d) + idxf = first(idxes_in_p) + idxl = last(idxes_in_p) + @test d[idxf] == p + @test d[idxl] == p +end + +d = SharedArray(Float64, (2,3)) +@test isa(d[:,2], Vector{Float64}) + +### SharedArrays from a file + +# Mapping an existing file +fn = tempname() +open(fn, "w") do io + write(io, 1:30) +end +sz = (6,5) +Atrue = reshape(1:30, sz) + +S = SharedArray(fn, Int, sz) +@test S == Atrue +@test length(procs(S)) > 1 +@sync begin + for p in procs(S) + @async remotecall_wait(p, D->fill!(D.loc_subarr_1d, myid()), S) + end +end +check_pids_all(S) + +filedata = similar(Atrue) +open(fn, "r") do io + read!(io, filedata) +end +@test filedata == sdata(S) + +# Error for write-only files +@test_throws ArgumentError SharedArray(fn, Int, sz, mode="w") + +# Error for file doesn't exist, but not allowed to create +@test_throws ArgumentError SharedArray(tempname(), Int, sz, mode="r") + +# Creating a new file +fn2 = tempname() +S = SharedArray(fn2, Int, sz, init=D->D[localindexes(D)] = myid()) +@test S == filedata +filedata2 = similar(Atrue) +open(fn2, "r") do io + read!(io, filedata2) +end +@test filedata == filedata2 + +# Appending to a file +fn3 = tempname() +open(fn3, "w") do io + write(io, ones(UInt8, 4)) +end +S = SharedArray(fn3, UInt8, sz, 4, mode="a+", init=D->D[localindexes(D)]=0x02) +len = prod(sz)+4 +@test filesize(fn3) == len +filedata = Array(UInt8, len) +open(fn3, "r") do io + read!(io, filedata) +end +@test all(filedata[1:4] .== 0x01) +@test all(filedata[5:end] .== 0x02) + +@unix_only begin # these give unlink: operation not permitted (EPERM) on Windows + rm(fn); rm(fn2); rm(fn3) +end + +### Utility functions + +# reshape + +d = Base.shmem_fill(1.0, (10,10,10)) +@test ones(100, 10) == reshape(d,(100,10)) +d = Base.shmem_fill(1.0, (10,10,10)) +@test_throws DimensionMismatch reshape(d,(50,)) + +# rand, randn +d = Base.shmem_rand(dims) +@test size(rand!(d)) == dims +d = Base.shmem_fill(1.0, dims) +@test size(randn!(d)) == dims + +# similar +d = Base.shmem_rand(dims) +@test size(similar(d, Complex128)) == dims +@test size(similar(d, dims)) == dims + +# issue #6362 +d = Base.shmem_rand(dims) +s = copy(sdata(d)) +ds = deepcopy(d) +@test ds == d +pids_d = procs(d) +remotecall_fetch(pids_d[findfirst(id->(id != myid()), pids_d)], setindex!, d, 1.0, 1:10) +@test ds != d +@test s != d + + +# SharedArray as an array +# Since the data in d will depend on the nprocs, just test that these operations work +a = d[1:5] +@test_throws BoundsError d[-1:5] +a = d[1,1,1:3:end] +d[2:4] = 7 +d[5,1:2:4,8] = 19 + +AA = rand(4,2) +A = convert(SharedArray, AA) +B = convert(SharedArray, AA') +@test B*A == ctranspose(AA)*AA + +d=SharedArray(Int64, (10,10); init = D->fill!(D.loc_subarr_1d, myid()), pids=[id_me, id_other]) +d2 = map(x->1, d) +@test reduce(+, d2) == 100 + +@test reduce(+, d) == ((50*id_me) + (50*id_other)) +map!(x->1, d) +@test reduce(+, d) == 100 + +@test fill!(d, 1) == ones(10, 10) +@test fill!(d, 2.) == fill(2, 10, 10) +@test d[:] == fill(2, 100) +@test d[:,1] == fill(2, 10) +@test d[1,:] == fill(2, 1, 10) + +# Boundary cases where length(S) <= length(pids) +@test 2.0 == remotecall_fetch(id_other, D->D[2], Base.shmem_fill(2.0, 2; pids=[id_me, id_other])) +@test 3.0 == remotecall_fetch(id_other, D->D[1], Base.shmem_fill(3.0, 1; pids=[id_me, id_other])) + +# Test @parallel load balancing - all processors should get either M or M+1 +# iterations out of the loop range for some M. +workloads = hist(@parallel((a,b)->[a;b], for i=1:7; myid(); end), nprocs())[2] +@test maximum(workloads) - minimum(workloads) <= 1 + +# @parallel reduction should work even with very short ranges +@test @parallel(+, for i=1:2; i; end) == 3 + +# Testing timedwait on multiple channels +@sync begin + rr1 = Channel() + rr2 = Channel() + rr3 = Channel() + + @async begin sleep(0.5); put!(rr1, :ok) end + @async begin sleep(1.0); put!(rr2, :ok) end + @async begin sleep(2.0); put!(rr3, :ok) end + + tic() + timedwait(1.0) do + all(map(isready, [rr1, rr2, rr3])) + end + et=toq() + # assuming that 0.5 seconds is a good enough buffer on a typical modern CPU + try + @test (et >= 1.0) && (et <= 1.5) + @test !isready(rr3) + catch + warn("timedwait tests delayed. et=$et, isready(rr3)=$(isready(rr3))") + end + @test isready(rr1) +end + +@test_throws ArgumentError sleep(-1) +@test_throws ArgumentError timedwait(()->false, 0.1, pollint=-0.5) + +# specify pids for pmap +@test sort(workers()[1:2]) == sort(unique(pmap(x->(sleep(0.1);myid()), 1:10, pids = workers()[1:2]))) + +# Testing buffered and unbuffered reads +# This large array should write directly to the socket +a = ones(10^6) +@test a == remotecall_fetch(id_other, (x)->x, a) + +# Not a bitstype, should be buffered +s = [randstring() for x in 1:10^5] +@test s == remotecall_fetch(id_other, (x)->x, s) + +#large number of small requests +num_small_requests = 10000 +@test fill(id_other, num_small_requests) == [remotecall_fetch(id_other, myid) for i in 1:num_small_requests] + +# test parallel sends of large arrays from multiple tasks to the same remote worker +ntasks = 10 +rr_list = [Channel() for x in 1:ntasks] +a=ones(2*10^5); +for rr in rr_list + @async let rr=rr + try + for i in 1:10 + @test a == remotecall_fetch(id_other, (x)->x, a) + yield() + end + put!(rr, :OK) + catch + put!(rr, :ERROR) + end + end +end + +@test [fetch(rr) for rr in rr_list] == [:OK for x in 1:ntasks] + +function test_channel(c) + put!(c, 1) + put!(c, "Hello") + put!(c, 5.0) + + @test isready(c) == true + @test fetch(c) == 1 + @test fetch(c) == 1 # Should not have been popped previously + @test take!(c) == 1 + @test take!(c) == "Hello" + @test fetch(c) == 5.0 + @test take!(c) == 5.0 + @test isready(c) == false + close(c) +end + +test_channel(Channel(10)) +test_channel(RemoteRef(()->Channel(10))) + +c=Channel{Int}(1) +@test_throws MethodError put!(c, "Hello") + +c=Channel(256) +# Test growth of channel +@test c.szp1 <= 33 +for x in 1:40 + put!(c, x) +end +@test c.szp1 <= 65 +for x in 1:39 + take!(c) +end +for x in 1:64 + put!(c, x) +end +@test (c.szp1 > 65) && (c.szp1 <= 129) +for x in 1:39 + take!(c) +end +@test fetch(c) == 39 +for x in 1:26 + take!(c) +end +@test isready(c) == false + +# test channel iterations +function test_iteration(in_c, out_c) + t=@schedule for v in in_c + put!(out_c, v) + end + + isa(in_c, Channel) && @test isopen(in_c) == true + put!(in_c, 1) + @test take!(out_c) == 1 + put!(in_c, "Hello") + close(in_c) + @test take!(out_c) == "Hello" + isa(in_c, Channel) && @test isopen(in_c) == false + @test_throws InvalidStateException put!(in_c, :foo) + yield() + @test istaskdone(t) == true +end + +test_iteration(Channel(10), Channel(10)) +# make sure exceptions propagate when waiting on Tasks +@test_throws CompositeException (@sync (@async error("oops"))) +try + @sync begin + for i in 1:5 + @async error(i) + end + end + error("unexpected") +catch ex + @test typeof(ex) == CompositeException + @test length(ex) == 5 + @test typeof(ex.exceptions[1]) == CapturedException + @test typeof(ex.exceptions[1].ex) == ErrorException + errors = map(x->x.ex.msg, ex.exceptions) + @test collect(1:5) == sort(map(x->parse(Int, x), errors)) +end + +macro test_remoteexception_thrown(expr) + quote + try + $(esc(expr)) + error("unexpected") + catch ex + @test typeof(ex) == RemoteException + @test typeof(ex.captured) == CapturedException + @test typeof(ex.captured.ex) == ErrorException + @test ex.captured.ex.msg == "foobar" + end + end +end + +for id in [id_other, id_me] + @test_remoteexception_thrown remotecall_fetch(id, ()->throw(ErrorException("foobar"))) + @test_remoteexception_thrown remotecall_wait(id, ()->throw(ErrorException("foobar"))) + @test_remoteexception_thrown wait(remotecall(id, ()->throw(ErrorException("foobar")))) +end + +# The below block of tests are usually run only on local development systems, since: +# - tests which print errors +# - addprocs tests are memory intensive +# - ssh addprocs requires sshd to be running locally with passwordless login enabled. +# The test block is enabled by defining env JULIA_TESTFULL=1 + +DoFullTest = Bool(parse(Int,(get(ENV, "JULIA_TESTFULL", "0")))) + +if DoFullTest + # pmap tests + # needs at least 4 processors dedicated to the below tests + ppids = remotecall_fetch(1, ()->addprocs(4)) + s = "abcdefghijklmnopqrstuvwxyz"; + ups = uppercase(s); + @test ups == bytestring(UInt8[UInt8(c) for c in pmap(x->uppercase(x), s)]) + @test ups == bytestring(UInt8[UInt8(c) for c in pmap(x->uppercase(Char(x)), s.data)]) + + # retry, on error exit + res = pmap(x->(x=='a') ? error("EXPECTED TEST ERROR. TO BE IGNORED.") : (sleep(0.1);uppercase(x)), s; err_retry=true, err_stop=true, pids=ppids); + @test (length(res) < length(ups)) + @test isa(res[1], Exception) + + # no retry, on error exit + res = pmap(x->(x=='a') ? error("EXPECTED TEST ERROR. TO BE IGNORED.") : (sleep(0.1);uppercase(x)), s; err_retry=false, err_stop=true, pids=ppids); + @test (length(res) < length(ups)) + @test isa(res[1], Exception) + + # retry, on error continue + res = pmap(x->iseven(myid()) ? error("EXPECTED TEST ERROR. TO BE IGNORED.") : (sleep(0.1);uppercase(x)), s; err_retry=true, err_stop=false, pids=ppids); + @test length(res) == length(ups) + @test ups == bytestring(UInt8[UInt8(c) for c in res]) + + # no retry, on error continue + res = pmap(x->(x=='a') ? error("EXPECTED TEST ERROR. TO BE IGNORED.") : (sleep(0.1);uppercase(x)), s; err_retry=false, err_stop=false, pids=ppids); + @test length(res) == length(ups) + @test isa(res[1], Exception) + + # Topology tests need to run externally since a given cluster at any + # time can only support a single topology and the current session + # is already running in parallel under the default topology. + script = joinpath(dirname(@__FILE__), "topology.jl") + cmd = `$(joinpath(JULIA_HOME,Base.julia_exename())) $script` + + (strm, proc) = open(cmd) + wait(proc) + if !success(proc) && ccall(:jl_running_on_valgrind,Cint,()) == 0 + println(readall(strm)) + error("Topology tests failed : $cmd") + end + + println("Testing exception printing on remote worker from a `remote_do` call") + println("Please ensure the remote error and backtrace is displayed on screen") + + Base.remote_do(id_other, ()->throw(ErrorException("TESTING EXCEPTION ON REMOTE DO. PLEASE IGNORE"))) + sleep(0.5) # Give some time for the above error to be printed + +@unix_only begin + function test_n_remove_pids(new_pids) + for p in new_pids + w_in_remote = sort(remotecall_fetch(p, workers)) + try + @test intersect(new_pids, w_in_remote) == new_pids + catch e + print("p : $p\n") + print("newpids : $new_pids\n") + print("w_in_remote : $w_in_remote\n") + print("intersect : $(intersect(new_pids, w_in_remote))\n\n\n") + rethrow(e) + end + end + + @test :ok == remotecall_fetch(1, (p)->rmprocs(p; waitfor=5.0), new_pids) + end + + print("\n\nTesting SSHManager. A minimum of 4GB of RAM is recommended.\n") + print("Please ensure sshd is running locally with passwordless login enabled.\n") + + sshflags = `-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR ` + #Issue #9951 + hosts=[] + localhost_aliases = ["localhost", string(getipaddr()), "127.0.0.1"] + num_workers = parse(Int,(get(ENV, "JULIA_ADDPROCS_NUM", "9"))) + + for i in 1:(num_workers/length(localhost_aliases)) + append!(hosts, localhost_aliases) + end + + print("\nTesting SSH addprocs with $(length(hosts)) workers...\n") + new_pids = remotecall_fetch(1, (h, sf) -> addprocs(h; sshflags=sf), hosts, sshflags) + @test length(new_pids) == length(hosts) + test_n_remove_pids(new_pids) + + print("\nMixed ssh addprocs with :auto\n") + new_pids = sort(remotecall_fetch(1, (h, sf) -> addprocs(h; sshflags=sf), ["localhost", ("127.0.0.1", :auto), "localhost"], sshflags)) + @test length(new_pids) == (2 + Sys.CPU_CORES) + test_n_remove_pids(new_pids) + + print("\nMixed ssh addprocs with numeric counts\n") + new_pids = sort(remotecall_fetch(1, (h, sf) -> addprocs(h; sshflags=sf), [("localhost", 2), ("127.0.0.1", 2), "localhost"], sshflags)) + @test length(new_pids) == 5 + test_n_remove_pids(new_pids) + + print("\nssh addprocs with tunnel\n") + new_pids = sort(remotecall_fetch(1, (h, sf) -> addprocs(h; tunnel=true, sshflags=sf), [("localhost", num_workers)], sshflags)) + @test length(new_pids) == num_workers + test_n_remove_pids(new_pids) + +end +end + +# issue #7727 +let A = [], B = [] + t = @task produce(11) + @sync begin + @async for x in t; push!(A,x); end + @async for x in t; push!(B,x); end + end + @test (A == [11]) != (B == [11]) +end + +let t = @task 42 + schedule(t, ErrorException(""), error=true) + @test_throws ErrorException wait(t) +end + +# issue #8207 +let A = Any[] + @parallel (+) for i in (push!(A,1); 1:2) + i + end + @test length(A) == 1 +end + +# issue #13168 +function f13168(n) + val = 0 + for i=1:n val+=sum(rand(n,n)^2) end + val +end +let t = schedule(@task f13168(100)) + @test schedule(t) === t +end + +# issue #13122 +@test remotecall_fetch(workers()[1], identity, C_NULL) === C_NULL diff --git a/test/runtests.jl b/test/runtests.jl index 349faf18c64f9..e032ae8a9dfe0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -20,7 +20,45 @@ cd(dirname(@__FILE__)) do @everywhere include("testdefs.jl") - reduce(propagate_errors, nothing, pmap(runtests, tests; err_retry=false, err_stop=true)) + results=[] + max_worker_rss = parse(Int, get(ENV, "JULIA_TEST_MAXRSS_MB", "500")) + @sync begin + for p in workers() + @async begin + while length(tests) > 0 + test = shift!(tests) + local resp + try + resp = remotecall_fetch(p, t -> runtests(t), test) + catch e + resp = e + end + push!(results, (test, resp)) + + if (isa(resp, Integer) && (resp > max_worker_rss * 2^20)) || isa(resp, Exception) + if n > 1 + rmprocs(p, waitfor=0.5) + p = addprocs(1; exeflags=`--check-bounds=yes --depwarn=error`)[1] + remotecall_fetch(p, ()->include("testdefs.jl")) + else + # single process testing, bail if mem limit reached, or on an exception. + isa(resp, Exception) ? rethrow(resp) : error("Halting tests. memory limit reached : $(resp) > $(max_worker_rss * 2^20)") + end + end + end + end + end + end + + errors = filter(x->isa(x[2], Exception), results) + if length(errors) > 0 + for err in errors + println("Exception running test $(err[1]) :") + showerror(STDERR, err[2]) + println() + end + error("Some tests exited with errors.") + end if compile_test n > 1 && print("\tFrom worker 1:\t") diff --git a/test/testdefs.jl b/test/testdefs.jl index 944b86d16c781..0c9a7cb4f002b 100644 --- a/test/testdefs.jl +++ b/test/testdefs.jl @@ -5,18 +5,9 @@ using Base.Test function runtests(name) @printf(" \033[1m*\033[0m \033[31m%-21s\033[0m", name) tt = @elapsed include("$name.jl") - @printf(" in %6.2f seconds\n", tt) - nothing -end - -function propagate_errors(a,b) - if isa(a,Exception) - rethrow(a) - end - if isa(b,Exception) - rethrow(b) - end - nothing + rss = Sys.maxrss() + @printf(" in %6.2f seconds, maxrss %7.2f MB\n", tt, rss / 2^20) + rss end # looking in . messes things up badly From f44129f1f807cdf85632145dcf4f6b218faccd7f Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Thu, 15 Oct 2015 09:45:13 -0400 Subject: [PATCH 057/106] Fix compilation on Linux (and Possibly other *nix) (cherry picked from commit a0802b31c0902d0fc0025be7b983afe9efe7fb04) ref #13624 --- src/sys.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/sys.c b/src/sys.c index caa0462c0aab5..d59ae7c29d300 100644 --- a/src/sys.c +++ b/src/sys.c @@ -24,6 +24,13 @@ #include #include +#ifndef _OS_WINDOWS_ +// for getrusage +#include +#include +#include +#endif + #ifdef __APPLE__ #include #include From a384f8ef21b93abf2df90ad7be3b2e3e19c7018b Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Thu, 15 Oct 2015 12:23:30 +0530 Subject: [PATCH 058/106] limit maxrss check only to travis linux 64-bit (cherry picked from commit e958e8ee0cf07965957884ee6d3637156a270512) ref #13621 --- .travis.yml | 1 + test/runtests.jl | 13 +++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1388c63a907cc..34e40fce6d4de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,6 +37,7 @@ before_install: sudo apt-get install binutils:i386 -y; sudo apt-get install gcc:i386 g++:i386 make:i386 cpp:i386 g++-4.6:i386 gcc-4.6:i386 libssl-dev:i386 patchelf:i386 gfortran:i386 llvm-3.3-dev:i386 libsuitesparse-dev:i386 libopenblas-dev:i386 libopenblas-base:i386 libblas-dev:i386 liblapack-dev:i386 liblapack3:i386 libarpack2-dev:i386 libarpack2:i386 libfftw3-dev:i386 libgmp-dev:i386 libpcre3-dev:i386 libopenlibm-dev:i386 libmpfr-dev:i386 -y; else + export JULIA_TEST_MAXRSS_MB="500"; sudo apt-get install patchelf gfortran llvm-3.3-dev libsuitesparse-dev libopenblas-dev liblapack-dev libarpack2-dev libfftw3-dev libgmp-dev libpcre3-dev libopenlibm-dev libmpfr-dev -y; fi; elif [ `uname` = "Darwin" ]; then diff --git a/test/runtests.jl b/test/runtests.jl index e032ae8a9dfe0..14f32828987be 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -21,7 +21,12 @@ cd(dirname(@__FILE__)) do @everywhere include("testdefs.jl") results=[] - max_worker_rss = parse(Int, get(ENV, "JULIA_TEST_MAXRSS_MB", "500")) + if haskey(ENV, "JULIA_TEST_MAXRSS_MB") + max_worker_rss = parse(Int, ENV["JULIA_TEST_MAXRSS_MB"]) * 2^20 + else + max_worker_rss = typemax(Csize_t) + end + println(max_worker_rss) @sync begin for p in workers() @async begin @@ -35,14 +40,14 @@ cd(dirname(@__FILE__)) do end push!(results, (test, resp)) - if (isa(resp, Integer) && (resp > max_worker_rss * 2^20)) || isa(resp, Exception) + if (isa(resp, Integer) && (resp > max_worker_rss)) || isa(resp, Exception) if n > 1 rmprocs(p, waitfor=0.5) p = addprocs(1; exeflags=`--check-bounds=yes --depwarn=error`)[1] remotecall_fetch(p, ()->include("testdefs.jl")) else - # single process testing, bail if mem limit reached, or on an exception. - isa(resp, Exception) ? rethrow(resp) : error("Halting tests. memory limit reached : $(resp) > $(max_worker_rss * 2^20)") + # single process testing, bail if mem limit reached, or, on an exception. + isa(resp, Exception) ? rethrow(resp) : error("Halting tests. Memory limit reached : $resp > $max_worker_rss") end end end From 38d462589649b459fad3b50d799445f92523f76e Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Thu, 15 Oct 2015 20:25:38 +0530 Subject: [PATCH 059/106] Remove debug print Remove debug print left behind (cherry picked from commit ceffe2dfbfaaa9ad69499e99b7c1e3f6b1d19e52) ref #13628 --- test/runtests.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/test/runtests.jl b/test/runtests.jl index 14f32828987be..b4aae903a9a6a 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -26,7 +26,6 @@ cd(dirname(@__FILE__)) do else max_worker_rss = typemax(Csize_t) end - println(max_worker_rss) @sync begin for p in workers() @async begin From ac98b71e294a4a462fb4f9a85a138a9553c89d4a Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Fri, 20 Nov 2015 22:20:35 +0530 Subject: [PATCH 060/106] simplify channel imp and fix missed put!s (cherry picked from commit 312e65c8e60a4c58c92db7845dba8d397eeb00b6) ref #14072 --- base/channels.jl | 56 ++++++++----------------------------------- test/parallel_exec.jl | 37 +++++++++++----------------- 2 files changed, 24 insertions(+), 69 deletions(-) diff --git a/base/channels.jl b/base/channels.jl index a4ef643afae12..b7d071f1a37a5 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -2,27 +2,22 @@ abstract AbstractChannel +const DEF_CHANNEL_SZ=32 + type Channel{T} <: AbstractChannel cond_take::Condition # waiting for data to become available cond_put::Condition # waiting for a writeable slot state::Symbol data::Array{T,1} - szp1::Int # current channel size plus one sz_max::Int # maximum size of channel - take_pos::Int # read position - put_pos::Int # write position function Channel(sz) sz_max = sz == typemax(Int) ? typemax(Int) - 1 : sz - szp1 = sz > 32 ? 33 : sz+1 - new(Condition(), Condition(), :open, - Array(T, szp1), szp1, sz_max, 1, 1) + new(Condition(), Condition(), :open, Array(T, 0), sz_max) end end -const DEF_CHANNEL_SZ=32 - Channel(sz::Int = DEF_CHANNEL_SZ) = Channel{Any}(sz) closed_exception() = InvalidStateException("Channel is closed.", :closed) @@ -40,53 +35,28 @@ end function put!(c::Channel, v) !isopen(c) && throw(closed_exception()) - d = c.take_pos - c.put_pos - if (d == 1) || (d == -(c.szp1-1)) - # grow the channel if possible - if (c.szp1 - 1) < c.sz_max - if ((c.szp1-1) * 2) > c.sz_max - c.szp1 = c.sz_max + 1 - else - c.szp1 = ((c.szp1-1) * 2) + 1 - end - newdata = Array(eltype(c), c.szp1) - if c.put_pos > c.take_pos - copy!(newdata, 1, c.data, c.take_pos, (c.put_pos - c.take_pos)) - c.put_pos = c.put_pos - c.take_pos + 1 - else - len_first_part = length(c.data) - c.take_pos + 1 - copy!(newdata, 1, c.data, c.take_pos, len_first_part) - copy!(newdata, len_first_part+1, c.data, 1, c.put_pos-1) - c.put_pos = len_first_part + c.put_pos - end - c.take_pos = 1 - c.data = newdata - else - wait(c.cond_put) - end + while length(c.data) == c.sz_max + wait(c.cond_put) end - - c.data[c.put_pos] = v - c.put_pos = (c.put_pos == c.szp1 ? 1 : c.put_pos + 1) + push!(c.data, v) notify(c.cond_take, nothing, true, false) # notify all, since some of the waiters may be on a "fetch" call. v end function fetch(c::Channel) wait(c) - c.data[c.take_pos] + c.data[1] end function take!(c::Channel) !isopen(c) && !isready(c) && throw(closed_exception()) wait(c) - v = c.data[c.take_pos] - c.take_pos = (c.take_pos == c.szp1 ? 1 : c.take_pos + 1) + v = shift!(c.data) notify(c.cond_put, nothing, false, false) # notify only one, since only one slot has become available for a put!. v end -isready(c::Channel) = (c.take_pos == c.put_pos ? false : true) +isready(c::Channel) = n_avail(c) > 0 function wait(c::Channel) while !isready(c) @@ -102,13 +72,7 @@ end eltype{T}(::Type{Channel{T}}) = T -function n_avail(c::Channel) - if c.put_pos >= c.take_pos - return c.put_pos - c.take_pos - else - return c.szp1 - c.take_pos + c.put_pos - end -end +n_avail(c::Channel) = length(c.data) show(io::IO, c::Channel) = print(io, "$(typeof(c))(sz_max:$(c.sz_max),sz_curr:$(n_avail(c)))") diff --git a/test/parallel_exec.jl b/test/parallel_exec.jl index ac88d587c071b..f48ef394cca15 100644 --- a/test/parallel_exec.jl +++ b/test/parallel_exec.jl @@ -253,6 +253,20 @@ workloads = hist(@parallel((a,b)->[a;b], for i=1:7; myid(); end), nprocs())[2] @test isready(rr1) end +# Test multiple concurrent put!/take! on a channel +function testcpt() + c = Channel() + size = 0 + inc() = size += 1 + dec() = size -= 1 + @sync for i = 1:10^4 + @async (sleep(rand()); put!(c, i); inc()) + @async (sleep(rand()); take!(c); dec()) + end + @test size == 0 +end +testcpt() + @test_throws ArgumentError sleep(-1) @test_throws ArgumentError timedwait(()->false, 0.1, pollint=-0.5) @@ -314,29 +328,6 @@ test_channel(RemoteRef(()->Channel(10))) c=Channel{Int}(1) @test_throws MethodError put!(c, "Hello") -c=Channel(256) -# Test growth of channel -@test c.szp1 <= 33 -for x in 1:40 - put!(c, x) -end -@test c.szp1 <= 65 -for x in 1:39 - take!(c) -end -for x in 1:64 - put!(c, x) -end -@test (c.szp1 > 65) && (c.szp1 <= 129) -for x in 1:39 - take!(c) -end -@test fetch(c) == 39 -for x in 1:26 - take!(c) -end -@test isready(c) == false - # test channel iterations function test_iteration(in_c, out_c) t=@schedule for v in in_c From 735fcbfffab9fb3b39f3fafe4b59223cafba796b Mon Sep 17 00:00:00 2001 From: Xander Dunn Date: Sat, 21 Nov 2015 20:18:10 -0800 Subject: [PATCH 061/106] Fix manual typo (cherry picked from commit c391b3d3c9c80e916342673bafffde202baa7578) ref #14096 --- doc/manual/methods.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual/methods.rst b/doc/manual/methods.rst index ac7898ee55305..f4feff7692676 100644 --- a/doc/manual/methods.rst +++ b/doc/manual/methods.rst @@ -54,7 +54,7 @@ for structuring and organizing programs. .. [#] In C++ or Java, for example, in a method call like ``obj.meth(arg1,arg2)``, the object obj "receives" the method call and is - implicitly passed to the method via the ``this`` keyword, rather then as an + implicitly passed to the method via the ``this`` keyword, rather than as an explicit method argument. When the current ``this`` object is the receiver of a method call, it can be omitted altogether, writing just ``meth(arg1,arg2)``, with ``this`` implied as the receiving object. From a308e191629f7ab808372069cf588aa97ad69752 Mon Sep 17 00:00:00 2001 From: Xander Dunn Date: Sat, 21 Nov 2015 19:57:00 -0800 Subject: [PATCH 062/106] Fix manual typo (cherry picked from commit ee3ede18c5d877bd409bde96205872d31ed7dea4) ref #14095 --- doc/manual/types.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/manual/types.rst b/doc/manual/types.rst index e6640457f9094..2ac88624915b8 100644 --- a/doc/manual/types.rst +++ b/doc/manual/types.rst @@ -1299,7 +1299,7 @@ minimal interface designed to ensure that interactions with missing values are safe. At present, the interface consists of four possible interactions: - Construct a :obj:`Nullable` object. -- Check if an :obj:`Nullable` object has a missing value. +- Check if a :obj:`Nullable` object has a missing value. - Access the value of a :obj:`Nullable` object with a guarantee that a :exc:`NullException` will be thrown if the object's value is missing. - Access the value of a :obj:`Nullable` object with a guarantee that a default @@ -1340,8 +1340,8 @@ Note the core distinction between these two ways of constructing a :obj:`Nullabl object: in one style, you provide a type, ``T``, as a function parameter; in the other style, you provide a single value of type ``T`` as an argument. -Checking if an :obj:`Nullable` object has a value -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Checking if a :obj:`Nullable` object has a value +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You can check if a :obj:`Nullable` object has any value using :func:`isnull`: @@ -1353,10 +1353,10 @@ You can check if a :obj:`Nullable` object has any value using :func:`isnull`: julia> isnull(Nullable(0.0)) false -Safely accessing the value of an :obj:`Nullable` object -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Safely accessing the value of a :obj:`Nullable` object +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -You can safely access the value of an :obj:`Nullable` object using :func:`get`: +You can safely access the value of a :obj:`Nullable` object using :func:`get`: .. doctest:: From 13b6b3aa52ccdca19ae7fd23f88751c4e3adc387 Mon Sep 17 00:00:00 2001 From: "Dr. Zygmunt L. Szpak" Date: Sat, 21 Nov 2015 12:21:17 +1030 Subject: [PATCH 063/106] Add BoundsError tests for getindex The tests verify that calling getindex with an index that falls outside the allowed bounds indeed throws a BoundsError. (cherry picked from commit 7e9a81b94a1c32f1c7e564a92357e05dd3e71d26) ref #14079 --- test/numbers.jl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/numbers.jl b/test/numbers.jl index 425472e1ceb42..3e334fb0e9b72 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -2561,6 +2561,21 @@ for x in [1.23, 7, e, 4//5] #[FP, Int, Irrational, Rat] @test getindex(x) == x end +#getindex(x::Number,-1) throws BoundsError +#getindex(x::Number,0) throws BoundsError +#getindex(x::Number,2) throws BoundsError +#getindex(x::Array,-1) throws BoundsError +#getindex(x::Array,0 throws BoundsError +#getindex(x::Array,length(x::Array)+1) throws BoundsError +for x in [1.23, 7, e, 4//5] #[FP, Int, Irrational, Rat] + @test_throws BoundsError getindex(x,-1) + @test_throws BoundsError getindex(x,0) + @test_throws BoundsError getindex(x,2) + @test_throws BoundsError getindex([x x],-1) + @test_throws BoundsError getindex([x x],0) + @test_throws BoundsError getindex([x x],length([x,x])+1) +end + #copysign(x::Real, y::Real) = ifelse(signbit(x)!=signbit(y), -x, x) #same sign for x in [1.23, 7, e, 4//5] From 5e8effe7763e90b2007175dd21cc15d39fdac4ad Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sun, 22 Nov 2015 22:38:23 -0500 Subject: [PATCH 064/106] auto completion for true and false. Fix #14101 (cherry picked from commit a6698e662fe6d2551644f917cf7fc6563e0baf19) ref #14102 --- base/REPLCompletions.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/REPLCompletions.jl b/base/REPLCompletions.jl index 420424dba1b9b..fe09ce3ef5625 100644 --- a/base/REPLCompletions.jl +++ b/base/REPLCompletions.jl @@ -95,10 +95,10 @@ end function complete_keyword(s::ByteString) const sorted_keywords = [ "abstract", "baremodule", "begin", "bitstype", "break", "catch", "ccall", - "const", "continue", "do", "else", "elseif", "end", "export", "finally", - "for", "function", "global", "if", "immutable", "import", "importall", - "let", "local", "macro", "module", "quote", "return", "try", "type", - "typealias", "using", "while"] + "const", "continue", "do", "else", "elseif", "end", "export", "false", + "finally", "for", "function", "global", "if", "immutable", "import", + "importall", "let", "local", "macro", "module", "quote", "return", + "true", "try", "type", "typealias", "using", "while"] r = searchsorted(sorted_keywords, s) i = first(r) n = length(sorted_keywords) From 040435b3d5d45a3ac268f0f2f72b63c5aa838cf4 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Mon, 23 Nov 2015 00:17:41 -0500 Subject: [PATCH 065/106] Add tests for auto completions of true and false . (cherry picked from commit f4e5672a4a6e5dca894a1c4cb5d0c781d42b28a3) --- test/replcompletions.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/replcompletions.jl b/test/replcompletions.jl index a84c0097b2147..3c3a6fc5d8390 100644 --- a/test/replcompletions.jl +++ b/test/replcompletions.jl @@ -555,3 +555,11 @@ c,r = test_complete("cd(\"folder_do_not_exist_77/file") end rm(tmp) end + +# auto completions of true and false... issue #14101 +s = "tru" +c, r, res = test_complete(s) +@test "true" in c +s = "fals" +c, r, res = test_complete(s) +@test "false" in c From 89594489a893acd2bef54be9a305b67c019c200b Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Mon, 23 Nov 2015 14:30:40 -0500 Subject: [PATCH 066/106] Promote Float32 and Complex{Float32} elements to Float64 and Complex{Float64}. Fixes #14076 (cherry picked from commit eeb0b9952d67d69288d8fc2ae379f5a80b4e3436) ref #14108 --- base/sparse/cholmod.jl | 14 ++++++++------ test/sparsedir/cholmod.jl | 4 ++++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/base/sparse/cholmod.jl b/base/sparse/cholmod.jl index ec7e980a7ed49..fde43db12838b 100644 --- a/base/sparse/cholmod.jl +++ b/base/sparse/cholmod.jl @@ -853,7 +853,8 @@ function convert{Tv<:VTypes}(::Type{Sparse}, A::SparseMatrixCSC{Tv,SuiteSparse_l return o end -function convert{Tv<:VTypes}(::Type{Sparse}, A::SparseMatrixCSC{Tv,SuiteSparse_long}) + +function convert{Tv<:VTypes,Ti<:ITypes}(::Type{Sparse}, A::SparseMatrixCSC{Tv,Ti}) o = Sparse(A, 0) # check if array is symmetric and change stype if it is if ishermitian(o) @@ -861,13 +862,14 @@ function convert{Tv<:VTypes}(::Type{Sparse}, A::SparseMatrixCSC{Tv,SuiteSparse_l end o end - +convert{Ti<:ITypes}(::Type{Sparse}, A::SparseMatrixCSC{Float32,Ti}) = convert(Sparse, convert(SparseMatrixCSC{Float64,SuiteSparse_long}, A)) +convert{Ti<:ITypes}(::Type{Sparse}, A::SparseMatrixCSC{Complex{Float32},Ti}) = convert(Sparse, convert(SparseMatrixCSC{Complex{Float64},SuiteSparse_long}, A)) convert(::Type{Sparse}, A::Symmetric{Float64,SparseMatrixCSC{Float64,SuiteSparse_long}}) = Sparse(A.data, A.uplo == 'L' ? -1 : 1) convert{Tv<:VTypes}(::Type{Sparse}, A::Hermitian{Tv,SparseMatrixCSC{Tv,SuiteSparse_long}}) = Sparse(A.data, A.uplo == 'L' ? -1 : 1) -function convert{T}(::Type{Sparse}, - A::Union{SparseMatrixCSC{T,SuiteSparse_long}, - Symmetric{T,SparseMatrixCSC{T,SuiteSparse_long}}, - Hermitian{T,SparseMatrixCSC{T,SuiteSparse_long}}}, +function convert{T,Ti<:ITypes}(::Type{Sparse}, + A::Union{SparseMatrixCSC{T,Ti}, + Symmetric{T,SparseMatrixCSC{T,Ti}}, + Hermitian{T,SparseMatrixCSC{T,Ti}}}, args...) return Sparse(float(A), args...) end diff --git a/test/sparsedir/cholmod.jl b/test/sparsedir/cholmod.jl index 8026c0039bf9e..a5d53f8e3c19f 100644 --- a/test/sparsedir/cholmod.jl +++ b/test/sparsedir/cholmod.jl @@ -597,3 +597,7 @@ Base.writemime(IOBuffer(), MIME"text/plain"(), cholfact(sparse(Float64[ 10 1 1 1 # Element promotion and type inference @inferred cholfact(As)\ones(Int, size(As, 1)) @inferred ldltfact(As)\ones(Int, size(As, 1)) + +# Issue 14076 +@test cholfact(sparse([1,2,3,4], [1,2,3,4], Float32[1,4,16,64]))\[1,4,16,64] == ones(4) + From cc14a34c65214eed837e9bc51339540d32000cf5 Mon Sep 17 00:00:00 2001 From: Robin Deits Date: Tue, 24 Nov 2015 14:58:31 -0500 Subject: [PATCH 067/106] replace JULIA_CPU_ARCH with JULIA_CPU_TARGET in RPi docs The RaspberryPi docs recommend setting JULIA_CPU_ARCH, but that variable does not exist. It should be JULIA_CPU_TARGET instead Fixes #14116 (cherry picked from commit 0733151e59b1997d7d9e38495fdc86a0df71de43) ref #14120 --- README.arm.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.arm.md b/README.arm.md index 7bfddb132ae62..0c55d5ef0b091 100644 --- a/README.arm.md +++ b/README.arm.md @@ -50,7 +50,7 @@ If you run into issues building LLVM, see these notes: # Raspberry Pi The Raspberry Pi ARM CPU type is not detected by LLVM. -Before starting the build, it is recommended to do `export JULIA_CPU_ARCH=arm1176jzf-s` +Before starting the build, it is recommended to do `export JULIA_CPU_TARGET=arm1176jzf-s` at the shell to tune the generated code for your CPU architecture. # Raspberry Pi 2 From adf54faf126a97c7e67a3604e07eb9eb737090b1 Mon Sep 17 00:00:00 2001 From: Katie Hyatt Date: Tue, 24 Nov 2015 11:57:38 -0800 Subject: [PATCH 068/106] More tests for special functions (cherry picked from commit 669468b1151c2c66e1f7e6b7c188bf7390c6b11b) ref #14119 --- test/math.jl | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/test/math.jl b/test/math.jl index 9c53689e75ff5..f543fe584ef1b 100644 --- a/test/math.jl +++ b/test/math.jl @@ -232,6 +232,13 @@ end @test cospi(1) == -1 @test cospi(2) == 1 +@test sinc(1) == 0 +@test sinc(complex(1,0)) == 0 +@test sinc(0) == 1 +@test cosc(1) == -1 +@test cosc(0) == 0 +@test cosc(complex(1,0)) == -1 + # check type stability for T = (Float32,Float64,BigFloat) for f = (sind,cosd,sinpi,cospi) @@ -239,7 +246,6 @@ for T = (Float32,Float64,BigFloat) end end - # error functions @test_approx_eq erf(1) 0.84270079294971486934 @test_approx_eq erfc(1) 0.15729920705028513066 @@ -451,6 +457,8 @@ end for x in (3.2, 2+1im, 3//2, 3.2+0.1im) @test factorial(x) == gamma(1+x) end +@test lfact(1) == 0 +@test lfact(2) == lgamma(3) # digamma for elty in (Float32, Float64) @@ -495,14 +503,18 @@ for elty in (Float32, Float64) @test abs(invdigamma(digamma(convert(elty, val))) - convert(elty, val)) < 1e-8 end end +@test abs(invdigamma(2)) == abs(invdigamma(2.)) @test_approx_eq polygamma(20, 7.) -4.644616027240543262561198814998587152547 # eta, zeta @test_approx_eq eta(1) log(2) @test_approx_eq eta(2) pi^2/12 +@test_approx_eq eta(Float32(2)) eta(2) +@test_approx_eq eta(Complex64(2)) eta(2) @test_approx_eq zeta(0) -0.5 @test_approx_eq zeta(2) pi^2/6 +@test_approx_eq zeta(Complex64(2)) zeta(2) @test_approx_eq zeta(4) pi^4/90 @test_approx_eq zeta(one(Float32)) Float32(zeta(one(Float64))) @test isnan(zeta(NaN)) @@ -562,6 +574,9 @@ end @test polygamma(4, -0.0) == Inf == -polygamma(4, +0.0) @test zeta(4, +0.0) == Inf == zeta(4, -0.0) @test zeta(5, +0.0) == Inf == -zeta(5, -0.0) +@test zeta(Inf, 1.) == 1 +@test zeta(Inf, 2.) == 0 +@test isnan(zeta(NaN, 1.)) @test isa([digamma(x) for x in [1.0]], Vector{Float64}) @test isa([trigamma(x) for x in [1.0]], Vector{Float64}) @test isa([polygamma(3,x) for x in [1.0]], Vector{Float64}) From 95368ee47e1b4ef011f23027270156862e0b4ac0 Mon Sep 17 00:00:00 2001 From: Katie Hyatt Date: Wed, 25 Nov 2015 12:44:22 -0800 Subject: [PATCH 069/106] Added tests for BufferStream (cherry picked from commit 070e3c6f59c8bd3a39961812461082caf0a54970) ref #14144 --- test/iobuffer.jl | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/iobuffer.jl b/test/iobuffer.jl index 36add0105c485..3c18a2022f3ae 100644 --- a/test/iobuffer.jl +++ b/test/iobuffer.jl @@ -184,3 +184,21 @@ end let io = IOBuffer(0) write(io, ones(UInt8, 1048577)) end + +let bstream = BufferStream() + @test isopen(bstream) + @test isreadable(bstream) + @test iswritable(bstream) + @test sprint(io -> show(io,bstream)) == "BufferStream() bytes waiting:$(nb_available(bstream.buffer)), isopen:true" + a = rand(UInt8,10) + write(bstream,a) + flush(bstream) + b = read(bstream,UInt8) + @test a[1] == b + b = read(bstream,UInt8) + @test a[2] == b + c = zeros(UInt8,8) + read!(bstream,c) + @test c == a[3:10] + close(bstream) +end From 5603ced10e5c72eee39f4fb98291d7abe5122129 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 24 Nov 2015 13:39:24 -0800 Subject: [PATCH 070/106] fix bug in spawn test's usage of search searching for a substring returns a range, not a tuple, so these could never fail (cherry picked from commit 1080edb833f92f648f07ae45b57647d14c97ff90) ref #14123 --- test/spawn.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/spawn.jl b/test/spawn.jl index 5707e28a917f1..398198e83095f 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -23,8 +23,8 @@ yes = `perl -le 'while (1) {print STDOUT "y"}'` @test length(spawn(pipeline(`echo hello`, `sort`)).processes) == 2 out = readall(`echo hello` & `echo world`) -@test search(out,"world") != (0,0) -@test search(out,"hello") != (0,0) +@test search(out,"world") != 0:-1 +@test search(out,"hello") != 0:-1 @test readall(pipeline(`echo hello` & `echo world`, `sort`)) == "hello\nworld\n" @test (run(`printf " \033[34m[stdio passthrough ok]\033[0m\n"`); true) From 084a9adf534d5569f08273a5de41caaf543838bc Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Fri, 20 Nov 2015 18:28:57 +0100 Subject: [PATCH 071/106] Comment out assertion on elapsed time in pollfd test Increasing the interval in db6d74c was not enough to fix the random failures. (cherry picked from commit ed7ca93639aa51fa969079fc6e8cb9a1dc74d946) ref #14074 --- test/pollfd.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/pollfd.jl b/test/pollfd.jl index 2044663f7df2b..f7d50d6a40c9e 100644 --- a/test/pollfd.jl +++ b/test/pollfd.jl @@ -56,7 +56,8 @@ function pfd_tst_timeout(idx, intvl) @test !evt.writable t_elapsed = toq() - @unix_only @test (intvl <= t_elapsed) # TODO: enable this test on windows when the libuv version is bumped + # Disabled since this assertion fails randomly, notably on build VMs (issue #12824) + # @unix_only @test (intvl <= t_elapsed) # TODO: enable this test on windows when the libuv version is bumped @test (t_elapsed <= (intvl + 1)) end From 06c9fe39da094c5c80d534ae8abf1700734708f4 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Sat, 28 Nov 2015 14:33:14 -0800 Subject: [PATCH 072/106] Tests a few "global" Pkg functions (cherry picked from commit 807ba177fce264bf30b21d408552a96ab9aec3ce) ref #14179 --- test/pkg.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/pkg.jl b/test/pkg.jl index 1f97090568920..7473c4923342e 100644 --- a/test/pkg.jl +++ b/test/pkg.jl @@ -16,11 +16,14 @@ function temp_pkg_dir(fn::Function) end # Test basic operations: adding or removing a package, status, free -#Also test for the existence of REQUIRE and META_Branch +# Also test for the existence of REQUIRE and META_Branch temp_pkg_dir() do @test isfile(joinpath(Pkg.dir(),"REQUIRE")) @test isfile(joinpath(Pkg.dir(),"META_BRANCH")) @test isempty(Pkg.installed()) + @test sprint(io -> Pkg.status(io)) == "No packages installed\n" + @test !isempty(Pkg.available()) + Pkg.add("Example") @test [keys(Pkg.installed())...] == ["Example"] iob = IOBuffer() @@ -57,6 +60,7 @@ temp_pkg_dir() do Pkg.status("Example", iob) str = chomp(takebuf_string(iob)) @test endswith(str, string(Pkg.installed("Example"))) + @test isempty(Pkg.dependents("Example")) # adding a package with unsatisfiable julia version requirements (REPL.jl) errors try From 13a68a051e24f54b5680476531c973bad6720f41 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Sat, 21 Nov 2015 18:03:47 +0100 Subject: [PATCH 073/106] Fix findmax and findmin with iterables The state is not guaranteed to be equivalent to the index of the element. (cherry picked from commit bbaaf547292544f4d7a85d2d698ad4001b643952) ref #14086 --- base/abstractarray.jl | 3 --- base/array.jl | 32 ++++++++++++++++---------------- base/multidimensional.jl | 4 +--- test/arrayops.jl | 12 +++++++++++- 4 files changed, 28 insertions(+), 23 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index e78eb6108d40d..c2cb4189262de 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -408,9 +408,6 @@ start(A::AbstractArray) = (@_inline_meta(); itr = eachindex(A); (itr, start(itr) next(A::AbstractArray,i) = (@_inline_meta(); (idx, s) = next(i[1], i[2]); (A[idx], (i[1], s))) done(A::AbstractArray,i) = done(i[1], i[2]) -iterstate(i) = i -iterstate(i::Tuple{UnitRange{Int},Int}) = i[2] - # eachindex iterates over all indices. LinearSlow definitions are later. eachindex(A::AbstractArray) = (@_inline_meta(); eachindex(linearindexing(A), A)) diff --git a/base/array.jl b/base/array.jl index 4b0d387847cd3..308a9e5ad091b 100644 --- a/base/array.jl +++ b/base/array.jl @@ -830,36 +830,36 @@ function findmax(a) if isempty(a) throw(ArgumentError("collection must be non-empty")) end - i = start(a) - mi = i - m, i = next(a, i) - while !done(a, i) - iold = i - ai, i = next(a, i) + s = start(a) + mi = i = 1 + m, s = next(a, s) + while !done(a, s) + ai, s = next(a, s) + i += 1 if ai > m || m!=m m = ai - mi = iold + mi = i end end - return (m, iterstate(mi)) + return (m, mi) end function findmin(a) if isempty(a) throw(ArgumentError("collection must be non-empty")) end - i = start(a) - mi = i - m, i = next(a, i) - while !done(a, i) - iold = i - ai, i = next(a, i) + s = start(a) + mi = i = 1 + m, s = next(a, s) + while !done(a, s) + ai, s = next(a, s) + i += 1 if ai < m || m!=m m = ai - mi = iold + mi = i end end - return (m, iterstate(mi)) + return (m, mi) end indmax(a) = findmax(a)[2] diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 5ff800c1cd492..eadcfe991f1de 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -3,7 +3,7 @@ ### Multidimensional iterators module IteratorsMD -import Base: eltype, length, start, done, next, last, getindex, setindex!, linearindexing, min, max, eachindex, ndims, iterstate +import Base: eltype, length, start, done, next, last, getindex, setindex!, linearindexing, min, max, eachindex, ndims importall ..Base.Operators import Base: simd_outer_range, simd_inner_length, simd_index, @generated import Base: @nref, @ncall, @nif, @nexprs, LinearFast, LinearSlow, to_index @@ -59,8 +59,6 @@ immutable CartesianRange{I<:CartesianIndex} stop::I end -iterstate{CR<:CartesianRange,CI<:CartesianIndex}(i::Tuple{CR,CI}) = Base._sub2ind(i[1].stop.I, i[2].I) - @generated function CartesianRange{N}(I::CartesianIndex{N}) startargs = fill(1, N) :(CartesianRange($I($(startargs...)), I)) diff --git a/test/arrayops.jl b/test/arrayops.jl index 0c41c798795dc..db78e7b94b217 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -306,7 +306,7 @@ for i = 1:3 end @test isequal(a,findn(z)) -#argmin argmax +#findmin findmax indmin indmax @test indmax([10,12,9,11]) == 2 @test indmin([10,12,9,11]) == 3 @test findmin([NaN,3.2,1.8]) == (1.8,3) @@ -316,6 +316,16 @@ end @test findmin([3.2,1.8,NaN,2.0]) == (1.8,2) @test findmax([3.2,1.8,NaN,2.0]) == (3.2,1) +# #14085 +@test findmax(4:9) == (9,6) +@test indmax(4:9) == 6 +@test findmin(4:9) == (4,1) +@test indmin(4:9) == 1 +@test findmax(5:-2:1) == (5,1) +@test indmax(5:-2:1) == 1 +@test findmin(5:-2:1) == (1,3) +@test indmin(5:-2:1) == 3 + ## permutedims ## #keeps the num of dim From dcf67a1b9a104af7d07456538da90bd58aea833d Mon Sep 17 00:00:00 2001 From: Katie Hyatt Date: Wed, 25 Nov 2015 12:11:36 -0800 Subject: [PATCH 074/106] Few tests for iobuffer (cherry picked from commit 62d2118f57e9be598f153e109d777dc60352fa59) ref #14141 --- test/iobuffer.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/iobuffer.jl b/test/iobuffer.jl index 3c18a2022f3ae..991d244676e22 100644 --- a/test/iobuffer.jl +++ b/test/iobuffer.jl @@ -6,6 +6,9 @@ let io = IOBuffer() @test eof(io) @test_throws EOFError read(io,UInt8) @test write(io,"abc") == 3 +@test isreadable(io) +@test iswritable(io) +@test isopen(io) @test ioslength(io) == 3 @test position(io) == 3 @test eof(io) From b3dd88b73139fb957a01ee94c6af2c8d574f00e1 Mon Sep 17 00:00:00 2001 From: Katie Hyatt Date: Wed, 25 Nov 2015 12:11:57 -0800 Subject: [PATCH 075/106] Tests for irrationals (cherry picked from commit 6145982b83b4c21855378ed76d07b641e44cc662) --- test/math.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/math.jl b/test/math.jl index f543fe584ef1b..14adc4f9f658d 100644 --- a/test/math.jl +++ b/test/math.jl @@ -14,6 +14,16 @@ @test clamp([0, 1, 2, 3, 4], 1.0, 3.0) == [1.0, 1.0, 2.0, 3.0, 3.0] +@test !(pi == e) +@test !(e == 1//2) +@test 1//2 <= e +@test big(1//2) < e +@test e < big(20//6) +@test e^pi == exp(pi) +@test e^2 == exp(2) +@test e^2.4 == exp(2.4) +@test e^(2//3) == exp(2//3) + begin x = [0.0, 1.0, 2.0, 3.0, 4.0] clamp!(x, 1, 3) @@ -108,6 +118,7 @@ for T in (Float32, Float64) @test_approx_eq_eps expm1(T(1)) T(e)-1 10*eps(T) @test isequal(hypot(T(3),T(4)), T(5)) @test isequal(log(T(1)), T(0)) + @test isequal(log(e,T(1)), T(0)) @test_approx_eq_eps log(T(e)) T(1) eps(T) @test isequal(log10(T(1)), T(0)) @test isequal(log10(T(10)), T(1)) @@ -167,6 +178,7 @@ for T in (Float32, Float64) @test_throws DomainError log1p(convert(T,-2.0)) end @test_approx_eq exp10(5) exp10(5.0) +@test log(e) == 1 for T in (Int, Float64, BigFloat) @test_approx_eq deg2rad(T(180)) 1pi From 38be33e9c36a836917022f665a0d2bc74fe69546 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Wed, 25 Nov 2015 22:02:53 -0800 Subject: [PATCH 076/106] Quick fix for decompose(::BigFloat) on win64 TODO: add much more thorough tests for this (cherry picked from commit d5bbf4eb9d31feac7298446f0de87a135f58ea8d) --- base/hashing2.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/hashing2.jl b/base/hashing2.jl index c90639fde2332..2be68504399e5 100644 --- a/base/hashing2.jl +++ b/base/hashing2.jl @@ -135,8 +135,8 @@ function decompose(x::BigFloat) x == 0 && return big(0), 0, Int(x.sign) s = BigInt() ccall((:__gmpz_realloc2, :libgmp), Void, (Ptr{BigInt}, Culong), &s, x.prec) - s.size = -fld(-x.prec,(sizeof(Culong)<<3)) - ccall(:memcpy, Ptr{Void}, (Ptr{Void}, Ptr{Void}, Csize_t), s.d, x.d, s.size*sizeof(Culong)) + s.size = -fld(-x.prec,(sizeof(GMP.Limb)<<3)) + ccall(:memcpy, Ptr{Void}, (Ptr{Void}, Ptr{Void}, Csize_t), s.d, x.d, s.size*sizeof(GMP.Limb)) s, Int(x.exp - x.prec), Int(x.sign) end From 456f38d43367b47019483344b6f7bb5baeb1d393 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sun, 29 Nov 2015 12:20:05 -0500 Subject: [PATCH 077/106] fix #12941: remove shutdown syscall from uv_shutdown using slightly different libuv branch for release-0.4 --- .../libuv-9ab431a88fe255dd21e19a11f7fa2dd95774abf4.tar.gz/md5 | 1 + .../sha512 | 1 + .../libuv-b99045f254789f2407e4cd0d9163b421bfedfb3f.tar.gz/md5 | 1 - .../sha512 | 1 - deps/libuv.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 deps/checksums/libuv-9ab431a88fe255dd21e19a11f7fa2dd95774abf4.tar.gz/md5 create mode 100644 deps/checksums/libuv-9ab431a88fe255dd21e19a11f7fa2dd95774abf4.tar.gz/sha512 delete mode 100644 deps/checksums/libuv-b99045f254789f2407e4cd0d9163b421bfedfb3f.tar.gz/md5 delete mode 100644 deps/checksums/libuv-b99045f254789f2407e4cd0d9163b421bfedfb3f.tar.gz/sha512 diff --git a/deps/checksums/libuv-9ab431a88fe255dd21e19a11f7fa2dd95774abf4.tar.gz/md5 b/deps/checksums/libuv-9ab431a88fe255dd21e19a11f7fa2dd95774abf4.tar.gz/md5 new file mode 100644 index 0000000000000..65f8ed01d20e2 --- /dev/null +++ b/deps/checksums/libuv-9ab431a88fe255dd21e19a11f7fa2dd95774abf4.tar.gz/md5 @@ -0,0 +1 @@ +68b47fd2886292f14feb3a8de7446e1d diff --git a/deps/checksums/libuv-9ab431a88fe255dd21e19a11f7fa2dd95774abf4.tar.gz/sha512 b/deps/checksums/libuv-9ab431a88fe255dd21e19a11f7fa2dd95774abf4.tar.gz/sha512 new file mode 100644 index 0000000000000..5df5ca3746492 --- /dev/null +++ b/deps/checksums/libuv-9ab431a88fe255dd21e19a11f7fa2dd95774abf4.tar.gz/sha512 @@ -0,0 +1 @@ +27bb21f3a7a663623245d50b9def2e73bc8ee47f13a74fcd83693a57651814790b5e8e0667e00ef45bfb4d41bb80943f6e143eec4a503f6a9a099e3804999e76 diff --git a/deps/checksums/libuv-b99045f254789f2407e4cd0d9163b421bfedfb3f.tar.gz/md5 b/deps/checksums/libuv-b99045f254789f2407e4cd0d9163b421bfedfb3f.tar.gz/md5 deleted file mode 100644 index 18e53611c426f..0000000000000 --- a/deps/checksums/libuv-b99045f254789f2407e4cd0d9163b421bfedfb3f.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -2bf6a037e8998d9ed1081591ff9dc483 diff --git a/deps/checksums/libuv-b99045f254789f2407e4cd0d9163b421bfedfb3f.tar.gz/sha512 b/deps/checksums/libuv-b99045f254789f2407e4cd0d9163b421bfedfb3f.tar.gz/sha512 deleted file mode 100644 index 0adafbd4e1946..0000000000000 --- a/deps/checksums/libuv-b99045f254789f2407e4cd0d9163b421bfedfb3f.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -8646c2ffa3ff90a3edb6bbd8197fc2918225acb4cdf8c9c1029f1f9e56fa72e4bcbea9ce6a3ab387fbf8b3eabfaae7329b83f7e7b9f5e4afa04e0b3a82f0209c diff --git a/deps/libuv.version b/deps/libuv.version index c41aae1aa6da1..7cc090bad451d 100644 --- a/deps/libuv.version +++ b/deps/libuv.version @@ -1,2 +1,2 @@ LIBUV_BRANCH=julia0.4-uv0.11.26 -LIBUV_SHA1=b99045f254789f2407e4cd0d9163b421bfedfb3f +LIBUV_SHA1=9ab431a88fe255dd21e19a11f7fa2dd95774abf4 From bf4eeab288275058dce0658fd45f50e66371f029 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sun, 29 Nov 2015 15:04:05 -0800 Subject: [PATCH 078/106] Fix #13926 by also defining ENDCOLOR when VERBOSE=1 backport of 9be6d6b066d731c5b0f0f2dcd370f5c2db70028d --- Make.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Make.inc b/Make.inc index a8e3c9b40284d..da01e384fa68e 100644 --- a/Make.inc +++ b/Make.inc @@ -932,6 +932,7 @@ VERBOSE = 0 endif WARNCOLOR="\033[33;1m" +ENDCOLOR="\033[0m" ifeq ($(VERBOSE), 0) @@ -946,7 +947,6 @@ JULIACOLOR="\033[32;1m" SRCCOLOR="\033[33m" BINCOLOR="\033[37;1m" JULCOLOR="\033[34;1m" -ENDCOLOR="\033[0m" GOAL=$(subst ','\'',$(subst $(abspath $(JULIAHOME))/,,$(abspath $@))) From 8b3c67bc46a093ba50472ec527a677794a3481d0 Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Fri, 27 Nov 2015 16:49:18 +0530 Subject: [PATCH 079/106] fix error on exit for an invalid remote reference (backport of d546f9a95e12aef03db1d2ad4023c6e4634429e4) --- base/multi.jl | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/base/multi.jl b/base/multi.jl index b1acc583072cc..d19ede35d0ac2 100644 --- a/base/multi.jl +++ b/base/multi.jl @@ -559,11 +559,7 @@ end function send_del_client(rr::RemoteRef) if rr.where == myid() del_client(rr2id(rr), myid()) - else - if in(rr.where, map_del_wrkr) - # for a removed worker, don't bother - return - end + elseif rr.where in procs() # process only if a valid worker w = worker_from_id(rr.where) push!(w.del_msgs, (rr2id(rr), myid())) w.gcflag = true @@ -572,7 +568,6 @@ function send_del_client(rr::RemoteRef) end function add_client(id, client) - #println("$(myid()) adding client $client to $id") rv = lookup_ref(id) push!(rv.clientset, client) nothing @@ -587,12 +582,11 @@ end function send_add_client(rr::RemoteRef, i) if rr.where == myid() add_client(rr2id(rr), i) - elseif i != rr.where + elseif (i != rr.where) && (rr.where in procs()) # don't need to send add_client if the message is already going # to the processor that owns the remote ref. it will add_client # itself inside deserialize(). w = worker_from_id(rr.where) - #println("$(myid()) adding $((rr2id(rr), i)) for $(rr.where)") push!(w.add_msgs, (rr2id(rr), i)) w.gcflag = true notify(any_gc_flag) From 1085429aef0f1acff0021da1bac7234af822bad7 Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Sat, 28 Nov 2015 11:07:09 -0500 Subject: [PATCH 080/106] Don't show object in whos (cherry picked from commit 7436aa5d9d136b5ba501ecdae67304e5ede3691a) ref #14177 --- base/interactiveutil.jl | 2 -- test/misc.jl | 11 ++++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl index bee7db3be6ebf..ca835b461d34c 100644 --- a/base/interactiveutil.jl +++ b/base/interactiveutil.jl @@ -440,8 +440,6 @@ function whos(io::IO=STDOUT, m::Module=current_module(), pattern::Regex=r"") @printf(head, "%6d KB ", bytes ÷ (1024)) end print(head, summary(value)) - print(head, " : ") - show(head, value) catch e print(head, "#=ERROR: unable to show value=#") end diff --git a/test/misc.jl b/test/misc.jl index 67b9d42837d7e..80a84e703f420 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -181,7 +181,7 @@ x = 1.0 end @test sprint(whos, Main, r"^$") == "" let v = sprint(whos, _test_whos_) - @test contains(v, "x 8 bytes Float64 : 1.0") + @test contains(v, "x 8 bytes Float64") end # issue #13021 @@ -198,3 +198,12 @@ end @test Base.is_unix(:FreeBSD) @test_throws ArgumentError Base.is_unix(:BeOS) @unix_only @test Base.windows_version() == (0,0) + +# Issue 14173 +module Tmp14173 + export A + A = randn(2000, 2000) +end +whos(IOBuffer(), Tmp14173) # warm up +@test @allocated(whos(IOBuffer(), Tmp14173)) < 7000 + From 2cba7572f78ff001d17de5bace20d5364e872271 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Mon, 30 Nov 2015 14:51:29 -0800 Subject: [PATCH 081/106] initialize temp_dir to empty in Pkg.init fixes `UndefVarError: temp_dir not defined` if the initial call to `mkpath` fails (cherry picked from commit 2b3ee1f82bfd7ee7ac874dfc1e22827a6c285d5b) ref #14199 --- base/pkg/dir.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/pkg/dir.jl b/base/pkg/dir.jl index 0e253001fe96f..09bd1dfbd685e 100644 --- a/base/pkg/dir.jl +++ b/base/pkg/dir.jl @@ -43,7 +43,7 @@ function init(meta::AbstractString=DEFAULT_META, branch::AbstractString=META_BRA Git.set_remote_url(meta, dir=metadata_dir) return end - local temp_dir + local temp_dir = "" try mkpath(dir) temp_dir = mktempdir(dir) From 4d20f125618d099642bdba863ca7848072bc6306 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Wed, 18 Nov 2015 03:57:51 +0000 Subject: [PATCH 082/106] Adjust to LLVM 3.8 API changes (cherry picked from commit 4e6d5023c389ce00eb52d87c5e46913a9b4d3c79) ref #14034 and #14202 --- src/ccall.cpp | 9 +++++++-- src/cgutils.cpp | 4 ++-- src/codegen.cpp | 33 ++++++++++++++++++++------------- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/ccall.cpp b/src/ccall.cpp index 22015ff6f6a52..7a4a9867327aa 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -1414,8 +1414,13 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) if (needStackRestore) { stacksave = CallInst::Create(Intrinsic::getDeclaration(jl_Module, Intrinsic::stacksave)); - if (savespot) - instList.insertAfter((Instruction*)savespot, (Instruction*)stacksave); + if (savespot) { +#ifdef LLVM38 + instList.insertAfter(savespot->getIterator(), (Instruction*)stacksave); +#else + instList.insertAfter((Instruction*)savespot, (Instruction*)stacksave); +#endif + } else instList.push_front((Instruction*)stacksave); } diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 67bd851a2be81..ef2fd9912266d 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -190,7 +190,7 @@ class FunctionMover : public ValueMaterializer Function::arg_iterator DestI = NewF->arg_begin(); for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) { DestI->setName(I->getName()); // Copy the name over... - VMap[I] = DestI++; // Add mapping to VMap + VMap[&*I] = &*(DestI++); // Add mapping to VMap } #ifdef LLVM36 @@ -1201,7 +1201,7 @@ static Value *emit_bounds_check(Value *a, jl_value_t *ty, Value *i, Value *len, // --- loading and storing --- static AllocaInst *emit_static_alloca(Type *lty, jl_codectx_t *ctx) { - return new AllocaInst(lty, "", /*InsertBefore=*/ctx->gc.gcframe); + return new AllocaInst(lty, "", /*InsertBefore=*/&*ctx->gc.gcframe); } static Value *emit_reg2mem(Value *v, jl_codectx_t *ctx) { diff --git a/src/codegen.cpp b/src/codegen.cpp index 969a96fe2ac0b..8934ff70a68a2 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1006,7 +1006,7 @@ Function* CloneFunctionToModule(Function *F, Module *destModule) Function::arg_iterator DestI = NewF->arg_begin(); for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) { DestI->setName(I->getName()); // Copy the name over... - VMap[I] = DestI++; // Add mapping to VMap + VMap[&*I] = &*DestI++; // Add mapping to VMap } SmallVector Returns; @@ -1041,7 +1041,7 @@ const jl_value_t *jl_dump_function_ir(void *f, bool strip_ir_metadata, bool dump BasicBlock::InstListType::iterator f2_il = (*f2_bb).getInstList().begin(); // iterate over instructions in basic block for (; f2_il != (*f2_bb).getInstList().end(); ) { - Instruction *inst = f2_il++; + Instruction *inst = &*f2_il++; // remove dbg.declare and dbg.value calls if (isa(inst) || isa(inst)) { inst->eraseFromParent(); @@ -3069,7 +3069,7 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) !is_stable_expr(r, ctx)) { Instruction *newroot = cast(emit_local_slot(ctx->gc.argSpaceSize++, ctx)); newroot->removeFromParent(); // move it to the gc frame basic block so it can be reused as needed - newroot->insertAfter(ctx->gc.last_gcframe_inst); + newroot->insertAfter(&*ctx->gc.last_gcframe_inst); vi.memvalue = bp = newroot; vi.hasGCRoot = true; // this has been discovered to need a gc root, add it now //TODO: move this logic after the emit_expr @@ -3552,7 +3552,7 @@ static void finalize_gc_frame(jl_codectx_t *ctx) } BasicBlock::iterator bbi(gc->gcframe); AllocaInst *newgcframe = gc->gcframe; - builder.SetInsertPoint(++gc->last_gcframe_inst); // set insert *before* point, e.g. after the gcframe + builder.SetInsertPoint(&*++gc->last_gcframe_inst); // set insert *before* point, e.g. after the gcframe // Allocate the real GC frame // n_frames++; newgcframe->setOperand(0, ConstantInt::get(T_int32, 2 + gc->argSpaceSize + gc->maxDepth)); // fix up the size of the gc frame @@ -3690,7 +3690,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t Function::arg_iterator AI = cw->arg_begin(); Value *sretPtr = NULL; if (sret) - sretPtr = AI++; + sretPtr = &*AI++; Value *result; size_t FParamIndex = 0; @@ -3704,7 +3704,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t } for (size_t i = 0; i < nargs; i++) { - Value *val = AI++; + Value *val = &*AI++; jl_value_t *jargty = jl_nth_slot_type(lam->specTypes, i); // figure out how to unpack this type @@ -3876,7 +3876,7 @@ static Function *gen_jlcall_wrapper(jl_lambda_info_t *lam, jl_expr_t *ast, Funct addComdat(w); Function::arg_iterator AI = w->arg_begin(); /* const Argument &fArg = */ *AI++; - Value *argArray = AI++; + Value *argArray = &*AI++; /* const Argument &argCount = *AI++; */ BasicBlock *b0 = BasicBlock::Create(jl_LLVMContext, "top", w); @@ -4269,10 +4269,17 @@ static Function *emit_function(jl_lambda_info_t *lam) 0, // ScopeLine 0, // Flags true, // isOptimized - f); // Fn + #ifdef LLVM38 + nullptr); // Template Parameters + #else + f); // Function + #endif // set initial line number inlineLoc = DebugLoc::get(lno, 0, (MDNode*)SP, NULL); builder.SetCurrentDebugLocation(inlineLoc); + #ifdef LLVM38 + f->setSubprogram(SP); + #endif #ifndef LLVM37 assert(SP.Verify() && SP.describes(f) && SP.getFunction() == f); #endif @@ -4386,9 +4393,9 @@ static Function *emit_function(jl_lambda_info_t *lam) unsigned argIdx = 0; if (!specsig) { Function::arg_iterator AI = f->arg_begin(); - fArg = AI++; - argArray = AI++; - argCount = AI++; + fArg = &*AI++; + argArray = &*AI++; + argCount = &*AI++; ctx.argArray = argArray; ctx.argCount = argCount; @@ -4565,7 +4572,7 @@ static Function *emit_function(jl_lambda_info_t *lam) if (specsig) { argType = jl_nth_slot_type(lam->specTypes,i); if (!vi.isGhost) { - argPtr = AI++; + argPtr = &*AI++; argPtr = mark_julia_type(argPtr, argType); } } @@ -4792,7 +4799,7 @@ static Function *emit_function(jl_lambda_info_t *lam) mallocVisitLine(filename, lno); if (ctx.sret) - builder.CreateStore(retval, ctx.f->arg_begin()); + builder.CreateStore(retval, &*ctx.f->arg_begin()); if (type_is_ghost(retty) || ctx.sret) builder.CreateRetVoid(); else From 4c33ac6aa66f70c413d20d4ad005c6521bf36ac4 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 1 Dec 2015 00:14:55 -0500 Subject: [PATCH 083/106] Add an openblas patch to fix #14174 ref https://github.com/xianyi/OpenBLAS/issues/697 (cherry picked from commit cdb316c8f72f18ee6e6829792505ba3dd3136a07) ref #14203 --- deps/Makefile | 1 + deps/openblas-win64.patch | 75 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 deps/openblas-win64.patch diff --git a/deps/Makefile b/deps/Makefile index b7f301fa2af1e..bd3cfd175537c 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -1080,6 +1080,7 @@ OPENBLAS_BUILD_OPTS += NO_AVX2=1 endif $(OPENBLAS_SRC_DIR)/config.status: $(OPENBLAS_SRC_DIR)/Makefile + cd $(dir $@) && patch -p1 < ../openblas-win64.patch perl -i -ple 's/^\s*(EXTRALIB\s*\+=\s*-lSystemStubs)\s*$$/# $$1/g' $(OPENBLAS_SRC_DIR)/Makefile.system touch $@ $(OPENBLAS_OBJ_SOURCE): $(OPENBLAS_SRC_DIR)/config.status diff --git a/deps/openblas-win64.patch b/deps/openblas-win64.patch new file mode 100644 index 0000000000000..a93e874499f7c --- /dev/null +++ b/deps/openblas-win64.patch @@ -0,0 +1,75 @@ +commit 640cccc2b159dba6d99b9eea11b7f23f98d6c85d +Author: Zhang Xianyi +Date: Mon Nov 30 15:19:45 2015 -0600 + + Refs #697. Fixed gemv bug for Windows. + + Thank matzeri's patch. + +diff --git a/interface/gemv.c b/interface/gemv.c +index 0a222a6..97c68bf 100644 +--- a/interface/gemv.c ++++ b/interface/gemv.c +@@ -37,6 +37,7 @@ + /*********************************************************************/ + + #include ++#include + #include "common.h" + #include "l1param.h" + #ifdef FUNCTION_PROFILE +@@ -224,13 +225,17 @@ void CNAME(enum CBLAS_ORDER order, + #ifdef ALIGNED_ACCESS + stack_alloc_size += 3; + #endif +- if(stack_alloc_size < 128) ++// if(stack_alloc_size < 128) + //dgemv_n.S require a 128 bytes buffer +- stack_alloc_size = 128; ++// increasing instead of capping 128 ++// ABI STACK for windows 288 bytes ++ stack_alloc_size += 288 / sizeof(FLOAT) ; + + if(stack_alloc_size > MAX_STACK_ALLOC / sizeof(FLOAT)) + stack_alloc_size = 0; + ++// stack overflow check ++ volatile double stack_check = 3.14159265358979323846; + FLOAT stack_buffer[stack_alloc_size]; + buffer = stack_alloc_size ? stack_buffer : (FLOAT *)blas_memory_alloc(1); + // printf("stack_alloc_size=%d\n", stack_alloc_size); +@@ -265,6 +270,8 @@ void CNAME(enum CBLAS_ORDER order, + + } + #endif ++// stack overflow check ++assert(stack_check==3.14159265358979323846); + + #ifdef MAX_STACK_ALLOC + if(!stack_alloc_size){ +diff --git a/exports/Makefile b/exports/Makefile +index 177e975..29a9ca8 100644 +--- a/exports/Makefile ++++ b/exports/Makefile +@@ -96,9 +96,9 @@ libgoto_hpl.def : gensymbol + ifeq (, $(SYMBOLPREFIX)$(SYMBOLSUFFIX)) + $(LIBDYNNAME) : ../$(LIBNAME) osx.def + else +-../$(LIBNAME).renamed : ../$(LIBNAME) objconv.def +- $(OBJCONV) @objconv.def ../$(LIBNAME) ../$(LIBNAME).renamed +-$(LIBDYNNAME) : ../$(LIBNAME).renamed osx.def ++../$(LIBNAME).osx.renamed : ../$(LIBNAME) objconv.def ++ $(OBJCONV) @objconv.def ../$(LIBNAME) ../$(LIBNAME).osx.renamed ++$(LIBDYNNAME) : ../$(LIBNAME).osx.renamed osx.def + endif + ifeq ($(NOFORTRAN), $(filter $(NOFORTRAN),1 2)) + #only build without Fortran +@@ -220,7 +220,7 @@ linktest.c : gensymbol ../Makefile.system ../getarch.c + perl ./gensymbol linktest $(ARCH) $(BU) $(EXPRECISION) $(NO_CBLAS) $(NO_LAPACK) $(NO_LAPACKE) $(NEED2UNDERSCORES) $(ONLY_CBLAS) "$(SYMBOLPREFIX)" "$(SYMBOLSUFFIX)" > linktest.c + + clean :: +- @rm -f *.def *.dylib __.SYMDEF* ++ @rm -f *.def *.dylib __.SYMDEF* *.renamed + + include ../Makefile.tail + From 7c7c66f5f050aa1a741740f15565cae6f5df2c94 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 1 Dec 2015 02:44:07 -0800 Subject: [PATCH 084/106] Revert "Use promote_op in broadcasting and matrix multiplication" This reverts commit e1a37492ff1053b114f8cb1fc2d135d25e3669a1. This change causes failures in NullableArrays, SALSA, and possibly elsewhere. Backporting can potentially be reconsidered in the future once more authors have fixed their code for 0.5-dev. --- base/abstractarray.jl | 9 --------- base/bool.jl | 2 -- base/broadcast.jl | 34 ++++++++++++++++++++++----------- base/complex.jl | 7 ------- base/functors.jl | 4 ---- base/int.jl | 2 -- base/linalg.jl | 1 - base/linalg/matmul.jl | 38 ++++++++++++++++++------------------- base/promotion.jl | 3 --- base/sparse/sparsematrix.jl | 2 +- test/arrayops.jl | 8 ++------ 11 files changed, 45 insertions(+), 65 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index c2cb4189262de..5ca8f10fe44fe 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1270,15 +1270,6 @@ function map_promote(f, A::AbstractArray) return promote_to!(f, 2, dest, A) end -# These are needed because map(eltype, As) is not inferrable -promote_eltype_op(::Any) = Bottom -promote_eltype_op{T}(op, ::AbstractArray{T}) = promote_op(op, T) -promote_eltype_op{T}(op, ::T ) = promote_op(op, T) -promote_eltype_op{R,S}(op, ::AbstractArray{R}, ::AbstractArray{S}) = promote_op(op, R, S) -promote_eltype_op{R,S}(op, ::AbstractArray{R}, ::S) = promote_op(op, R, S) -promote_eltype_op{R,S}(op, ::R, ::AbstractArray{S}) = promote_op(op, R, S) -promote_eltype_op(op, A, B, C, D...) = promote_op(op, eltype(A), promote_eltype_op(op, B, C, D...)) - ## 1 argument map!{F}(f::F, A::AbstractArray) = map!(f, A, A) function map!{F}(f::F, dest::AbstractArray, A::AbstractArray) diff --git a/base/bool.jl b/base/bool.jl index 915d67a97bb3f..95df1e3494cb3 100644 --- a/base/bool.jl +++ b/base/bool.jl @@ -59,5 +59,3 @@ fld(x::Bool, y::Bool) = div(x,y) cld(x::Bool, y::Bool) = div(x,y) rem(x::Bool, y::Bool) = y ? false : throw(DivideError()) mod(x::Bool, y::Bool) = rem(x,y) - -promote_op(op, ::Type{Bool}, ::Type{Bool}) = typeof(op(true, true)) diff --git a/base/broadcast.jl b/base/broadcast.jl index efb0eb1173c5b..c590f6a38b149 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -3,8 +3,9 @@ module Broadcast using ..Cartesian -using Base: promote_op, promote_eltype, promote_eltype_op, @get!, _msk_end, unsafe_bitgetindex -using Base: AddFun, SubFun, MulFun, LDivFun, RDivFun, PowFun +import Base.promote_eltype +import Base.@get! +import Base.num_bit_chunks, Base._msk_end, Base.unsafe_bitgetindex import Base: .+, .-, .*, ./, .\, .//, .==, .<, .!=, .<=, .%, .<<, .>>, .^ export broadcast, broadcast!, broadcast_function, broadcast!_function, bitbroadcast export broadcast_getindex, broadcast_setindex! @@ -249,7 +250,7 @@ for (Bsig, Asig, gbf, gbb) in end -broadcast(f, As...) = broadcast!(f, Array(promote_eltype_op(f, As...), broadcast_shape(As...)), As...) +broadcast(f, As...) = broadcast!(f, Array(promote_eltype(As...), broadcast_shape(As...)), As...) bitbroadcast(f, As...) = broadcast!(f, BitArray(broadcast_shape(As...)), As...) @@ -303,28 +304,35 @@ end ## elementwise operators ## +.*(As::AbstractArray...) = broadcast(*, As...) .%(A::AbstractArray, B::AbstractArray) = broadcast(%, A, B) .<<(A::AbstractArray, B::AbstractArray) = broadcast(<<, A, B) .>>(A::AbstractArray, B::AbstractArray) = broadcast(>>, A, B) -eltype_plus(As::AbstractArray...) = promote_eltype_op(AddFun(), As...) +eltype_plus(As::AbstractArray...) = promote_eltype(As...) +eltype_plus(As::AbstractArray{Bool}...) = typeof(true+true) .+(As::AbstractArray...) = broadcast!(+, Array(eltype_plus(As...), broadcast_shape(As...)), As...) +type_minus(T, S) = promote_type(T, S) +type_minus(::Type{Bool}, ::Type{Bool}) = typeof(true-true) + function .-(A::AbstractArray, B::AbstractArray) - broadcast!(-, Array(promote_op(SubFun(), eltype(A), eltype(B)), broadcast_shape(A,B)), A, B) + broadcast!(-, Array(type_minus(eltype(A), eltype(B)), broadcast_shape(A,B)), A, B) end -eltype_mul(As::AbstractArray...) = promote_eltype_op(MulFun(), As...) - -.*(As::AbstractArray...) = broadcast!(*, Array(eltype_mul(As...), broadcast_shape(As...)), As...) +type_div(T,S) = promote_type(T,S) +type_div{T<:Integer,S<:Integer}(::Type{T},::Type{S}) = typeof(one(T)/one(S)) +type_div{T,S}(::Type{Complex{T}},::Type{Complex{S}}) = Complex{type_div(T,S)} +type_div{T,S}(::Type{Complex{T}},::Type{S}) = Complex{type_div(T,S)} +type_div{T,S}(::Type{T},::Type{Complex{S}}) = Complex{type_div(T,S)} function ./(A::AbstractArray, B::AbstractArray) - broadcast!(/, Array(promote_op(RDivFun(), eltype(A), eltype(B)), broadcast_shape(A, B)), A, B) + broadcast!(/, Array(type_div(eltype(A), eltype(B)), broadcast_shape(A, B)), A, B) end function .\(A::AbstractArray, B::AbstractArray) - broadcast!(\, Array(promote_op(LDivFun(), eltype(A), eltype(B)), broadcast_shape(A, B)), A, B) + broadcast!(\, Array(type_div(eltype(A), eltype(B)), broadcast_shape(A, B)), A, B) end typealias RatIntT{T<:Integer} Union{Type{Rational{T}},Type{T}} @@ -337,8 +345,12 @@ function .//(A::AbstractArray, B::AbstractArray) broadcast!(//, Array(type_rdiv(eltype(A), eltype(B)), broadcast_shape(A, B)), A, B) end +type_pow(T,S) = promote_type(T,S) +type_pow{S<:Integer}(::Type{Bool},::Type{S}) = Bool +type_pow{S}(T,::Type{Rational{S}}) = type_pow(T, type_div(S, S)) + function .^(A::AbstractArray, B::AbstractArray) - broadcast!(^, Array(promote_op(PowFun(), eltype(A), eltype(B)), broadcast_shape(A, B)), A, B) + broadcast!(^, Array(type_pow(eltype(A), eltype(B)), broadcast_shape(A, B)), A, B) end ## element-wise comparison operators returning BitArray ## diff --git a/base/complex.jl b/base/complex.jl index 88151b0ace75b..99cc4d2cd29fd 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -26,13 +26,6 @@ promote_rule{T<:Real,S<:Real}(::Type{Complex{T}}, ::Type{S}) = promote_rule{T<:Real,S<:Real}(::Type{Complex{T}}, ::Type{Complex{S}}) = Complex{promote_type(T,S)} -promote_op{T<:Real,S<:Real}(op, ::Type{Complex{T}}, ::Type{Complex{S}}) = - Complex{promote_op(op,T,S)} -promote_op{T<:Real,S<:Real}(op, ::Type{Complex{T}}, ::Type{S}) = - Complex{promote_op(op,T,S)} -promote_op{T<:Real,S<:Real}(op, ::Type{T}, ::Type{Complex{S}}) = - Complex{promote_op(op,T,S)} - widen{T}(::Type{Complex{T}}) = Complex{widen(T)} real(z::Complex) = z.re diff --git a/base/functors.jl b/base/functors.jl index ba8aa4e354344..613698192b7ba 100644 --- a/base/functors.jl +++ b/base/functors.jl @@ -120,10 +120,6 @@ EqX{T}(x::T) = EqX{T}(x) call(f::EqX, y) = f.x == y -# More promote_op rules - -promote_op{T<:Integer}(::PowFun, ::Type{Bool}, ::Type{T}) = Bool - #### Bitwise operators #### # BitFunctors are functions that behave in the same bit-wise manner when applied diff --git a/base/int.jl b/base/int.jl index 0ca47800f043c..2ace89965c3dd 100644 --- a/base/int.jl +++ b/base/int.jl @@ -340,8 +340,6 @@ promote_rule(::Type{UInt128}, ::Type{Int32} ) = UInt128 promote_rule(::Type{UInt128}, ::Type{Int64} ) = UInt128 promote_rule(::Type{UInt128}, ::Type{Int128}) = UInt128 -promote_op{R<:Integer,S<:Integer}(op, ::Type{R}, ::Type{S}) = typeof(op(one(R), one(S))) - ## traits ## typemin(::Type{Int8 }) = Int8(-128) diff --git a/base/linalg.jl b/base/linalg.jl index 27227a221f8b1..5947cd6d59d6f 100644 --- a/base/linalg.jl +++ b/base/linalg.jl @@ -7,7 +7,6 @@ importall ..Base.Operators import Base: USE_BLAS64, size, copy, copy_transpose!, power_by_squaring, print_matrix, transpose!, unsafe_getindex, unsafe_setindex!, isapprox -using Base: promote_op, MulFun export # Modules diff --git a/base/linalg/matmul.jl b/base/linalg/matmul.jl index 816170429b88f..2066ff3603efe 100644 --- a/base/linalg/matmul.jl +++ b/base/linalg/matmul.jl @@ -38,8 +38,8 @@ function scale!(C::AbstractMatrix, b::AbstractVector, A::AbstractMatrix) end C end -scale(A::Matrix, b::Vector) = scale!(similar(A, promote_op(MulFun(),eltype(A),eltype(b))), A, b) -scale(b::Vector, A::Matrix) = scale!(similar(b, promote_op(MulFun(),eltype(b),eltype(A)), size(A)), b, A) +scale(A::Matrix, b::Vector) = scale!(similar(A, promote_type(eltype(A),eltype(b))), A, b) +scale(b::Vector, A::Matrix) = scale!(similar(b, promote_type(eltype(A),eltype(b)), size(A)), b, A) # Dot products @@ -78,11 +78,11 @@ At_mul_B{T<:BlasComplex}(x::StridedVector{T}, y::StridedVector{T}) = [BLAS.dotu( # Matrix-vector multiplication function (*){T<:BlasFloat,S}(A::StridedMatrix{T}, x::StridedVector{S}) - TS = promote_op(MulFun(),arithtype(T),arithtype(S)) + TS = promote_type(arithtype(T),arithtype(S)) A_mul_B!(similar(x, TS, size(A,1)), A, convert(AbstractVector{TS}, x)) end function (*){T,S}(A::AbstractMatrix{T}, x::AbstractVector{S}) - TS = promote_op(MulFun(),arithtype(T),arithtype(S)) + TS = promote_type(arithtype(T),arithtype(S)) A_mul_B!(similar(x,TS,size(A,1)),A,x) end (*)(A::AbstractVector, B::AbstractMatrix) = reshape(A,length(A),1)*B @@ -101,22 +101,22 @@ end A_mul_B!(y::StridedVector, A::StridedVecOrMat, x::StridedVector) = generic_matvecmul!(y, 'N', A, x) function At_mul_B{T<:BlasFloat,S}(A::StridedMatrix{T}, x::StridedVector{S}) - TS = promote_op(MulFun(),arithtype(T),arithtype(S)) + TS = promote_type(arithtype(T),arithtype(S)) At_mul_B!(similar(x,TS,size(A,2)), A, convert(AbstractVector{TS}, x)) end function At_mul_B{T,S}(A::StridedMatrix{T}, x::StridedVector{S}) - TS = promote_op(MulFun(),arithtype(T),arithtype(S)) + TS = promote_type(arithtype(T),arithtype(S)) At_mul_B!(similar(x,TS,size(A,2)), A, x) end At_mul_B!{T<:BlasFloat}(y::StridedVector{T}, A::StridedVecOrMat{T}, x::StridedVector{T}) = gemv!(y, 'T', A, x) At_mul_B!(y::StridedVector, A::StridedVecOrMat, x::StridedVector) = generic_matvecmul!(y, 'T', A, x) function Ac_mul_B{T<:BlasFloat,S}(A::StridedMatrix{T}, x::StridedVector{S}) - TS = promote_op(MulFun(),arithtype(T),arithtype(S)) + TS = promote_type(arithtype(T),arithtype(S)) Ac_mul_B!(similar(x,TS,size(A,2)),A,convert(AbstractVector{TS},x)) end function Ac_mul_B{T,S}(A::StridedMatrix{T}, x::StridedVector{S}) - TS = promote_op(MulFun(),arithtype(T),arithtype(S)) + TS = promote_type(arithtype(T),arithtype(S)) Ac_mul_B!(similar(x,TS,size(A,2)), A, x) end @@ -127,7 +127,7 @@ Ac_mul_B!(y::StridedVector, A::StridedVecOrMat, x::StridedVector) = generic_matv # Matrix-matrix multiplication function (*){T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) - TS = promote_op(MulFun(), arithtype(T), arithtype(S)) + TS = promote_type(arithtype(T), arithtype(S)) A_mul_B!(similar(B, TS, (size(A,1), size(B,2))), A, B) end A_mul_B!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = gemm_wrapper!(C, 'N', 'N', A, B) @@ -144,14 +144,14 @@ end A_mul_B!(C::StridedMatrix, A::StridedVecOrMat, B::StridedVecOrMat) = generic_matmatmul!(C, 'N', 'N', A, B) function At_mul_B{T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) - TS = promote_op(MulFun(),arithtype(T), arithtype(S)) + TS = promote_type(arithtype(T), arithtype(S)) At_mul_B!(similar(B, TS, (size(A,2), size(B,2))), A, B) end At_mul_B!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = is(A,B) ? syrk_wrapper!(C, 'T', A) : gemm_wrapper!(C, 'T', 'N', A, B) At_mul_B!(C::StridedMatrix, A::StridedVecOrMat, B::StridedVecOrMat) = generic_matmatmul!(C, 'T', 'N', A, B) function A_mul_Bt{T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) - TS = promote_op(MulFun(),arithtype(T), arithtype(S)) + TS = promote_type(arithtype(T), arithtype(S)) A_mul_Bt!(similar(B, TS, (size(A,1), size(B,1))), A, B) end A_mul_Bt!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = is(A,B) ? syrk_wrapper!(C, 'N', A) : gemm_wrapper!(C, 'N', 'T', A, B) @@ -168,7 +168,7 @@ end A_mul_Bt!(C::StridedVecOrMat, A::StridedVecOrMat, B::StridedVecOrMat) = generic_matmatmul!(C, 'N', 'T', A, B) function At_mul_Bt{T,S}(A::AbstractMatrix{T}, B::StridedVecOrMat{S}) - TS = promote_op(MulFun(),arithtype(T), arithtype(S)) + TS = promote_type(arithtype(T), arithtype(S)) At_mul_Bt!(similar(B, TS, (size(A,2), size(B,1))), A, B) end At_mul_Bt!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = gemm_wrapper!(C, 'T', 'T', A, B) @@ -177,7 +177,7 @@ At_mul_Bt!(C::StridedMatrix, A::StridedVecOrMat, B::StridedVecOrMat) = generic_m Ac_mul_B{T<:BlasReal}(A::StridedMatrix{T}, B::StridedMatrix{T}) = At_mul_B(A, B) Ac_mul_B!{T<:BlasReal}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = At_mul_B!(C, A, B) function Ac_mul_B{T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) - TS = promote_op(MulFun(),arithtype(T), arithtype(S)) + TS = promote_type(arithtype(T), arithtype(S)) Ac_mul_B!(similar(B, TS, (size(A,2), size(B,2))), A, B) end Ac_mul_B!{T<:BlasComplex}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = is(A,B) ? herk_wrapper!(C,'C',A) : gemm_wrapper!(C,'C', 'N', A, B) @@ -186,16 +186,16 @@ Ac_mul_B!(C::StridedMatrix, A::StridedVecOrMat, B::StridedVecOrMat) = generic_ma A_mul_Bc{T<:BlasFloat,S<:BlasReal}(A::StridedMatrix{T}, B::StridedMatrix{S}) = A_mul_Bt(A, B) A_mul_Bc!{T<:BlasFloat,S<:BlasReal}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{S}) = A_mul_Bt!(C, A, B) function A_mul_Bc{T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) - TS = promote_op(MulFun(),arithtype(T),arithtype(S)) + TS = promote_type(arithtype(T),arithtype(S)) A_mul_Bc!(similar(B,TS,(size(A,1),size(B,1))),A,B) end A_mul_Bc!{T<:BlasComplex}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = is(A,B) ? herk_wrapper!(C, 'N', A) : gemm_wrapper!(C, 'N', 'C', A, B) A_mul_Bc!(C::StridedMatrix, A::StridedVecOrMat, B::StridedVecOrMat) = generic_matmatmul!(C, 'N', 'C', A, B) -Ac_mul_Bc{T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) = Ac_mul_Bc!(similar(B, promote_op(MulFun(),arithtype(T), arithtype(S)), (size(A,2), size(B,1))), A, B) +Ac_mul_Bc{T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) = Ac_mul_Bc!(similar(B, promote_type(arithtype(T), arithtype(S)), (size(A,2), size(B,1))), A, B) Ac_mul_Bc!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = gemm_wrapper!(C, 'C', 'C', A, B) Ac_mul_Bc!(C::StridedMatrix, A::StridedVecOrMat, B::StridedVecOrMat) = generic_matmatmul!(C, 'C', 'C', A, B) -Ac_mul_Bt{T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) = Ac_mul_Bt(similar(B, promote_op(MulFun(),arithtype(A), arithtype(B)), (size(A,2), size(B,1))), A, B) +Ac_mul_Bt{T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) = Ac_mul_Bt(similar(B, promote_type(arithtype(A), arithtype(B)), (size(A,2), size(B,1))), A, B) Ac_mul_Bt!(C::StridedMatrix, A::StridedVecOrMat, B::StridedVecOrMat) = generic_matmatmul!(C, 'C', 'T', A, B) # Supporting functions for matrix multiplication @@ -420,7 +420,7 @@ end function generic_matmatmul{T,S}(tA, tB, A::AbstractVecOrMat{T}, B::AbstractMatrix{S}) mA, nA = lapack_size(tA, A) mB, nB = lapack_size(tB, B) - C = similar(B, promote_op(MulFun(),arithtype(T),arithtype(S)), mA, nB) + C = similar(B, promote_type(arithtype(T),arithtype(S)), mA, nB) generic_matmatmul!(C, tA, tB, A, B) end @@ -625,7 +625,7 @@ end # multiply 2x2 matrices function matmul2x2{T,S}(tA, tB, A::AbstractMatrix{T}, B::AbstractMatrix{S}) - matmul2x2!(similar(B, promote_op(MulFun(),T,S), 2, 2), tA, tB, A, B) + matmul2x2!(similar(B, promote_type(T,S), 2, 2), tA, tB, A, B) end function matmul2x2!{T,S,R}(C::AbstractMatrix{R}, tA, tB, A::AbstractMatrix{T}, B::AbstractMatrix{S}) @@ -654,7 +654,7 @@ end # Multiply 3x3 matrices function matmul3x3{T,S}(tA, tB, A::AbstractMatrix{T}, B::AbstractMatrix{S}) - matmul3x3!(similar(B, promote_op(MulFun(),T,S), 3, 3), tA, tB, A, B) + matmul3x3!(similar(B, promote_type(T,S), 3, 3), tA, tB, A, B) end function matmul3x3!{T,S,R}(C::AbstractMatrix{R}, tA, tB, A::AbstractMatrix{T}, B::AbstractMatrix{S}) diff --git a/base/promotion.jl b/base/promotion.jl index f9a38a0f86c75..63e3b9a3d7606 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -203,10 +203,7 @@ checked_mul(x::Integer, y::Integer) = checked_mul(promote(x,y)...) # as needed. For example, if you need to provide a custom result type # for the multiplication of two types, # promote_op{R<:MyType,S<:MyType}(::MulFun, ::Type{R}, ::Type{S}) = MyType{multype(R,S)} -promote_op(::Any) = Bottom -promote_op(::Any, T) = T promote_op{R,S}(::Any, ::Type{R}, ::Type{S}) = promote_type(R, S) -promote_op(op, T, S, U, V...) = promote_op(op, T, promote_op(op, S, U, V...)) ## catch-alls to prevent infinite recursion when definitions are missing ## diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index 37291f1061541..ec0f8f4c1aa71 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -1023,7 +1023,7 @@ end # macro (.-)(A::Number, B::SparseMatrixCSC) = A .- full(B) ( -)(A::Array , B::SparseMatrixCSC) = A - full(B) -(.*)(A::AbstractArray, B::AbstractArray) = broadcast_zpreserving(Base.MulFun(), A, B) +(.*)(A::AbstractArray, B::AbstractArray) = broadcast_zpreserving(*, A, B) (.*)(A::SparseMatrixCSC, B::Number) = SparseMatrixCSC(A.m, A.n, copy(A.colptr), copy(A.rowval), A.nzval .* B) (.*)(A::Number, B::SparseMatrixCSC) = SparseMatrixCSC(B.m, B.n, copy(B.colptr), copy(B.rowval), A .* B.nzval) diff --git a/test/arrayops.jl b/test/arrayops.jl index db78e7b94b217..16b5f882709b1 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -1243,7 +1243,7 @@ b = rand(6,7) # return type declarations (promote_op) module RetTypeDecl using Base.Test - import Base: +, *, .*, zero + import Base: +, *, .* immutable MeterUnits{T,P} <: Number val::T @@ -1253,11 +1253,9 @@ module RetTypeDecl m = MeterUnits(1.0, 1) # 1.0 meter, i.e. units of length m2 = MeterUnits(1.0, 2) # 1.0 meter^2, i.e. units of area - (+){T,pow}(x::MeterUnits{T,pow}, y::MeterUnits{T,pow}) = MeterUnits{T,pow}(x.val+y.val) - (*){T,pow}(x::Int, y::MeterUnits{T,pow}) = MeterUnits{typeof(x*one(T)),pow}(x*y.val) + (+){T}(x::MeterUnits{T,1}, y::MeterUnits{T,1}) = MeterUnits{T,1}(x.val+y.val) (*){T}(x::MeterUnits{T,1}, y::MeterUnits{T,1}) = MeterUnits{T,2}(x.val*y.val) (.*){T}(x::MeterUnits{T,1}, y::MeterUnits{T,1}) = MeterUnits{T,2}(x.val*y.val) - zero{T,pow}(x::MeterUnits{T,pow}) = MeterUnits{T,pow}(zero(T)) Base.promote_op{R,S}(::Base.AddFun, ::Type{MeterUnits{R,1}}, ::Type{MeterUnits{S,1}}) = MeterUnits{promote_type(R,S),1} Base.promote_op{R,S}(::Base.MulFun, ::Type{MeterUnits{R,1}}, ::Type{MeterUnits{S,1}}) = MeterUnits{promote_type(R,S),2} @@ -1267,8 +1265,6 @@ module RetTypeDecl @test @inferred([m,m]+m) == [m+m,m+m] @test @inferred(m.*[m,m]) == [m2,m2] @test @inferred([m,m].*m) == [m2,m2] - @test @inferred([m 2m; m m]*[m,m]) == [3m2,2m2] - @test @inferred([m m].*[m,m]) == [m2 m2; m2 m2] end # range, range ops From 64f167f3ff81c5beca1c04d001d878469e01a9ba Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Mon, 30 Nov 2015 23:38:38 -0800 Subject: [PATCH 085/106] Take Git/usr/bin off the path on Windows to hopefully fix starting the binaries in Cygwin or MSYS2 ref https://groups.google.com/forum/#!msg/julia-users/tCfrhMWBEwk/K4-nde_1BQAJ adjust paths in spawn test so it still passes (cherry picked from commit a0197694cdd9b88d7607ae359b76650e7e17bbce) ref #14206 --- contrib/windows/juliarc.jl | 3 +-- test/spawn.jl | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/contrib/windows/juliarc.jl b/contrib/windows/juliarc.jl index db0e0ea61a36f..47158525cad61 100644 --- a/contrib/windows/juliarc.jl +++ b/contrib/windows/juliarc.jl @@ -1,4 +1,3 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license -ENV["PATH"] = JULIA_HOME*";"*joinpath(JULIA_HOME,"..","Git","bin")*";"* - joinpath(JULIA_HOME,"..","Git","usr","bin")*";"*ENV["PATH"] +ENV["PATH"] = JULIA_HOME*";"*joinpath(JULIA_HOME,"..","Git","bin")*";"*ENV["PATH"] diff --git a/test/spawn.jl b/test/spawn.jl index 398198e83095f..e4d87d73b8ffe 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -11,6 +11,8 @@ #TODO: # - Windows: # - Add a test whether coreutils are available and skip tests if not +@windows_only oldpath = ENV["PATH"] +@windows_only ENV["PATH"] = joinpath(JULIA_HOME,"..","Git","usr","bin")*";"*oldpath valgrind_off = ccall(:jl_running_on_valgrind,Cint,()) == 0 @@ -329,3 +331,5 @@ let cmd = AbstractString[] cmd = ["foo bar", "baz"] @test string(`$cmd`) == "`'foo bar' baz`" end + +@windows_only ENV["PATH"] = oldpath From cbebbb71b58531c6aa00906188363886955acaa0 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 1 Dec 2015 17:39:38 -0500 Subject: [PATCH 086/106] Fix doctests for reversion of promote_op change --- doc/devdocs/types.rst | 2 +- doc/manual/conversion-and-promotion.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/devdocs/types.rst b/doc/devdocs/types.rst index 48898e1cd2977..450d9abd2c6b9 100644 --- a/doc/devdocs/types.rst +++ b/doc/devdocs/types.rst @@ -363,7 +363,7 @@ type: in getindex at ./essentials.jl:211 [inlined code] from essentials.jl:218 in show_delim_array at show.jl:229 - [inlined code] from int.jl:360 + [inlined code] from int.jl:358 in show at show.jl:257 in anonymous at show.jl:1294 in with_output_limit at ./show.jl:1271 diff --git a/doc/manual/conversion-and-promotion.rst b/doc/manual/conversion-and-promotion.rst index c001da1f97484..4ef4ebcd10795 100644 --- a/doc/manual/conversion-and-promotion.rst +++ b/doc/manual/conversion-and-promotion.rst @@ -147,7 +147,7 @@ to one and zero: julia> convert(Bool, 1im) ERROR: InexactError() [inlined code] from essentials.jl:25 - in convert at complex.jl:38 + in convert at complex.jl:31 julia> convert(Bool, 0im) false @@ -165,7 +165,7 @@ This is the actual implementation in julia:: julia> convert(Bool, 1im) ERROR: InexactError() [inlined code] from essentials.jl:25 - in convert at complex.jl:38 + in convert at complex.jl:31 Case Study: Rational Conversions From 89386b47c0d27a86cc3c3db82f309039fbef29b0 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 1 Dec 2015 15:02:42 -0500 Subject: [PATCH 087/106] fix #14027, deepcopy throws UndeRefError on some null Nullables (cherry picked from commit 8ad0d6ea5251f39699f0368eddc4e5dbdd15b2f2) --- base/deepcopy.jl | 15 ++++++--------- test/copy.jl | 3 +++ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/base/deepcopy.jl b/base/deepcopy.jl index d705f0f74c00d..b28520de04a45 100644 --- a/base/deepcopy.jl +++ b/base/deepcopy.jl @@ -34,18 +34,15 @@ end function _deepcopy_t(x, T::DataType, stackdict::ObjectIdDict) nf = nfields(T) (isbits(T) || nf == 0) && return x + y = ccall(:jl_new_struct_uninit, Any, (Any,), T) if T.mutable - y = ccall(:jl_new_struct_uninit, Any, (Any,), T) stackdict[x] = y - for i in 1:nf - if isdefined(x,i) - y.(i) = deepcopy_internal(x.(i), stackdict) - end + end + for i in 1:nf + if isdefined(x,i) + ccall(:jl_set_nth_field, Void, (Any, Csize_t, Any), y, i-1, + deepcopy_internal(getfield(x,i), stackdict)) end - else - fields = Any[deepcopy_internal(x.(i), stackdict) for i in 1:nf] - y = ccall(:jl_new_structv, Any, (Any, Ptr{Void}, UInt32), - T, pointer(fields), length(fields)) end return y::T end diff --git a/test/copy.jl b/test/copy.jl index cd5ca21cb3567..f452af8365e32 100644 --- a/test/copy.jl +++ b/test/copy.jl @@ -57,3 +57,6 @@ let a = Any[[1]], q = QuoteNode([1]) @test dca[1] !== a[1] @test deepcopy(q).value !== q.value end + +# issue #14027 +@test isnull(deepcopy(Nullable{Array}())) From b8382ea4a9cd32ea7f2245b77c71a57de60c0d4a Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 1 Dec 2015 15:16:33 -0500 Subject: [PATCH 088/106] fix #14159, suggest `using Base.Dates` instead of `using Dates` (cherry picked from commit f308703afc24d4486d46efeec7b4088e825457c9) --- doc/stdlib/dates.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/stdlib/dates.rst b/doc/stdlib/dates.rst index 8074d8b074e68..6a01349afb0dd 100644 --- a/doc/stdlib/dates.rst +++ b/doc/stdlib/dates.rst @@ -43,8 +43,8 @@ Dates Functions --------------- All Dates functions are defined in the ``Dates`` module; note that only the ``Date``, ``DateTime``, and ``now`` functions are exported; -to use all other ``Dates`` functions, you'll need to prefix each function call with an explicit ``Dates.``, e.g. ``Dates.dayofweek(dt)``; -alternatively, you could call ``using Dates`` to bring all exported functions into ``Main`` to be used without the ``Dates.`` prefix. +to use all other ``Dates`` functions, you'll need to prefix each function call with an explicit ``Dates.``, e.g. ``Dates.dayofweek(dt)``. +Alternatively, you can write ``using Base.Dates`` to bring all exported functions into ``Main`` to be used without the ``Dates.`` prefix. .. function:: DateTime(y, [m, d, h, mi, s, ms]) -> DateTime From af1cd90c33fc40777ed3f0cd501ec21b78b77e71 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Tue, 1 Dec 2015 13:47:32 +0100 Subject: [PATCH 089/106] Comment out two assertions on elapsed time in pollfd test (cherry picked from commit 0bf41279a75a6b5380a49fac22cf797e8a8e6cdd) ref #14207 --- test/pollfd.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/pollfd.jl b/test/pollfd.jl index f7d50d6a40c9e..1c1a71b88232d 100644 --- a/test/pollfd.jl +++ b/test/pollfd.jl @@ -33,8 +33,8 @@ function pfd_tst_reads(idx, intvl) @test @windows ? evt.writable : !evt.writable # println("Expected ", intvl, ", actual ", t_elapsed, ", diff ", t_elapsed - intvl) - # Assuming that a 2 second buffer is good enough on a modern system - @test t_elapsed <= (intvl + 1) + # Disabled since this assertion fails randomly, notably on build VMs (issue #12824) + # @test t_elapsed <= (intvl + 1) dout = Array(UInt8, 1) @windows ? ( @@ -56,9 +56,9 @@ function pfd_tst_timeout(idx, intvl) @test !evt.writable t_elapsed = toq() - # Disabled since this assertion fails randomly, notably on build VMs (issue #12824) + # Disabled since these assertions fail randomly, notably on build VMs (issue #12824) # @unix_only @test (intvl <= t_elapsed) # TODO: enable this test on windows when the libuv version is bumped - @test (t_elapsed <= (intvl + 1)) + # @test (t_elapsed <= (intvl + 1)) end From 084c906305f91862ba8867ecb82623d59069fcdd Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 1 Dec 2015 19:57:29 -0800 Subject: [PATCH 090/106] Don't use shared pkg .cache directory any more on Windows The directory junctions created by `symlink` are proving too problematic with respect to network drives. This essentially reverts #7361. Ref #14026 and #14205. (cherry picked from commit 61d1087960185d76fd9b7542576a82a9dd01e72f) ref #14225 --- base/pkg/cache.jl | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/base/pkg/cache.jl b/base/pkg/cache.jl index 842d3ba9eba52..3916405635476 100644 --- a/base/pkg/cache.jl +++ b/base/pkg/cache.jl @@ -13,19 +13,13 @@ function mkcachedir() return end - @windows_only if Base.windows_version() < Base.WINDOWS_VISTA_VER - mkdir(cache) - return - end - if Dir.isversioned(pwd()) + @unix_only if Dir.isversioned(pwd()) rootcache = joinpath(realpath(".."), ".cache") if !isdir(rootcache) mkdir(rootcache) end - try - symlink(rootcache, cache) - return - end + symlink(rootcache, cache) + return end mkdir(cache) end From 906288e320330ccb90531b14a5b8730b49182c42 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 1 Dec 2015 22:28:11 -0800 Subject: [PATCH 091/106] Fix #14205, package installation on a network drive on Windows also see #12166 and https://github.com/git-for-windows/git/issues/554 and https://groups.google.com/forum/#!msg/msysgit/5J3ELvZND0s/2VPm-eUf0YMJ when doing a clone from a local bare repository, need file:// prefix for it to work correctly when on a Windows network drive this is only an issue on release-0.4, libgit2 on master appears to work correctly --- base/pkg/write.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/pkg/write.jl b/base/pkg/write.jl index 4f9c68c7bd16a..77f3bfe2a7564 100644 --- a/base/pkg/write.jl +++ b/base/pkg/write.jl @@ -32,7 +32,8 @@ function install(pkg::AbstractString, sha1::AbstractString) if isdir(".trash/$pkg") mv(".trash/$pkg", "./$pkg") else - Git.run(`clone -q $(Cache.path(pkg)) $pkg`) + fileprefix = @windows? "file://" : "" + Git.run(`clone -q $(fileprefix * Cache.path(pkg)) $pkg`) end fetch(pkg, sha1) checkout(pkg, sha1) From b938804443a1333f3c2b5d5d698f12f7f3974854 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 1 Dec 2015 22:58:24 -0800 Subject: [PATCH 092/106] Adjust header comment in juliarc.jl (cherry picked from commit 1868fee0dde30ba3365ee528fbb8906e11cb1ced) --- contrib/add_license_to_files.jl | 39 +++++++++++++++++---------------- contrib/windows/juliarc.jl | 3 ++- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/contrib/add_license_to_files.jl b/contrib/add_license_to_files.jl index 53a7e94ddfe38..97f755b8c7c4a 100644 --- a/contrib/add_license_to_files.jl +++ b/contrib/add_license_to_files.jl @@ -30,26 +30,27 @@ const excludedirs = [ const skipfiles = [ "../contrib/add_license_to_files.jl", + "../contrib/windows/juliarc.jl", # files to check - already copyright - # see: https://github.com/JuliaLang/julia/pull/11073#issuecomment-98099389 - "../base/special/trig.jl", - "../base/sparse/csparse.jl", - "../base/linalg/givens.jl", - # - "../src/abi_llvm.cpp", - "../src/abi_win32.cpp", - "../src/abi_win64.cpp", - "../src/abi_x86.cpp", - "../src/abi_x86_64.cpp", - "../src/disasm.cpp", - "../src/support/END.h", - "../src/support/ENTRY.amd64.h", - "../src/support/ENTRY.i387.h", - "../src/support/MurmurHash3.c", - "../src/support/MurmurHash3.h", - "../src/support/asprintf.c", - "../src/support/strtod.c", - "../src/support/utf8.c", + # see: https://github.com/JuliaLang/julia/pull/11073#issuecomment-98099389 + "../base/special/trig.jl", + "../base/sparse/csparse.jl", + "../base/linalg/givens.jl", + # + "../src/abi_llvm.cpp", + "../src/abi_win32.cpp", + "../src/abi_win64.cpp", + "../src/abi_x86.cpp", + "../src/abi_x86_64.cpp", + "../src/disasm.cpp", + "../src/support/END.h", + "../src/support/ENTRY.amd64.h", + "../src/support/ENTRY.i387.h", + "../src/support/MurmurHash3.c", + "../src/support/MurmurHash3.h", + "../src/support/asprintf.c", + "../src/support/strtod.c", + "../src/support/utf8.c", ] const ext_prefix = Dict([ diff --git a/contrib/windows/juliarc.jl b/contrib/windows/juliarc.jl index 47158525cad61..f2eca8637eed9 100644 --- a/contrib/windows/juliarc.jl +++ b/contrib/windows/juliarc.jl @@ -1,3 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file should contain site-specific commands to be executed on Julia startup +# Users should store their own personal commands in homedir(), in a file named .juliarc.jl ENV["PATH"] = JULIA_HOME*";"*joinpath(JULIA_HOME,"..","Git","bin")*";"*ENV["PATH"] From 74a3188bc0916141dc4d62bb49f5d70b0aa5531e Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 1 Dec 2015 23:50:07 -0800 Subject: [PATCH 093/106] Fix nonportable shelling out use Dates module in Pkg.generate (already fixed in PkgDev.jl) temporarily add path to Git/usr/bin on Windows for tests that shell out ls in test/gitutils.jl iconv and perl in test/strings/io.jl cat in test/cmdlineargs.jl backport of b613309e0109001b33214a904acad8e266b07ca5 with a few additions for release-0.4 --- base/pkg/generate.jl | 2 +- test/cmdlineargs.jl | 11 +++++++---- test/gitutils.jl | 18 ++++++++++++------ test/strings/io.jl | 3 +++ 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/base/pkg/generate.jl b/base/pkg/generate.jl index 0c41174bf8768..af6c74376f2f2 100644 --- a/base/pkg/generate.jl +++ b/base/pkg/generate.jl @@ -4,7 +4,7 @@ module Generate import ..Git, ..Read -copyright_year() = readchomp(`date +%Y`) +copyright_year() = string(Dates.year(Dates.today())) copyright_name(dir::AbstractString) = readchomp(Git.cmd(`config --get user.name`, dir=dir)) github_user() = readchomp(ignorestatus(`git config --global --get github.user`)) diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index 9a8e9396aed1a..66c0e76c2a7b5 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -228,8 +228,11 @@ let exename = `$(joinpath(JULIA_HOME, Base.julia_exename())) --precompiled=yes` @test readchomp(`$exename -e 'println(ARGS);' ''`) == "UTF8String[\"\"]" # issue #12679 - @test readchomp(pipeline(ignorestatus(`$exename -f --compile=yes -foo`),stderr=`cat`)) == "ERROR: unknown option `-o`" - @test readchomp(pipeline(ignorestatus(`$exename -f -p`),stderr=`cat`)) == "ERROR: option `-p/--procs` is missing an argument" - @test readchomp(pipeline(ignorestatus(`$exename -f --inline`),stderr=`cat`)) == "ERROR: option `--inline` is missing an argument" - @test readchomp(pipeline(ignorestatus(`$exename -f -e "@show ARGS" -now -- julia RUN.jl`),stderr=`cat`)) == "ERROR: unknown option `-n`" + extrapath = @windows? joinpath(JULIA_HOME,"..","Git","usr","bin")*";" : "" + withenv("PATH" => extrapath * ENV["PATH"]) do + @test readchomp(pipeline(ignorestatus(`$exename -f --compile=yes -foo`),stderr=`cat`)) == "ERROR: unknown option `-o`" + @test readchomp(pipeline(ignorestatus(`$exename -f -p`),stderr=`cat`)) == "ERROR: option `-p/--procs` is missing an argument" + @test readchomp(pipeline(ignorestatus(`$exename -f --inline`),stderr=`cat`)) == "ERROR: option `--inline` is missing an argument" + @test readchomp(pipeline(ignorestatus(`$exename -f -e "@show ARGS" -now -- julia RUN.jl`),stderr=`cat`)) == "ERROR: unknown option `-n`" + end end diff --git a/test/gitutils.jl b/test/gitutils.jl index 9485719ebf880..d42d02a15640d 100644 --- a/test/gitutils.jl +++ b/test/gitutils.jl @@ -72,9 +72,12 @@ function verify_work(d::Dict) end end # check for anything that's not in d - for line in eachline(`ls -A`) - name = chomp(line) - @test name == ".git" || haskey(d,name) + extrapath = @windows? joinpath(JULIA_HOME,"..","Git","usr","bin")*";" : "" + withenv("PATH" => extrapath * ENV["PATH"]) do + for line in eachline(`ls -A`) + name = chomp(line) + @test name == ".git" || haskey(d,name) + end end end @@ -91,9 +94,12 @@ function git_setup(h::Dict, i::Dict, w::Dict, parents::AbstractString...) work = mktree(w) # clear the repo - for line in eachline(`ls -A`) - name = chomp(line) - name == ".git" || rm(name, recursive=true) + extrapath = @windows? joinpath(JULIA_HOME,"..","Git","usr","bin")*";" : "" + withenv("PATH" => extrapath * ENV["PATH"]) do + for line in eachline(`ls -A`) + name = chomp(line) + name == ".git" || rm(name, recursive=true) + end end # create the head commit diff --git a/test/strings/io.jl b/test/strings/io.jl index dc315fb3bb62e..405444afbdf78 100644 --- a/test/strings/io.jl +++ b/test/strings/io.jl @@ -134,6 +134,8 @@ end @test "\x0f" == unescape_string("\\x0f") @test "\x0F" == unescape_string("\\x0F") +extrapath = @windows? joinpath(JULIA_HOME,"..","Git","usr","bin")*";" : "" +withenv("PATH" => extrapath * ENV["PATH"]) do if !success(`iconv --version`) warn("iconv not found, skipping unicode tests!") @windows_only warn("Use WinRPM.install(\"win_iconv\") to run these tests") @@ -201,6 +203,7 @@ else end rm(unicodedir) end +end # Tests of join() @test join([]) == "" From 783c2de7b5119b7ac2aa8630a187879214893a55 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Tue, 1 Dec 2015 20:18:11 -0500 Subject: [PATCH 094/106] Don't declare something a long and pass it as a size_t The two are not the same on Win64, causing type intersection to sometimes return incorrect answers (not fun!). (cherry picked from commit b0e19c87380b88a7a907ab6227bcc4fdeb5bf3ab) ref #14223 --- src/jltypes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jltypes.c b/src/jltypes.c index 3591bddf2f719..43a9b2b969ba6 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -833,7 +833,7 @@ static jl_value_t *jl_type_intersect(jl_value_t *a, jl_value_t *b, if (b == (jl_value_t*)jl_any_type || b == jl_ANY_flag) return a; // tuple if (jl_is_tuple_type(a)) { - long alen = (long)jl_nparams(a); + size_t alen = jl_nparams(a); jl_value_t *temp=NULL; JL_GC_PUSH2(&b, &temp); if (jl_is_ntuple_type(b)) { From 10defac13af8d4ab5b0d9beebcb66da5678a914e Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Wed, 2 Dec 2015 17:32:12 -0500 Subject: [PATCH 095/106] Revert "Fix doctests" This reverts commit d8b91c6e42d6fa5aaec0f7c302539545db6fd354. --- base/docs/helpdb.jl | 1 - doc/devdocs/types.rst | 8 ++------ doc/manual/complex-and-rational-numbers.rst | 3 --- doc/manual/constructors.rst | 2 -- doc/manual/control-flow.rst | 7 ------- doc/manual/conversion-and-promotion.rst | 6 ++---- doc/manual/mathematical-operations.rst | 6 +----- doc/manual/strings.rst | 2 -- doc/manual/types.rst | 1 - doc/stdlib/collections.rst | 1 - 10 files changed, 5 insertions(+), 32 deletions(-) diff --git a/base/docs/helpdb.jl b/base/docs/helpdb.jl index f1fdd5ef068fb..f508e7399d081 100644 --- a/base/docs/helpdb.jl +++ b/base/docs/helpdb.jl @@ -6733,7 +6733,6 @@ julia> deleteat!([6, 5, 4, 3, 2, 1], 1:2:5) julia> deleteat!([6, 5, 4, 3, 2, 1], (2, 2)) ERROR: ArgumentError: indices must be unique and sorted - [inlined code] from essentials.jl:59 in deleteat! at array.jl:546 ``` """ diff --git a/doc/devdocs/types.rst b/doc/devdocs/types.rst index 450d9abd2c6b9..1310a2e2161d5 100644 --- a/doc/devdocs/types.rst +++ b/doc/devdocs/types.rst @@ -359,19 +359,15 @@ type: julia> MyType.name.cache svec(MyType{Float32,5},MyType{Int64,2},Evaluation succeeded, but an error occurred while showing value of type SimpleVector: ERROR: UndefRefError: access to undefined reference - [inlined code] from ./essentials.jl:30 in getindex at ./essentials.jl:211 - [inlined code] from essentials.jl:218 in show_delim_array at show.jl:229 - [inlined code] from int.jl:358 in show at show.jl:257 in anonymous at show.jl:1294 in with_output_limit at ./show.jl:1271 in showlimited at show.jl:1293 - [inlined code] from replutil.jl:4 in display at multimedia.jl:120 - [inlined code] from operators.jl:313 - in display at multimedia.jl:163 + [inlined code] from multimedia.jl:151 + in display at multimedia.jl:162 (The error is triggered because the cache is pre-allocated to have length 8, but only the first two entries are populated.) diff --git a/doc/manual/complex-and-rational-numbers.rst b/doc/manual/complex-and-rational-numbers.rst index 6d0479bc2eeb6..8274529a89b50 100644 --- a/doc/manual/complex-and-rational-numbers.rst +++ b/doc/manual/complex-and-rational-numbers.rst @@ -159,7 +159,6 @@ versus ``-1 + 0im`` even though ``-1 == -1 + 0im``: julia> sqrt(-1) ERROR: DomainError: sqrt will only return a complex result if called with a complex argument. Try sqrt(complex(x)). - [inlined code] from math.jl:144 in sqrt at math.jl:146 julia> sqrt(-1 + 0im) @@ -304,9 +303,7 @@ Trying to construct a :const:`NaN` rational value, however, is not: julia> 0//0 ERROR: ArgumentError: invalid rational: zero(Int64)//zero(Int64) - [inlined code] from strings/io.jl:43 in call at rational.jl:8 - [inlined code] from rational.jl:13 in // at rational.jl:22 As usual, the promotion system makes interactions with other numeric diff --git a/doc/manual/constructors.rst b/doc/manual/constructors.rst index 8983e8c8c1dda..15fab79f4956d 100644 --- a/doc/manual/constructors.rst +++ b/doc/manual/constructors.rst @@ -121,7 +121,6 @@ Now ``OrderedPair`` objects can only be constructed such that julia> OrderedPair(2,1) ERROR: out of order - [inlined code] from error.jl:21 in call at none:5 You can still reach in and directly change the field values to violate @@ -340,7 +339,6 @@ types of the arguments given to the constructor. Here are some examples: julia> Point{Int64}(1.0,2.5) ERROR: InexactError() - [inlined code] from int.jl:209 in call at none:2 julia> Point{Float64}(1.0,2.5) diff --git a/doc/manual/control-flow.rst b/doc/manual/control-flow.rst index 4b56a3fb47564..143f0de971bf7 100644 --- a/doc/manual/control-flow.rst +++ b/doc/manual/control-flow.rst @@ -162,7 +162,6 @@ the above function results in a runtime error julia> test(2,1) ERROR: UndefVarError: relation not defined - [inlined code] from strings/io.jl:28 in test at none:7 ``if`` blocks also return a value, which may seem unintuitive to users @@ -366,7 +365,6 @@ For example, a recursive factorial routine could be defined like this: julia> factorial(-1) ERROR: n must be non-negative - [inlined code] from error.jl:21 in factorial at none:2 @@ -663,7 +661,6 @@ negative real value: julia> sqrt(-1) ERROR: DomainError: sqrt will only return a complex result if called with a complex argument. Try sqrt(complex(x)). - [inlined code] from math.jl:144 in sqrt at math.jl:146 You may define your own exceptions in the following way: @@ -689,7 +686,6 @@ if the argument is negative: julia> f(-1) ERROR: DomainError: - [inlined code] from essentials.jl:23 in f at none:1 Note that :exc:`DomainError` without parentheses is not an exception, but a type of @@ -741,7 +737,6 @@ the :func:`sqrt` function that raises an error if its argument is negative: julia> fussy_sqrt(-1) ERROR: negative x not allowed - [inlined code] from error.jl:21 in fussy_sqrt at none:1 If ``fussy_sqrt`` is called with a negative value from another function, @@ -767,7 +762,6 @@ session: julia> verbose_fussy_sqrt(-1) before fussy_sqrt ERROR: negative x not allowed - [inlined code] from error.jl:21 in verbose_fussy_sqrt at none:3 Warnings and informational messages @@ -848,7 +842,6 @@ assumes ``x`` is a real number and returns its square root: julia> sqrt_second(-9) ERROR: DomainError: - [inlined code] from math.jl:144 in sqrt_second at none:7 Note that the symbol following ``catch`` will always be interpreted as a diff --git a/doc/manual/conversion-and-promotion.rst b/doc/manual/conversion-and-promotion.rst index 4ef4ebcd10795..c975e4ebc9198 100644 --- a/doc/manual/conversion-and-promotion.rst +++ b/doc/manual/conversion-and-promotion.rst @@ -146,8 +146,7 @@ to one and zero: julia> convert(Bool, 1im) ERROR: InexactError() - [inlined code] from essentials.jl:25 - in convert at complex.jl:31 + in convert at complex.jl:18 julia> convert(Bool, 0im) false @@ -164,8 +163,7 @@ This is the actual implementation in julia:: julia> convert(Bool, 1im) ERROR: InexactError() - [inlined code] from essentials.jl:25 - in convert at complex.jl:31 + in convert at complex.jl:18 Case Study: Rational Conversions diff --git a/doc/manual/mathematical-operations.rst b/doc/manual/mathematical-operations.rst index 4242ad55e5fcd..5bdefaa4208b2 100644 --- a/doc/manual/mathematical-operations.rst +++ b/doc/manual/mathematical-operations.rst @@ -380,7 +380,6 @@ The following examples show the different forms. julia> Int8(128) ERROR: InexactError() - [inlined code] from int.jl:172 in call at essentials.jl:56 julia> Int8(127.0) @@ -388,12 +387,10 @@ The following examples show the different forms. julia> Int8(3.14) ERROR: InexactError() - [inlined code] from int.jl:209 in call at essentials.jl:56 julia> Int8(128.0) ERROR: InexactError() - [inlined code] from int.jl:209 in call at essentials.jl:56 julia> 127 % Int8 @@ -407,9 +404,8 @@ The following examples show the different forms. julia> round(Int8,127.6) ERROR: InexactError() - [inlined code] from essentials.jl:25 in trunc at float.jl:357 - in round at float.jl:188 + in round at float.jl:177 See :ref:`man-conversion-and-promotion` for how to define your own conversions and promotions. diff --git a/doc/manual/strings.rst b/doc/manual/strings.rst index c56657d0c5a5d..f7de1ca0d3ac3 100644 --- a/doc/manual/strings.rst +++ b/doc/manual/strings.rst @@ -291,13 +291,11 @@ such an invalid byte index, an error is thrown: julia> s[2] ERROR: UnicodeError: invalid character index - [inlined code] from ./int.jl:187 in next at ./unicode/utf8.jl:65 in getindex at strings/basic.jl:37 julia> s[3] ERROR: UnicodeError: invalid character index - [inlined code] from ./int.jl:187 in next at ./unicode/utf8.jl:65 in getindex at strings/basic.jl:37 diff --git a/doc/manual/types.rst b/doc/manual/types.rst index 2ac88624915b8..ac1e76f2fd5a2 100644 --- a/doc/manual/types.rst +++ b/doc/manual/types.rst @@ -401,7 +401,6 @@ However, the value for ``baz`` must be convertible to :class:`Int`: julia> Foo((), 23.5, 1) ERROR: InexactError() - [inlined code] from float.jl:24 in call at none:2 You may find a list of field names using the ``fieldnames`` function. diff --git a/doc/stdlib/collections.rst b/doc/stdlib/collections.rst index 9a07f313cd0d6..bcb3ab2ab2e49 100644 --- a/doc/stdlib/collections.rst +++ b/doc/stdlib/collections.rst @@ -1161,7 +1161,6 @@ Dequeues julia> deleteat!([6, 5, 4, 3, 2, 1], (2, 2)) ERROR: ArgumentError: indices must be unique and sorted - [inlined code] from essentials.jl:59 in deleteat! at array.jl:546 .. function:: splice!(collection, index, [replacement]) -> item From fa54d2290aa85f29f78b1a859b88bc04c2ceb902 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Wed, 2 Dec 2015 17:32:36 -0500 Subject: [PATCH 096/106] Revert "Ignore line number node when counting expressions for inlining. Fix #13551" This reverts commit 617db6b7625acebb22361c63ab1d898fa3f1e1bc. --- base/inference.jl | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 36ddda51cfea6..840da1b351f5c 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -1925,7 +1925,6 @@ end function occurs_more(e::ANY, pred, n) if isa(e,Expr) e = e::Expr - e.head === :line && return 0 c = 0 for a = e.args c += occurs_more(a, pred, n) @@ -2613,17 +2612,10 @@ function inline_worthy(body::Expr, cost::Integer=1000) # precondition: 0 < cost; return false end symlim = 1000 + 5_000_000 ÷ cost - nargs = 0 - for arg in body.args - if (!isa(arg, LineNumberNode) && - !(isa(arg, Expr) && (arg::Expr).head === :line)) - nargs += 1 - end - end - if nargs < (symlim + 500) ÷ 1000 + if length(body.args) < (symlim + 500) ÷ 1000 symlim *= 16 symlim ÷= 1000 - if occurs_more(body, e->(!isa(e, LineNumberNode)), symlim) < symlim + if occurs_more(body, e->true, symlim) < symlim return true end end @@ -2661,7 +2653,7 @@ end const corenumtype = Union{Int32,Int64,Float32,Float64} function inlining_pass(e::Expr, sv, ast) - if e.head === :method + if e.head == :method # avoid running the inlining pass on function definitions return (e,()) end From 3202b54f8fdacc086db43518bdb88505dbdc84be Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Wed, 2 Dec 2015 17:44:03 -0500 Subject: [PATCH 097/106] Revert "fix #922 (wrong line numbers in error expressions) and remove old hacks around this issue" This reverts commit b8a6d771042add982a6a8739994c6f7dba2f4461. --- src/builtins.c | 6 ++++++ src/cgutils.cpp | 14 ++++++++----- src/codegen.cpp | 52 +++++++++++++++++++++++++++++------------------ src/julia.h | 3 +++ src/task.c | 5 +++++ test/backtrace.jl | 3 +-- 6 files changed, 56 insertions(+), 27 deletions(-) diff --git a/src/builtins.c b/src/builtins.c index f1a3d6dd538e5..8495f0261a746 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -103,6 +103,12 @@ void NORETURN jl_type_error_rt(const char *fname, const char *context, jl_throw(ex); } +void NORETURN jl_type_error_rt_line(const char *fname, const char *context, + jl_value_t *ty, jl_value_t *got, int line) +{ + jl_type_error_rt(fname, context, ty, got); +} + void NORETURN jl_type_error(const char *fname, jl_value_t *expected, jl_value_t *got) { jl_type_error_rt(fname, "", expected, got); diff --git a/src/cgutils.cpp b/src/cgutils.cpp index ef2fd9912266d..e9225a1527245 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -1059,9 +1059,11 @@ static void raise_exception_unless(Value *cond, Value *exc, jl_codectx_t *ctx) builder.CreateCondBr(cond, passBB, failBB); builder.SetInsertPoint(failBB); #ifdef LLVM37 - builder.CreateCall(prepare_call(jlthrow_func), { exc }); + builder.CreateCall(prepare_call(jlthrow_line_func), { exc, + ConstantInt::get(T_int32, ctx->lineno) }); #else - builder.CreateCall(prepare_call(jlthrow_func), exc); + builder.CreateCall2(prepare_call(jlthrow_line_func), exc, + ConstantInt::get(T_int32, ctx->lineno)); #endif builder.CreateUnreachable(); ctx->f->getBasicBlockList().push_back(passBB); @@ -1105,11 +1107,13 @@ static void emit_type_error(Value *x, jl_value_t *type, const std::string &msg, #ifdef LLVM37 builder.CreateCall(prepare_call(jltypeerror_func), { fname_val, msg_val, - literal_pointer_val(type), boxed(x,ctx)}); + literal_pointer_val(type), boxed(x,ctx), + ConstantInt::get(T_int32, ctx->lineno) }); #else - builder.CreateCall4(prepare_call(jltypeerror_func), + builder.CreateCall5(prepare_call(jltypeerror_func), fname_val, msg_val, - literal_pointer_val(type), boxed(x,ctx)); + literal_pointer_val(type), boxed(x,ctx), + ConstantInt::get(T_int32, ctx->lineno)); #endif } diff --git a/src/codegen.cpp b/src/codegen.cpp index 8934ff70a68a2..cafe14806d5e4 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -298,6 +298,7 @@ extern RTDyldMemoryManager* createRTDyldMemoryManagerOSX(); // important functions static Function *jlnew_func; static Function *jlthrow_func; +static Function *jlthrow_line_func; static Function *jlerror_func; static Function *jltypeerror_func; static Function *jlundefvarerror_func; @@ -467,6 +468,7 @@ typedef struct { bool vaStack; // varargs stack-allocated bool sret; int nReqArgs; + int lineno; std::vector boundsCheck; jl_gcinfo_t gc; @@ -1270,7 +1272,7 @@ extern "C" void jl_write_malloc_log(void) static void show_source_loc(JL_STREAM *out, jl_codectx_t *ctx) { if (ctx == NULL) return; - jl_printf(out, "in %s at %s", ctx->linfo->name->name, ctx->linfo->file->name); + jl_printf(out, "in %s at %s:%d", ctx->linfo->name->name, ctx->linfo->file->name, ctx->lineno); } extern "C" void jl_binding_deprecation_warning(jl_binding_t *b); @@ -4183,6 +4185,7 @@ static Function *emit_function(jl_lambda_info_t *lam) } } } + ctx.lineno = lno; int toplineno = lno; DIBuilder dbuilder(*m); @@ -4194,7 +4197,6 @@ static Function *emit_function(jl_lambda_info_t *lam) DIFile topfile; DISubprogram SP; #endif - DebugLoc inlineLoc; BasicBlock *b0 = BasicBlock::Create(jl_LLVMContext, "top", f); builder.SetInsertPoint(b0); @@ -4275,8 +4277,7 @@ static Function *emit_function(jl_lambda_info_t *lam) f); // Function #endif // set initial line number - inlineLoc = DebugLoc::get(lno, 0, (MDNode*)SP, NULL); - builder.SetCurrentDebugLocation(inlineLoc); + builder.SetCurrentDebugLocation(DebugLoc::get(lno, 0, (MDNode*)SP, NULL)); #ifdef LLVM38 f->setSubprogram(SP); #endif @@ -4296,7 +4297,7 @@ static Function *emit_function(jl_lambda_info_t *lam) argname->name, // Variable name ctx.sret + i + 1, // Argument number (1-based) topfile, // File - toplineno == -1 ? 0 : toplineno, // Line + ctx.lineno == -1 ? 0 : ctx.lineno, // Line // Variable type julia_type_to_di(varinfo.declType,ctx.dbuilder,specsig)); #else @@ -4305,7 +4306,7 @@ static Function *emit_function(jl_lambda_info_t *lam) SP, // Scope (current function will be fill in later) argname->name, // Variable name topfile, // File - toplineno == -1 ? 0 : toplineno, // Line (for now, use lineno of the function) + ctx.lineno == -1 ? 0 : ctx.lineno, // Line (for now, use lineno of the function) julia_type_to_di(varinfo.declType,ctx.dbuilder,specsig), // Variable type false, // May be optimized out 0, // Flags (TODO: Do we need any) @@ -4319,7 +4320,7 @@ static Function *emit_function(jl_lambda_info_t *lam) ctx.vaName->name, // Variable name ctx.sret + nreq + 1, // Argument number (1-based) topfile, // File - toplineno == -1 ? 0 : toplineno, // Line (for now, use lineno of the function) + ctx.lineno == -1 ? 0 : ctx.lineno, // Line (for now, use lineno of the function) julia_type_to_di(ctx.vars[ctx.vaName].declType,ctx.dbuilder,false)); #else ctx.vars[ctx.vaName].dinfo = ctx.dbuilder->createLocalVariable( @@ -4327,7 +4328,7 @@ static Function *emit_function(jl_lambda_info_t *lam) SP, // Scope (current function will be fill in later) ctx.vaName->name, // Variable name topfile, // File - toplineno == -1 ? 0 : toplineno, // Line (for now, use lineno of the function) + ctx.lineno == -1 ? 0 : ctx.lineno, // Line (for now, use lineno of the function) julia_type_to_di(ctx.vars[ctx.vaName].declType,ctx.dbuilder,false), // Variable type false, // May be optimized out 0, // Flags (TODO: Do we need any) @@ -4348,7 +4349,7 @@ static Function *emit_function(jl_lambda_info_t *lam) SP, // Scope (current function will be fill in later) s->name, // Variable name topfile, // File - toplineno == -1 ? 0 : toplineno, // Line (for now, use lineno of the function) + ctx.lineno == -1 ? 0 : ctx.lineno, // Line (for now, use lineno of the function) julia_type_to_di(varinfo.declType,ctx.dbuilder,specsig), // Variable type false, // May be optimized out 0 // Flags (TODO: Do we need any) @@ -4372,7 +4373,7 @@ static Function *emit_function(jl_lambda_info_t *lam) SP, // Scope (current function will be filled in later) vname->name, // Variable name topfile, // File - toplineno == -1 ? 0 : toplineno, // Line (for now, use lineno of the function) + ctx.lineno == -1 ? 0 : ctx.lineno, // Line (for now, use lineno of the function) julia_type_to_di(varinfo.declType,ctx.dbuilder,specsig), // Variable type false, // May be optimized out 0 // Flags (TODO: Do we need any) @@ -4738,6 +4739,7 @@ static Function *emit_function(jl_lambda_info_t *lam) } DebugLoc loc; if (ctx.debug_enabled) { + MDNode *funcscope = (MDNode*)dbuilder.createLexicalBlockFile(SP, topfile); MDNode *scope; if ((dfil == topfile || dfil == NULL) && lno >= toplineno) @@ -4745,17 +4747,19 @@ static Function *emit_function(jl_lambda_info_t *lam) // for sequentially-defined code, // set location to line in top file. // TODO: improve handling of nested inlines - loc = inlineLoc = DebugLoc::get(lno, 1, SP, NULL); + loc = DebugLoc::get(lno, 1, SP, NULL); } else { // otherwise, we are compiling inlined code, // so set the DebugLoc "inlinedAt" parameter // to the current line, then use source loc. #ifdef LLVM37 scope = (MDNode*)dbuilder.createLexicalBlockFile(SP,dfil); - MDNode *inlineLocMd = inlineLoc.getAsMDNode(); + MDNode *inlineLocMd = DebugLoc::get(toplineno, 1, funcscope, NULL). + getAsMDNode(); #else scope = (MDNode*)dbuilder.createLexicalBlockFile(SP,DIFile(dfil)); - MDNode *inlineLocMd = inlineLoc.getAsMDNode(jl_LLVMContext); + MDNode *inlineLocMd = DebugLoc::get(toplineno, 1, funcscope, NULL). + getAsMDNode(jl_LLVMContext); #endif loc = DebugLoc::get(lno, 1, scope, inlineLocMd); } @@ -4763,6 +4767,7 @@ static Function *emit_function(jl_lambda_info_t *lam) } if (do_coverage) coverageVisitLine(filename, lno); + ctx.lineno = lno; // NOO TOUCHIE; NO TOUCH! See #922 } if (jl_is_labelnode(stmt)) { if (prevlabel) continue; @@ -5201,6 +5206,15 @@ static void init_julia_llvm_env(Module *m) jluboundserror_func->setDoesNotReturn(); add_named_global(jluboundserror_func, (void*)&jl_bounds_error_unboxed_int); + std::vector args2_throw(0); + args2_throw.push_back(jl_pvalue_llvmt); + args2_throw.push_back(T_int32); + jlthrow_line_func = + (Function*)m->getOrInsertFunction("jl_throw_with_superfluous_argument", + FunctionType::get(T_void, args2_throw, false)); + jlthrow_line_func->setDoesNotReturn(); + add_named_global(jlthrow_line_func, (void*)&jl_throw_with_superfluous_argument); + jlnew_func = Function::Create(jl_func_sig, Function::ExternalLinkage, "jl_new_structv", m); @@ -5231,12 +5245,13 @@ static void init_julia_llvm_env(Module *m) te_args.push_back(T_pint8); te_args.push_back(jl_pvalue_llvmt); te_args.push_back(jl_pvalue_llvmt); + te_args.push_back(T_int32); jltypeerror_func = Function::Create(FunctionType::get(T_void, te_args, false), Function::ExternalLinkage, - "jl_type_error_rt", m); + "jl_type_error_rt_line", m); jltypeerror_func->setDoesNotReturn(); - add_named_global(jltypeerror_func, (void*)&jl_type_error_rt); + add_named_global(jltypeerror_func, (void*)&jl_type_error_rt_line); std::vector args_2ptrs(0); args_2ptrs.push_back(jl_pvalue_llvmt); @@ -5678,16 +5693,13 @@ static inline SmallVector getTargetFeatures() { extern "C" void jl_init_codegen(void) { - const char *const argv_tailmerge[] = {"", "-enable-tail-merge=0"}; // NOO TOUCHIE; NO TOUCH! See #922 - cl::ParseCommandLineOptions(sizeof(argv_tailmerge)/sizeof(argv_tailmerge[0]), argv_tailmerge, "disable-tail-merge\n"); #if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_) - const char *const argv_copyprop[] = {"", "-disable-copyprop"}; // llvm bug 21743 - cl::ParseCommandLineOptions(sizeof(argv_copyprop)/sizeof(argv_copyprop[0]), argv_copyprop, "disable-copyprop\n"); + const char *const argv[] = {"", "-disable-copyprop"}; // llvm bug 21743 + cl::ParseCommandLineOptions(sizeof(argv)/sizeof(argv[0]), argv, "disable-copyprop\n"); #endif #ifdef JL_DEBUG_BUILD cl::ParseEnvironmentOptions("Julia", "JULIA_LLVM_ARGS"); #endif - #if defined(_CPU_PPC_) || defined(_CPU_PPC64_) imaging_mode = true; // LLVM seems to JIT bad TOC tables for the optimizations we attempt in non-imaging_mode #else diff --git a/src/julia.h b/src/julia.h index fce506f7d7914..29407e9b8055f 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1146,6 +1146,8 @@ DLLEXPORT void NORETURN jl_too_many_args(const char *fname, int max); DLLEXPORT void NORETURN jl_type_error(const char *fname, jl_value_t *expected, jl_value_t *got); DLLEXPORT void NORETURN jl_type_error_rt(const char *fname, const char *context, jl_value_t *ty, jl_value_t *got); +DLLEXPORT void NORETURN jl_type_error_rt_line(const char *fname, const char *context, + jl_value_t *ty, jl_value_t *got, int line); DLLEXPORT void NORETURN jl_undefined_var_error(jl_sym_t *var); DLLEXPORT void NORETURN jl_bounds_error(jl_value_t *v, jl_value_t *t); DLLEXPORT void NORETURN jl_bounds_error_v(jl_value_t *v, jl_value_t **idxs, size_t nidxs); @@ -1399,6 +1401,7 @@ extern DLLEXPORT JL_THREAD jl_value_t *jl_exception_in_transit; DLLEXPORT jl_task_t *jl_new_task(jl_function_t *start, size_t ssize); DLLEXPORT jl_value_t *jl_switchto(jl_task_t *t, jl_value_t *arg); DLLEXPORT void NORETURN jl_throw(jl_value_t *e); +DLLEXPORT void NORETURN jl_throw_with_superfluous_argument(jl_value_t *e, int); DLLEXPORT void NORETURN jl_rethrow(void); DLLEXPORT void NORETURN jl_rethrow_other(jl_value_t *e); diff --git a/src/task.c b/src/task.c index f2cde6166ae61..99e8ac9647191 100644 --- a/src/task.c +++ b/src/task.c @@ -836,6 +836,11 @@ DLLEXPORT void jl_rethrow_other(jl_value_t *e) throw_internal(e); } +DLLEXPORT void jl_throw_with_superfluous_argument(jl_value_t *e, int line) +{ + jl_throw(e); +} + DLLEXPORT jl_task_t *jl_new_task(jl_function_t *start, size_t ssize) { size_t pagesz = jl_page_size; diff --git a/test/backtrace.jl b/test/backtrace.jl index 4f6b2eb6d194b..d5b9f3ad97c5f 100644 --- a/test/backtrace.jl +++ b/test/backtrace.jl @@ -99,6 +99,5 @@ let ind2 = find(:test_throw_commoning .== map(b->code_loc(b)[1], b2)) @test !isempty(ind1) @test !isempty(ind2) - @test code_loc(b1[ind1[1]])[3]::Int == code_loc(b2[ind2[1]])[3]::Int && # source line, for example: essentials.jl:58 - code_loc(b1[ind1[1]])[5]::Int != code_loc(b2[ind2[1]])[5]::Int # inlined line, for example: backtrace.jl:82 + @test code_loc(b1[ind1[1]])[3] != code_loc(b2[ind2[1]])[3] end From 9f8ec24adba6a8360ad4d0a7e0e10d22b9941db7 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Wed, 2 Dec 2015 17:32:48 -0500 Subject: [PATCH 098/106] Revert "preserve inline line numbers during inlining" This reverts commit 488fb5a5978589fec4e703203d333f27b859a4aa. --- base/inference.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/inference.jl b/base/inference.jl index 840da1b351f5c..dc07af2f2e5f5 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -2245,7 +2245,8 @@ function inlineable(f::ANY, e::Expr, atype::ANY, sv::StaticVarInfo, enclosing_as end body = Expr(:block) - body.args = ast.args[3].args::Array{Any,1} + body.args = filter(x->!((isa(x,Expr) && is(x.head,:line)) || isa(x,LineNumberNode)), + ast.args[3].args::Array{Any,1}) cost::Int = 1000 if incompletematch cost *= 4 From 74dcb330dd76ecad44739dac36229616d71ce557 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 3 Dec 2015 16:27:54 -0500 Subject: [PATCH 099/106] Also remove the problematic pointer case (cherry picked from commit b794bf9eb63b0f2f5d3159bc7fe1b9aa7eb317bd) --- src/jltypes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jltypes.c b/src/jltypes.c index 43a9b2b969ba6..e518cf097a5ed 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -845,7 +845,7 @@ static jl_value_t *jl_type_intersect(jl_value_t *a, jl_value_t *b, if (eqc->data[i] == lenvar) { jl_value_t *v = eqc->data[i+1]; // N is already known in NTuple{N,...} - if (jl_get_size(v, (size_t *)&alen)) break; + if (jl_get_size(v, &alen)) break; } } b = (jl_value_t*)jl_tupletype_fill(alen, elty); From f9d049bd226f0f754c33dbdc16f51779cf45b449 Mon Sep 17 00:00:00 2001 From: Erik Schnetter Date: Thu, 3 Dec 2015 11:20:40 -0500 Subject: [PATCH 100/106] Ignore non-rst files when generating stdlib documentation Most importantly this skips backup files left by some editors, which otherwise confuse the script. (cherry picked from commit 98292947d60f7617593a742c72b4167fe9a8ecd6) ref #14250 --- doc/genstdlib.jl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/genstdlib.jl b/doc/genstdlib.jl index 04bd624d471c6..30759b85cc83f 100644 --- a/doc/genstdlib.jl +++ b/doc/genstdlib.jl @@ -286,9 +286,11 @@ function translate(file) end for folder in ["stdlib", "manual", "devdocs"] - println("\nConverting $folder/\n") + println("\nConverting rst files in $folder/\n") for file in readdir("$folder") - translate("$folder/$file") + if endswith(file, ".rst") + translate("$folder/$file") + end end end From 0a268e7deb791c72bdff5fd90e1f020da074ea67 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sat, 5 Dec 2015 13:18:28 -0800 Subject: [PATCH 101/106] build with assertions enabled on appveyor (cherry picked from commit b0cf837b9cf26f25cc68d52b2fa24354be894c77) --- contrib/windows/msys_build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/windows/msys_build.sh b/contrib/windows/msys_build.sh index cecae2581a369..4feba26649c2e 100755 --- a/contrib/windows/msys_build.sh +++ b/contrib/windows/msys_build.sh @@ -197,6 +197,7 @@ else make VERBOSE=1 -C base version_git.jl.phony echo 'NO_GIT = 1' >> Make.user fi +echo 'FORCE_ASSERTIONS = 1' >> Make.user cat Make.user make VERBOSE=1 From 09b44c2abf9ad7a23766b5916aaedbae6831aa74 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 5 Dec 2015 18:53:33 -0500 Subject: [PATCH 102/106] add a test for reading 128 bit ints from RandomDevice (cherry picked from commit 358f2ef7af43aa7e4665c21fdb22bf81698f89b5) ref #14283 --- test/random.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/random.jl b/test/random.jl index dc78c9368239d..5ed896248319f 100644 --- a/test/random.jl +++ b/test/random.jl @@ -286,6 +286,11 @@ let mt = MersenneTwister() end end +# make sure reading 128-bit ints from RandomDevice works +let a = [rand(RandomDevice(), UInt128) for i=1:10] + @test reduce(|, a)>>>64 != 0 +end + # test all rand APIs for rng in ([], [MersenneTwister()], [RandomDevice()]) for f in [rand, randn, randexp] From bea4d83a67565eafb9b19e98c4bc2835f86cb3d9 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sun, 6 Dec 2015 00:28:59 -0800 Subject: [PATCH 103/106] Only apply openblas patch on Windows (cherry picked from commit a4f2e2ec0b1cf2dbc59a134b08c2c2f49e5498b1) --- deps/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deps/Makefile b/deps/Makefile index bd3cfd175537c..051b23d2ea82b 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -1080,7 +1080,9 @@ OPENBLAS_BUILD_OPTS += NO_AVX2=1 endif $(OPENBLAS_SRC_DIR)/config.status: $(OPENBLAS_SRC_DIR)/Makefile +ifeq ($(OS),WINNT) cd $(dir $@) && patch -p1 < ../openblas-win64.patch +endif perl -i -ple 's/^\s*(EXTRALIB\s*\+=\s*-lSystemStubs)\s*$$/# $$1/g' $(OPENBLAS_SRC_DIR)/Makefile.system touch $@ $(OPENBLAS_OBJ_SOURCE): $(OPENBLAS_SRC_DIR)/config.status From d0af15f7249aac0ce4e937e23cf93eef28f62fdf Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sat, 5 Dec 2015 04:10:46 -0500 Subject: [PATCH 104/106] Fix travis_fastfail.sh for null case when an old PR build gets restarted after some time, the travis API request might not return enough builds to include the most recent one for the PR, so the null result would incorrectly cause a 'superceded' fast-fail condition (cherry picked from commit 111f5e5a0d18be556060fb4f91a89505f9116ff7) --- contrib/travis_fastfail.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/contrib/travis_fastfail.sh b/contrib/travis_fastfail.sh index 8d692c430653b..6eb349a49b1ff 100755 --- a/contrib/travis_fastfail.sh +++ b/contrib/travis_fastfail.sh @@ -5,9 +5,10 @@ curlhdr="Accept: application/vnd.travis-ci.2+json" endpoint="https://api.travis-ci.org/repos/$TRAVIS_REPO_SLUG" # Fail fast for superseded builds to PR's -if ! [ "$TRAVIS_PULL_REQUEST" = "false" ]; then - if ! [ \"$TRAVIS_BUILD_NUMBER\" = $(curl -H "$curlhdr" $endpoint/builds?event_type=pull_request | \ - jq ".builds | map(select(.pull_request_number == $TRAVIS_PULL_REQUEST))[0].number") ]; then +if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then + newestbuildforthisPR=$(curl -H "$curlhdr" $endpoint/builds?event_type=pull_request | \ + jq ".builds | map(select(.pull_request_number == $TRAVIS_PULL_REQUEST))[0].number") + if [ $newestbuildforthisPR != null -a $newestbuildforthisPR != \"$TRAVIS_BUILD_NUMBER\" ]; then echo "There are newer queued builds for this pull request, failing early." exit 1 fi @@ -17,7 +18,7 @@ else master | release*) ;; *) - if ! [ \"$TRAVIS_BUILD_NUMBER\" = $(curl -H "$curlhdr" \ + if [ \"$TRAVIS_BUILD_NUMBER\" != $(curl -H "$curlhdr" \ $endpoint/branches/$TRAVIS_BRANCH | jq ".branch.number") ]; then echo "There are newer queued builds for this branch, failing early." exit 1 From c49006707ff5707186ee8259e57be9af7dffe6eb Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Mon, 12 Oct 2015 12:27:32 -0700 Subject: [PATCH 105/106] use sudo: false worker on linux travis with cached source build of deps ref #13569 (cherry picked from commit d7fc5d81a3ed42587bbd43413ef0518b4cf1af92) Only cache deps on Travis for master and release branches (cherry picked from commit 05301b9b8827b67d506f136e1d24eecb4d739bd9) leave old travis cache in place for non-master builds delete .pyc files from doc build (cherry picked from commit 005510711adc779ef47fa0586b3922b8d9c78ba4) --- .travis.yml | 70 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/.travis.yml b/.travis.yml index 34e40fce6d4de..089b5adf5252a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,32 @@ language: cpp -os: - - linux - - osx -env: - - ARCH="i686" - - ARCH="x86_64" +sudo: false matrix: - exclude: - - os: osx + include: + - os: linux env: ARCH="i686" + addons: + apt: + packages: + - binutils:i386 + - gcc:i386 + - g++:i386 + - make:i386 + - cpp:i386 + - libssl-dev:i386 + - gfortran:i386 + - os: linux + env: ARCH="x86_64" + addons: + apt: + packages: + - gfortran + - os: osx + env: ARCH="x86_64" +cache: + directories: + - $TRAVIS_BUILD_DIR/deps/srccache + - $TRAVIS_BUILD_DIR/deps/build-i686 + - $TRAVIS_BUILD_DIR/deps/build-x86_64 notifications: email: false irc: @@ -23,29 +41,14 @@ notifications: before_install: - make check-whitespace - if [ `uname` = "Linux" ]; then - sudo apt-get install jq -y; contrib/travis_fastfail.sh || exit 1; - BUILDOPTS="-j3 USEGCC=1 LLVM_CONFIG=llvm-config-3.3 VERBOSE=1 USE_BLAS64=0 FORCE_ASSERTIONS=1 STAGE2_DEPS=utf8proc"; - for lib in LLVM SUITESPARSE ARPACK BLAS FFTW LAPACK GMP MPFR OPENLIBM; do - export BUILDOPTS="$BUILDOPTS USE_SYSTEM_$lib=1"; - done; - sudo add-apt-repository ppa:staticfloat/julia-deps -y; - sudo apt-get update -qq -y; - if [ "$ARCH" = "i686" ]; then - export BUILDOPTS="$BUILDOPTS MARCH=pentium4"; - sudo apt-get remove libblas3gf liblapack3gf libarmadillo2 -y; - sudo apt-get install binutils:i386 -y; - sudo apt-get install gcc:i386 g++:i386 make:i386 cpp:i386 g++-4.6:i386 gcc-4.6:i386 libssl-dev:i386 patchelf:i386 gfortran:i386 llvm-3.3-dev:i386 libsuitesparse-dev:i386 libopenblas-dev:i386 libopenblas-base:i386 libblas-dev:i386 liblapack-dev:i386 liblapack3:i386 libarpack2-dev:i386 libarpack2:i386 libfftw3-dev:i386 libgmp-dev:i386 libpcre3-dev:i386 libopenlibm-dev:i386 libmpfr-dev:i386 -y; - else - export JULIA_TEST_MAXRSS_MB="500"; - sudo apt-get install patchelf gfortran llvm-3.3-dev libsuitesparse-dev libopenblas-dev liblapack-dev libarpack2-dev libfftw3-dev libgmp-dev libpcre3-dev libopenlibm-dev libmpfr-dev -y; - fi; + BUILDOPTS="-j3 VERBOSE=1 FORCE_ASSERTIONS=1"; elif [ `uname` = "Darwin" ]; then - brew tap staticfloat/julia; - brew rm --force $(brew deps --HEAD julia); brew update; brew install -v jq; contrib/travis_fastfail.sh || exit 1; + brew tap staticfloat/julia; + brew rm --force $(brew deps --HEAD julia); brew install -v --only-dependencies --HEAD julia; BUILDOPTS="-j3 USECLANG=1 LLVM_CONFIG=$(brew --prefix llvm33-julia)/bin/llvm-config-3.3 VERBOSE=1 USE_BLAS64=0 SUITESPARSE_INC=-I$(brew --prefix suite-sparse-julia)/include FORCE_ASSERTIONS=1 STAGE2_DEPS=utf8proc"; BUILDOPTS="$BUILDOPTS LIBBLAS=-lopenblas LIBBLASNAME=libopenblas LIBLAPACK=-lopenblas LIBLAPACKNAME=libopenblas"; @@ -56,9 +59,11 @@ before_install: export DYLD_FALLBACK_LIBRARY_PATH="/usr/local/lib:/lib:/usr/lib:$(brew --prefix openblas-julia)/lib:$(brew --prefix suite-sparse-julia)/lib:$(brew --prefix arpack-julia)/lib"; make $BUILDOPTS -C contrib -f repackage_system_suitesparse4.make; fi + - git clone -q git://git.kitenet.net/moreutils script: + - if [ -e deps/build-$ARCH ]; then cp -a deps/build-$ARCH deps/build; fi - make $BUILDOPTS -C base version_git.jl.phony - - git clone -q git://git.kitenet.net/moreutils + - make $BUILDOPTS NO_GIT=1 -C deps > deps.log || cat deps.log - make $BUILDOPTS NO_GIT=1 JULIA_SYSIMG_BUILD_FLAGS="--output-ji ../usr/lib/julia/sys.ji" prefix=/tmp/julia install | moreutils/ts -s "%.s" - if [ `uname` = "Darwin" ]; then for name in suitesparseconfig spqr umfpack colamd cholmod amd suitesparse_wrapper; do @@ -69,6 +74,11 @@ script: - cp /tmp/julia/lib/julia/sys.ji local.ji && /tmp/julia/bin/julia -J local.ji -e 'true' && /tmp/julia/bin/julia-debug -J local.ji -e 'true' && rm local.ji - /tmp/julia/bin/julia -e 'versioninfo()' - export JULIA_CPU_CORES=2 && cd /tmp/julia/share/julia/test && /tmp/julia/bin/julia --check-bounds=yes runtests.jl all && /tmp/julia/bin/julia --check-bounds=yes runtests.jl pkg - - cd - && mv julia2 julia - - sudo dmesg - - echo "Ready for packaging..." + - cd `dirname $TRAVIS_BUILD_DIR` && mv julia2 julia && rm -f julia/deps/build/julia-env/src/*/*/*.pyc + - case $TRAVIS_PULL_REQUEST-$TRAVIS_BRANCH in + false-master | false-release*) + rm -rf julia/deps/build-$ARCH && + mv julia/deps/build julia/deps/build-$ARCH;; + esac +# uncomment the following if failures are suspected to be due to the out-of-memory killer +# - dmesg From 652d1de4aec0ecf19375b1fc412399097936180e Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sun, 6 Dec 2015 03:10:57 -0800 Subject: [PATCH 106/106] Travis caching adjustments for release-0.4 --- .travis.yml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 089b5adf5252a..f0c0ab8791dac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,9 +24,8 @@ matrix: env: ARCH="x86_64" cache: directories: - - $TRAVIS_BUILD_DIR/deps/srccache - - $TRAVIS_BUILD_DIR/deps/build-i686 - - $TRAVIS_BUILD_DIR/deps/build-x86_64 + - $TRAVIS_BUILD_DIR/deps-i686 + - $TRAVIS_BUILD_DIR/deps-x86_64 notifications: email: false irc: @@ -43,6 +42,9 @@ before_install: - if [ `uname` = "Linux" ]; then contrib/travis_fastfail.sh || exit 1; BUILDOPTS="-j3 VERBOSE=1 FORCE_ASSERTIONS=1"; + if [ "$ARCH" = "i686" ]; then + export BUILDOPTS="$BUILDOPTS MARCH=pentium4"; + fi; elif [ `uname` = "Darwin" ]; then brew update; brew install -v jq; @@ -61,7 +63,7 @@ before_install: fi - git clone -q git://git.kitenet.net/moreutils script: - - if [ -e deps/build-$ARCH ]; then cp -a deps/build-$ARCH deps/build; fi + - if [ -n "`ls deps-$ARCH`" ]; then cp -a deps-$ARCH/* deps; fi - make $BUILDOPTS -C base version_git.jl.phony - make $BUILDOPTS NO_GIT=1 -C deps > deps.log || cat deps.log - make $BUILDOPTS NO_GIT=1 JULIA_SYSIMG_BUILD_FLAGS="--output-ji ../usr/lib/julia/sys.ji" prefix=/tmp/julia install | moreutils/ts -s "%.s" @@ -74,11 +76,13 @@ script: - cp /tmp/julia/lib/julia/sys.ji local.ji && /tmp/julia/bin/julia -J local.ji -e 'true' && /tmp/julia/bin/julia-debug -J local.ji -e 'true' && rm local.ji - /tmp/julia/bin/julia -e 'versioninfo()' - export JULIA_CPU_CORES=2 && cd /tmp/julia/share/julia/test && /tmp/julia/bin/julia --check-bounds=yes runtests.jl all && /tmp/julia/bin/julia --check-bounds=yes runtests.jl pkg - - cd `dirname $TRAVIS_BUILD_DIR` && mv julia2 julia && rm -f julia/deps/build/julia-env/src/*/*/*.pyc + - cd `dirname $TRAVIS_BUILD_DIR` && mv julia2 julia && rm -f julia/deps/julia-env/src/*/*/*.pyc - case $TRAVIS_PULL_REQUEST-$TRAVIS_BRANCH in false-master | false-release*) - rm -rf julia/deps/build-$ARCH && - mv julia/deps/build julia/deps/build-$ARCH;; + cd julia && rm -rf deps-$ARCH && mkdir -p deps-$ARCH && + for i in $(git ls-files -o --directory deps); do + mv $i deps-$ARCH; + done;; esac # uncomment the following if failures are suspected to be due to the out-of-memory killer # - dmesg