diff --git a/base/abstractarray.jl b/base/abstractarray.jl index e74181d6428d1..22714acac9d16 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1409,12 +1409,12 @@ end # These are needed because map(eltype, As) is not inferrable promote_eltype_op(::Any) = (@_pure_meta; Bottom) -promote_eltype_op(op, A) = (@_pure_meta; _promote_op(op, eltype(A))) -promote_eltype_op{T}(op, ::AbstractArray{T}) = (@_pure_meta; _promote_op(op, T)) -promote_eltype_op{T}(op, ::AbstractArray{T}, A) = (@_pure_meta; _promote_op(op, T, eltype(A))) -promote_eltype_op{T}(op, A, ::AbstractArray{T}) = (@_pure_meta; _promote_op(op, eltype(A), T)) -promote_eltype_op{R,S}(op, ::AbstractArray{R}, ::AbstractArray{S}) = (@_pure_meta; _promote_op(op, R, S)) -promote_eltype_op(op, A, B, C, D...) = (@_pure_meta; promote_eltype_op(op, promote_eltype_op(op, A, B), C, D...)) +promote_eltype_op{T}(op, ::AbstractArray{T}) = (@_pure_meta; promote_op(op, T)) +promote_eltype_op{T}(op, ::T ) = (@_pure_meta; promote_op(op, T)) +promote_eltype_op{R,S}(op, ::AbstractArray{R}, ::AbstractArray{S}) = (@_pure_meta; promote_op(op, R, S)) +promote_eltype_op{R,S}(op, ::AbstractArray{R}, ::S) = (@_pure_meta; promote_op(op, R, S)) +promote_eltype_op{R,S}(op, ::R, ::AbstractArray{S}) = (@_pure_meta; promote_op(op, R, S)) +promote_eltype_op(op, A, B, C, D...) = (@_pure_meta; promote_op(op, eltype(A), promote_eltype_op(op, B, C, D...))) ## 1 argument map!{F}(f::F, A::AbstractArray) = map!(f, A, A) diff --git a/base/arraymath.jl b/base/arraymath.jl index f5a0954b8323e..319f7937cc8e4 100644 --- a/base/arraymath.jl +++ b/base/arraymath.jl @@ -35,26 +35,30 @@ function !(A::AbstractArray{Bool}) end ## Binary arithmetic operators ## +@pure promote_array_type{S<:Number, A<:AbstractArray}(F, ::Type{S}, ::Type{A}) = + promote_array_type(F, S, eltype(A), promote_op(F, S, eltype(A))) +@pure promote_array_type{S<:Number, A<:AbstractArray}(F, ::Type{A}, ::Type{S}) = + promote_array_type(F, S, eltype(A), promote_op(F, eltype(A), S)) -promote_array_type(F, ::Type, ::Type, T::Type) = T -promote_array_type{S<:Real, A<:AbstractFloat}(F, ::Type{S}, ::Type{A}, ::Type) = A -promote_array_type{S<:Integer, A<:Integer}(F, ::Type{S}, ::Type{A}, ::Type) = A -promote_array_type{S<:Integer, A<:Integer}(::typeof(./), ::Type{S}, ::Type{A}, T::Type) = T -promote_array_type{S<:Integer, A<:Integer}(::typeof(.\), ::Type{S}, ::Type{A}, T::Type) = T -promote_array_type{S<:Integer}(::typeof(./), ::Type{S}, ::Type{Bool}, T::Type) = T -promote_array_type{S<:Integer}(::typeof(.\), ::Type{S}, ::Type{Bool}, T::Type) = T -promote_array_type{S<:Integer}(F, ::Type{S}, ::Type{Bool}, T::Type) = T +@pure promote_array_type{S, A, P}(F, ::Type{S}, ::Type{A}, ::Type{P}) = P +@pure promote_array_type{S<:Real, A<:AbstractFloat, P}(F, ::Type{S}, ::Type{A}, ::Type{P}) = A +@pure promote_array_type{S<:Integer, A<:Integer, P}(F::typeof(./), ::Type{S}, ::Type{A}, ::Type{P}) = P +@pure promote_array_type{S<:Integer, A<:Integer, P}(F::typeof(.\), ::Type{S}, ::Type{A}, ::Type{P}) = P +@pure promote_array_type{S<:Integer, A<:Integer, P}(F, ::Type{S}, ::Type{A}, ::Type{P}) = A +@pure promote_array_type{S<:Integer, P}(F::typeof(./), ::Type{S}, ::Type{Bool}, ::Type{P}) = P +@pure promote_array_type{S<:Integer, P}(F::typeof(.\), ::Type{S}, ::Type{Bool}, ::Type{P}) = P +@pure promote_array_type{S<:Integer, P}(F, ::Type{S}, ::Type{Bool}, ::Type{P}) = P for f in (:+, :-, :div, :mod, :&, :|, :$) - @eval ($f)(A::AbstractArray, B::AbstractArray) = - _elementwise($f, promote_op($f, eltype(A), eltype(B)), A, B) + @eval ($f){S,T}(A::AbstractArray{S}, B::AbstractArray{T}) = + _elementwise($f, A, B, promote_eltype_op($f, A, B)) end -function _elementwise(op, ::Type{Any}, A::AbstractArray, B::AbstractArray) - promote_shape(A, B) # check size compatibility +function _elementwise{S,T}(op, A::AbstractArray{S}, B::AbstractArray{T}, ::Type{Any}) + promote_shape(A,B) # check size compatibility return broadcast(op, A, B) end -function _elementwise{T}(op, ::Type{T}, A::AbstractArray, B::AbstractArray) - F = similar(A, T, promote_shape(A, B)) +function _elementwise{S,T,R}(op, A::AbstractArray{S}, B::AbstractArray{T}, ::Type{R}) + F = similar(A, R, promote_shape(A,B)) for (iF, iA, iB) in zip(eachindex(F), eachindex(A), eachindex(B)) @inbounds F[iF] = op(A[iA], B[iB]) end @@ -63,21 +67,15 @@ end for f in (:.+, :.-, :.*, :./, :.\, :.^, :.÷, :.%, :.<<, :.>>, :div, :mod, :rem, :&, :|, :$) @eval begin - function ($f)(A::Number, B::AbstractArray) - P = promote_op($f, typeof(A), eltype(B)) - T = promote_array_type($f, typeof(A), eltype(B), P) - T === Any && return [($f)(A, b) for b in B] - F = similar(B, T) + function ($f){T}(A::Number, B::AbstractArray{T}) + F = similar(B, promote_array_type($f,typeof(A),typeof(B))) for (iF, iB) in zip(eachindex(F), eachindex(B)) @inbounds F[iF] = ($f)(A, B[iB]) end return F end - function ($f)(A::AbstractArray, B::Number) - P = promote_op($f, eltype(A), typeof(B)) - T = promote_array_type($f, typeof(B), eltype(A), P) - T === Any && return [($f)(a, B) for a in A] - F = similar(A, T) + function ($f){T}(A::AbstractArray{T}, B::Number) + F = similar(A, promote_array_type($f,typeof(A),typeof(B))) for (iF, iA) in zip(eachindex(F), eachindex(A)) @inbounds F[iF] = ($f)(A[iA], B) end diff --git a/base/bitarray.jl b/base/bitarray.jl index 81ba017866ee9..f3e7ff9c90689 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -1035,29 +1035,18 @@ for f in (:+, :-) return r end end - for (f) in (:.+, :.-) - for (arg1, arg2, T, t) in ((:(B::BitArray), :(x::Bool) , Int , (:b, :x)), - (:(B::BitArray), :(x::Number) , :(Bool, typeof(x)), (:b, :x)), - (:(x::Bool) , :(B::BitArray), Int , (:x, :b)), - (:(x::Number) , :(B::BitArray), :(typeof(x), Bool), (:x, :b))) + for (arg1, arg2, T, fargs) in ((:(B::BitArray), :(x::Bool) , Int , :(b, x)), + (:(B::BitArray), :(x::Number) , :(promote_array_type($f, BitArray, typeof(x))), :(b, x)), + (:(x::Bool) , :(B::BitArray), Int , :(x, b)), + (:(x::Number) , :(B::BitArray), :(promote_array_type($f, typeof(x), BitArray)), :(x, b))) @eval function ($f)($arg1, $arg2) - $(if T === Int - quote - r = Array{Int}(size(B)) - end - else - quote - T = promote_op($f, $(T.args[1]), $(T.args[2])) - T === Any && return [($f)($(t[1]), $(t[2])) for b in B] - r = Array{T}(size(B)) - end - end) + r = Array{$T}(size(B)) bi = start(B) ri = 1 while !done(B, bi) b, bi = next(B, bi) - @inbounds r[ri] = ($f)($(t[1]), $(t[2])) + @inbounds r[ri] = ($f)($fargs...) ri += 1 end return r @@ -1089,8 +1078,9 @@ function div(x::Bool, B::BitArray) end function div(x::Number, B::BitArray) all(B) || throw(DivideError()) + pt = promote_array_type(div, typeof(x), BitArray) y = div(x, true) - return fill(y, size(B)) + reshape(pt[ y for i = 1:length(B) ], size(B)) end function mod(A::BitArray, B::BitArray) @@ -1109,16 +1099,15 @@ function mod(x::Bool, B::BitArray) end function mod(x::Number, B::BitArray) all(B) || throw(DivideError()) + pt = promote_array_type(mod, typeof(x), BitArray) y = mod(x, true) - return fill(y, size(B)) + reshape(pt[ y for i = 1:length(B) ], size(B)) end for f in (:div, :mod) @eval begin function ($f)(B::BitArray, x::Number) - T = promote_op($f, Bool, typeof(x)) - T === Any && return [($f)(b, x) for b in B] - F = Array{T}(size(B)) + F = Array{promote_array_type($f, BitArray, typeof(x))}(size(B)) for i = 1:length(F) F[i] = ($f)(B[i], x) end diff --git a/base/broadcast.jl b/base/broadcast.jl index e42f2a67edfbc..937d66375bd9a 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -3,7 +3,7 @@ module Broadcast using Base.Cartesian -using Base: promote_eltype_op, @get!, _msk_end, unsafe_bitgetindex, linearindices, tail, OneTo, to_shape +using Base: promote_op, promote_eltype, promote_eltype_op, @get!, _msk_end, unsafe_bitgetindex, linearindices, tail, OneTo, to_shape import Base: .+, .-, .*, ./, .\, .//, .==, .<, .!=, .<=, .÷, .%, .<<, .>>, .^ export broadcast, broadcast!, bitbroadcast, dotview export broadcast_getindex, broadcast_setindex! @@ -299,7 +299,7 @@ end ## elementwise operators ## for op in (:÷, :%, :<<, :>>, :-, :/, :\, ://, :^) - @eval $(Symbol(:., op))(A::AbstractArray, B::AbstractArray) = broadcast($op, A, B) + @eval $(Symbol(:., op))(A::AbstractArray, B::AbstractArray) = broadcast($(op), A, B) end .+(As::AbstractArray...) = broadcast(+, As...) .*(As::AbstractArray...) = broadcast(*, As...) diff --git a/base/char.jl b/base/char.jl index 58481c6d39c2a..52aa1492e2f86 100644 --- a/base/char.jl +++ b/base/char.jl @@ -40,6 +40,10 @@ hash(x::Char, h::UInt) = hash_uint64(((UInt64(x)+hashchar_seed)<<32) $ UInt64(h) +(x::Char, y::Integer) = Char(Int32(x) + Int32(y)) +(x::Integer, y::Char) = y + x +Base.promote_op{I<:Integer}(::typeof(-), ::Type{Char}, ::Type{I}) = Char +Base.promote_op{I<:Integer}(::typeof(+), ::Type{Char}, ::Type{I}) = Char +Base.promote_op{I<:Integer}(::typeof(+), ::Type{I}, ::Type{Char}) = Char + bswap(x::Char) = Char(bswap(UInt32(x))) print(io::IO, c::Char) = (write(io, c); nothing) diff --git a/base/complex.jl b/base/complex.jl index 7be18a036f951..da644f9412331 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -804,8 +804,7 @@ big{T<:AbstractFloat,N}(A::AbstractArray{Complex{T},N}) = convert(AbstractArray{ ## promotion to complex ## -_default_type(T::Type{Complex}) = Complex{Int} -promote_array_type{S<:Union{Complex, Real}, T<:AbstractFloat}(F, ::Type{S}, ::Type{Complex{T}}, ::Type) = Complex{T} +promote_array_type{S<:Union{Complex, Real}, AT<:AbstractFloat, P}(F, ::Type{S}, ::Type{Complex{AT}}, ::Type{P}) = Complex{AT} function complex{S<:Real,T<:Real}(A::AbstractArray{S}, B::AbstractArray{T}) if size(A) != size(B); throw(DimensionMismatch()); end diff --git a/base/dates/arithmetic.jl b/base/dates/arithmetic.jl index 94752ffe2390a..4a94fc13df911 100644 --- a/base/dates/arithmetic.jl +++ b/base/dates/arithmetic.jl @@ -94,3 +94,21 @@ end # AbstractArray{TimeType}, AbstractArray{TimeType} (-){T<:TimeType}(x::OrdinalRange{T}, y::OrdinalRange{T}) = collect(x) - collect(y) (-){T<:TimeType}(x::Range{T}, y::Range{T}) = collect(x) - collect(y) + +# promotion rules + +for op in (:+, :-, :.+, :.-) + @eval begin + Base.promote_op{P<:Period}(::typeof($op), ::Type{P}, ::Type{P}) = P + Base.promote_op{P1<:Period,P2<:Period}(::typeof($op), ::Type{P1}, ::Type{P2}) = CompoundPeriod + Base.promote_op{D<:Date}(::typeof($op), ::Type{D}, ::Type{D}) = Day + Base.promote_op{D<:DateTime}(::typeof($op), ::Type{D}, ::Type{D}) = Millisecond + end +end + +for op in (:/, :%, :div, :mod, :./, :.%) + @eval begin + Base.promote_op{P<:Period}(::typeof($op), ::Type{P}, ::Type{P}) = typeof($op(1,1)) + Base.promote_op{P<:Period,R<:Real}(::typeof($op), ::Type{P}, ::Type{R}) = P + end +end diff --git a/base/float.jl b/base/float.jl index 01767dd3d4123..20b7e9a2513ca 100644 --- a/base/float.jl +++ b/base/float.jl @@ -230,8 +230,6 @@ promote_rule(::Type{Float64}, ::Type{Float32}) = Float64 widen(::Type{Float16}) = Float32 widen(::Type{Float32}) = Float64 -_default_type(T::Union{Type{Real},Type{AbstractFloat}}) = Float64 - ## floating point arithmetic ## -(x::Float32) = box(Float32,neg_float(unbox(Float32,x))) -(x::Float64) = box(Float64,neg_float(unbox(Float64,x))) diff --git a/base/int.jl b/base/int.jl index 79cfb0ddafb0b..ca3242cc682f5 100644 --- a/base/int.jl +++ b/base/int.jl @@ -305,9 +305,6 @@ promote_rule{T<:BitSigned64}(::Type{UInt64}, ::Type{T}) = UInt64 promote_rule{T<:Union{UInt32, UInt64}}(::Type{T}, ::Type{Int128}) = Int128 promote_rule{T<:BitSigned}(::Type{UInt128}, ::Type{T}) = UInt128 -_default_type(T::Type{Unsigned}) = UInt -_default_type(T::Union{Type{Integer},Type{Signed}}) = Int - ## traits ## typemin(::Type{Int8 }) = Int8(-128) diff --git a/base/irrationals.jl b/base/irrationals.jl index a5e091f5ca1e3..e76f40760c0b9 100644 --- a/base/irrationals.jl +++ b/base/irrationals.jl @@ -10,6 +10,13 @@ promote_rule{s}(::Type{Irrational{s}}, ::Type{Float32}) = Float32 promote_rule{s,t}(::Type{Irrational{s}}, ::Type{Irrational{t}}) = Float64 promote_rule{s,T<:Number}(::Type{Irrational{s}}, ::Type{T}) = promote_type(Float64,T) +promote_op{S<:Irrational,T<:Irrational}(op::Any, ::Type{S}, ::Type{T}) = + promote_op(op, Float64, Float64) +promote_op{S<:Irrational,T<:Number}(op::Any, ::Type{S}, ::Type{T}) = + promote_op(op, Float64, T) +promote_op{S<:Irrational,T<:Number}(op::Any, ::Type{T}, ::Type{S}) = + promote_op(op, T, Float64) + convert(::Type{AbstractFloat}, x::Irrational) = Float64(x) convert(::Type{Float16}, x::Irrational) = Float16(Float32(x)) convert{T<:Real}(::Type{Complex{T}}, x::Irrational) = convert(Complex{T}, convert(T,x)) diff --git a/base/linalg/matmul.jl b/base/linalg/matmul.jl index aa713321a42bb..6c9117a3cd06e 100644 --- a/base/linalg/matmul.jl +++ b/base/linalg/matmul.jl @@ -76,11 +76,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(*, arithtype(T), arithtype(S)) + TS = promote_op(*,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(*, arithtype(T), arithtype(S)) + TS = promote_op(*,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 @@ -99,22 +99,22 @@ end A_mul_B!(y::AbstractVector, A::AbstractVecOrMat, x::AbstractVector) = generic_matvecmul!(y, 'N', A, x) function At_mul_B{T<:BlasFloat,S}(A::StridedMatrix{T}, x::StridedVector{S}) - TS = promote_op(*, arithtype(T), arithtype(S)) + TS = promote_op(*,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::AbstractMatrix{T}, x::AbstractVector{S}) - TS = promote_op(*, arithtype(T), arithtype(S)) + TS = promote_op(*,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::AbstractVector, A::AbstractVecOrMat, x::AbstractVector) = generic_matvecmul!(y, 'T', A, x) function Ac_mul_B{T<:BlasFloat,S}(A::StridedMatrix{T}, x::StridedVector{S}) - TS = promote_op(*, arithtype(T), arithtype(S)) + TS = promote_op(*,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::AbstractMatrix{T}, x::AbstractVector{S}) - TS = promote_op(*, arithtype(T), arithtype(S)) + TS = promote_op(*,arithtype(T),arithtype(S)) Ac_mul_B!(similar(x,TS,size(A,2)), A, x) end @@ -142,14 +142,14 @@ end A_mul_B!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic_matmatmul!(C, 'N', 'N', A, B) function At_mul_B{T,S}(A::AbstractMatrix{T}, B::AbstractMatrix{S}) - TS = promote_op(*, arithtype(T), arithtype(S)) + TS = promote_op(*,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::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic_matmatmul!(C, 'T', 'N', A, B) function A_mul_Bt{T,S}(A::AbstractMatrix{T}, B::AbstractMatrix{S}) - TS = promote_op(*, arithtype(T), arithtype(S)) + TS = promote_op(*,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) @@ -166,7 +166,7 @@ end A_mul_Bt!(C::AbstractVecOrMat, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic_matmatmul!(C, 'N', 'T', A, B) function At_mul_Bt{T,S}(A::AbstractMatrix{T}, B::AbstractVecOrMat{S}) - TS = promote_op(*, arithtype(T), arithtype(S)) + TS = promote_op(*,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) @@ -175,7 +175,7 @@ At_mul_Bt!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = generi 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::AbstractMatrix{T}, B::AbstractMatrix{S}) - TS = promote_op(*, arithtype(T), arithtype(S)) + TS = promote_op(*,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) @@ -184,14 +184,13 @@ Ac_mul_B!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic 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::AbstractMatrix{T}, B::AbstractMatrix{S}) - TS = promote_op(*, arithtype(T), arithtype(S)) + TS = promote_op(*,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::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic_matmatmul!(C, 'N', 'C', A, B) -Ac_mul_Bc{T,S}(A::AbstractMatrix{T}, B::AbstractMatrix{S}) = - Ac_mul_Bc!(similar(B, promote_op(*, arithtype(T), arithtype(S)), (size(A,2), size(B,1))), A, B) +Ac_mul_Bc{T,S}(A::AbstractMatrix{T}, B::AbstractMatrix{S}) = Ac_mul_Bc!(similar(B, promote_op(*,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::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic_matmatmul!(C, 'C', 'C', A, B) Ac_mul_Bt!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic_matmatmul!(C, 'C', 'T', A, B) @@ -424,7 +423,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(*, arithtype(T), arithtype(S)), mA, nB) + C = similar(B, promote_op(*,arithtype(T),arithtype(S)), mA, nB) generic_matmatmul!(C, tA, tB, A, B) end @@ -618,7 +617,7 @@ end # multiply 2x2 matrices function matmul2x2{T,S}(tA, tB, A::AbstractMatrix{T}, B::AbstractMatrix{S}) - matmul2x2!(similar(B, promote_op(*, T, S), 2, 2), tA, tB, A, B) + matmul2x2!(similar(B, promote_op(*,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}) @@ -647,7 +646,7 @@ end # Multiply 3x3 matrices function matmul3x3{T,S}(tA, tB, A::AbstractMatrix{T}, B::AbstractMatrix{S}) - matmul3x3!(similar(B, promote_op(*, T, S), 3, 3), tA, tB, A, B) + matmul3x3!(similar(B, promote_op(*,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/number.jl b/base/number.jl index 42ffb708736ee..d2d3270f1cfc4 100644 --- a/base/number.jl +++ b/base/number.jl @@ -63,4 +63,16 @@ zero{T<:Number}(::Type{T}) = convert(T,0) one(x::Number) = oftype(x,1) one{T<:Number}(::Type{T}) = convert(T,1) +promote_op{R,S<:Number}(::Type{R}, ::Type{S}) = (@_pure_meta; R) # to fix ambiguities +function promote_op{T<:Number}(op, ::Type{T}) + S = typeof(op(one(T))) + # preserve the most general (abstract) type when possible + return isleaftype(T) ? S : typejoin(S, T) +end +function promote_op{R<:Number,S<:Number}(op, ::Type{R}, ::Type{S}) + T = typeof(op(one(R), one(S))) + # preserve the most general (abstract) type when possible + return isleaftype(R) && isleaftype(S) ? T : typejoin(R, S, T) +end + factorial(x::Number) = gamma(x + 1) # fallback for x not Integer diff --git a/base/pkg/resolve/fieldvalue.jl b/base/pkg/resolve/fieldvalue.jl index fe175ce356b0b..a3666388d35a7 100644 --- a/base/pkg/resolve/fieldvalue.jl +++ b/base/pkg/resolve/fieldvalue.jl @@ -42,6 +42,7 @@ Base.typemin(::Type{FieldValue}) = (x=typemin(Int); y=typemin(VersionWeight); Fi Base.:-(a::FieldValue, b::FieldValue) = FieldValue(a.l0-b.l0, a.l1-b.l1, a.l2-b.l2, a.l3-b.l3, a.l4-b.l4) Base.:+(a::FieldValue, b::FieldValue) = FieldValue(a.l0+b.l0, a.l1+b.l1, a.l2+b.l2, a.l3+b.l3, a.l4+b.l4) +Base.promote_op(::Union{typeof(+), typeof(-)}, ::Type{FieldValue}, ::Type{FieldValue}) = FieldValue function Base.isless(a::FieldValue, b::FieldValue) a.l0 < b.l0 && return true diff --git a/base/process.jl b/base/process.jl index 88d51cb4f1634..55495765febe5 100644 --- a/base/process.jl +++ b/base/process.jl @@ -289,7 +289,7 @@ type Process <: AbstractPipe typemin(fieldtype(Process, :termsignal)), false, Condition(), false, Condition()) finalizer(this, uvfinalize) - return this + this end end pipe_reader(p::Process) = p.out @@ -325,12 +325,9 @@ function _jl_spawn(cmd, argv, loop::Ptr{Void}, pp::Process, end function uvfinalize(proc::Process) - if proc.handle != C_NULL - disassociate_julia_struct(proc.handle) - ccall(:jl_close_uv, Void, (Ptr{Void},), proc.handle) - proc.handle = C_NULL - end - nothing + proc.handle != C_NULL && ccall(:jl_close_uv, Void, (Ptr{Void},), proc.handle) + disassociate_julia_struct(proc) + proc.handle = C_NULL end function uv_return_spawn(p::Ptr{Void}, exit_status::Int64, termsignal::Int32) @@ -339,9 +336,7 @@ function uv_return_spawn(p::Ptr{Void}, exit_status::Int64, termsignal::Int32) proc = unsafe_pointer_to_objref(data)::Process proc.exitcode = exit_status proc.termsignal = termsignal - if isa(proc.exitcb, Function) - proc.exitcb(proc, exit_status, termsignal) - end + if isa(proc.exitcb, Function) proc.exitcb(proc, exit_status, termsignal) end ccall(:jl_close_uv, Void, (Ptr{Void},), proc.handle) notify(proc.exitnotify) nothing @@ -349,9 +344,7 @@ end function _uv_hook_close(proc::Process) proc.handle = C_NULL - if isa(proc.closecb, Function) - proc.closecb(proc) - end + if isa(proc.closecb, Function) proc.closecb(proc) end notify(proc.closenotify) end diff --git a/base/promotion.jl b/base/promotion.jl index 449dae5add81a..778de13c004c9 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -217,38 +217,13 @@ max(x::Real, y::Real) = max(promote(x,y)...) min(x::Real, y::Real) = min(promote(x,y)...) minmax(x::Real, y::Real) = minmax(promote(x, y)...) -# "Promotion" that takes a function into account. These are meant to be -# used mainly by broadcast methods, so it is advised against overriding them -if isdefined(Core, :Inference) - function _promote_op(op, T::Type) - G = Tuple{Generator{Tuple{T},typeof(op)}} - R = Core.Inference.return_type(first, G) - return isleaftype(R) ? R : Any - end - function _promote_op(op, R::Type, S::Type) - F = typeof(a -> op(a...)) - G = Tuple{Generator{Zip2{Tuple{R},Tuple{S}},F}} - T = Core.Inference.return_type(first, G) - return isleaftype(T) ? T : Any - end -else - _promote_op(::Any...) = (@_pure_meta; Any) -end -_default_type(T::Type) = (@_pure_meta; T) - -promote_op(::Any...) = (@_pure_meta; Any) -promote_op(T::Type, ::Any) = (@_pure_meta; T) -promote_op(T::Type, ::Type) = (@_pure_meta; T) # To handle ambiguities -# Promotion that tries to preserve non-concrete types -function promote_op(f, S::Type) - T = _promote_op(f, _default_type(S)) - return isleaftype(S) ? T : typejoin(S, T) -end -function promote_op(f, R::Type, S::Type) - T = _promote_op(f, _default_type(R), _default_type(S)) - isleaftype(R) && return isleaftype(S) ? T : typejoin(S, T) - return isleaftype(S) ? typejoin(R, T) : typejoin(R, S, T) -end +# "Promotion" that takes a function into account. You can override this +# 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}(::typeof(*), ::Type{R}, ::Type{S}) = MyType{multype(R,S)} +promote_op(::Any) = (@_pure_meta; Bottom) +promote_op(::Any, ::Any, ::Any...) = (@_pure_meta; Any) +promote_op{T}(::Type{T}, ::Any) = (@_pure_meta; T) ## catch-alls to prevent infinite recursion when definitions are missing ## diff --git a/base/socket.jl b/base/socket.jl index 8365f219fe711..29dd8d6caa3aa 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -281,7 +281,7 @@ function TCPSocket() throw(UVError("failed to create tcp socket",err)) end this.status = StatusInit - return this + this end type TCPServer <: LibuvServer @@ -312,7 +312,7 @@ function TCPServer() throw(UVError("failed to create tcp server",err)) end this.status = StatusInit - return this + this end isreadable(io::TCPSocket) = isopen(io) || nb_available(io) > 0 @@ -365,11 +365,19 @@ function UDPSocket() throw(UVError("failed to create udp socket",err)) end this.status = StatusInit - return this + this end show(io::IO, stream::UDPSocket) = print(io, typeof(stream), "(", uv_status_string(stream), ")") +function uvfinalize(uv::Union{TTY,PipeEndpoint,PipeServer,TCPServer,TCPSocket,UDPSocket}) + if (uv.status != StatusUninit && uv.status != StatusInit) + close(uv) + end + disassociate_julia_struct(uv) + uv.handle = C_NULL +end + function _uv_hook_close(sock::UDPSocket) sock.handle = C_NULL sock.status = StatusClosed diff --git a/base/stream.jl b/base/stream.jl index 733bba8d450ce..d649b88116736 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -322,26 +322,9 @@ function wait_close(x::Union{LibuvStream, LibuvServer}) end function close(stream::Union{LibuvStream, LibuvServer}) - if isopen(stream) - if stream.status != StatusClosing - ccall(:jl_close_uv, Void, (Ptr{Void},), stream.handle) - stream.status = StatusClosing - end - if uv_handle_data(stream) != C_NULL - stream_wait(stream, stream.closenotify) - end - end - nothing -end - -function uvfinalize(uv::Union{LibuvStream, LibuvServer}) - if uv.handle != C_NULL - disassociate_julia_struct(uv.handle) # not going to call the usual close hooks - if uv.status != StatusUninit && uv.status != StatusInit - close(uv) - uv.handle = C_NULL - uv.status = StatusClosed - end + if isopen(stream) && stream.status != StatusClosing + ccall(:jl_close_uv,Void, (Ptr{Void},), stream.handle) + stream.status = StatusClosing end nothing end @@ -489,10 +472,8 @@ function uv_readcb(handle::Ptr{Void}, nread::Cssize_t, buf::Ptr{Void}) stream.status = StatusEOF # libuv called stop_reading already notify(stream.readnotify) notify(stream.closenotify) - elseif stream.status != StatusClosing - # begin shutdown of the stream - ccall(:jl_close_uv, Void, (Ptr{Void},), stream.handle) - stream.status = StatusClosing + else + close(stream) end else # This is a fatal connection error. Shutdown requests as per the usual @@ -1038,8 +1019,6 @@ function close(s::BufferStream) notify(s.close_c; all=true) nothing end -uvfinalize(s::BufferStream) = nothing - read(s::BufferStream, ::Type{UInt8}) = (wait_readnb(s, 1); read(s.buffer, UInt8)) unsafe_read(s::BufferStream, a::Ptr{UInt8}, nb::UInt) = (wait_readnb(s, Int(nb)); unsafe_read(s.buffer, a, nb)) nb_available(s::BufferStream) = nb_available(s.buffer) diff --git a/base/version.jl b/base/version.jl index 219d1e08c6774..2a5b37e2718f5 100644 --- a/base/version.jl +++ b/base/version.jl @@ -236,7 +236,7 @@ function banner(io::IO = STDOUT) commit = GIT_VERSION_INFO.commit_short if distance == 0 - commit_string = "Commit $(commit) ($(days) $(unit) old master)" + commit_string = "Commit $(commit) ($(days) $(unit) old release-0.5)" else branch = GIT_VERSION_INFO.branch commit_string = "$(branch)/$(commit) (fork: $(distance) commits, $(days) $(unit))" diff --git a/base/version_git.sh b/base/version_git.sh index ebcd0965a7587..9a04d2224a9ec 100644 --- a/base/version_git.sh +++ b/base/version_git.sh @@ -68,8 +68,8 @@ if [ $(git describe --tags --exact-match 2> /dev/null) ]; then else tagged_commit="false" fi -fork_master_distance=$(git rev-list HEAD ^"$(echo $origin)master" | wc -l | sed -e 's/[^[:digit:]]//g') -fork_master_timestamp=$(git show -s $(git merge-base HEAD $(echo $origin)master) --format=format:"%ct") +fork_master_distance=$(git rev-list HEAD ^"$(echo $origin)release-0.5" | wc -l | sed -e 's/[^[:digit:]]//g') +fork_master_timestamp=$(git show -s $(git merge-base HEAD $(echo $origin)release-0.5) --format=format:"%ct") # Check for errrors and emit default value for missing numbers. if [ -z "$build_number" ]; then diff --git a/deps/checksums/libuv-cb6d0f875a5b8ca30cba45c0c1ef7442c87c1e68.tar.gz/md5 b/deps/checksums/libuv-cb6d0f875a5b8ca30cba45c0c1ef7442c87c1e68.tar.gz/md5 deleted file mode 100644 index 793f153e26212..0000000000000 --- a/deps/checksums/libuv-cb6d0f875a5b8ca30cba45c0c1ef7442c87c1e68.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -c6a019d79d20eabc39619a04961c9a3b diff --git a/deps/checksums/libuv-cb6d0f875a5b8ca30cba45c0c1ef7442c87c1e68.tar.gz/sha512 b/deps/checksums/libuv-cb6d0f875a5b8ca30cba45c0c1ef7442c87c1e68.tar.gz/sha512 deleted file mode 100644 index f3f1ec9dca483..0000000000000 --- a/deps/checksums/libuv-cb6d0f875a5b8ca30cba45c0c1ef7442c87c1e68.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -478ab473244b01bef344892a75e09fef50da8fb1a7212e0257c53f3223de4fde5f6bd449eef34bc1f025481c7d9f854002acb6eb203b447a50a34bae4ad9dee4 diff --git a/deps/checksums/libuv-ecbd6eddfac4940ab8db57c73166a7378563ebd3.tar.gz/md5 b/deps/checksums/libuv-ecbd6eddfac4940ab8db57c73166a7378563ebd3.tar.gz/md5 new file mode 100644 index 0000000000000..6dfbbd2a475fb --- /dev/null +++ b/deps/checksums/libuv-ecbd6eddfac4940ab8db57c73166a7378563ebd3.tar.gz/md5 @@ -0,0 +1 @@ +7248e38acefd92761c54640622357b7b diff --git a/deps/checksums/libuv-ecbd6eddfac4940ab8db57c73166a7378563ebd3.tar.gz/sha512 b/deps/checksums/libuv-ecbd6eddfac4940ab8db57c73166a7378563ebd3.tar.gz/sha512 new file mode 100644 index 0000000000000..e04d388782eba --- /dev/null +++ b/deps/checksums/libuv-ecbd6eddfac4940ab8db57c73166a7378563ebd3.tar.gz/sha512 @@ -0,0 +1 @@ +2fad17bddc568125d50ce50b7f27aa2de4380400589043d74b180883c96070c2dcad93557f2f5f5416cc297de3a66b35ec8942bd33d8ef1bb22744dad60b760d diff --git a/deps/libuv.version b/deps/libuv.version index 51f79989c5fc3..efe634777261b 100644 --- a/deps/libuv.version +++ b/deps/libuv.version @@ -1,2 +1,2 @@ LIBUV_BRANCH=julia-uv1.9.0 -LIBUV_SHA1=cb6d0f875a5b8ca30cba45c0c1ef7442c87c1e68 +LIBUV_SHA1=ecbd6eddfac4940ab8db57c73166a7378563ebd3 diff --git a/doc/devdocs/promote-op.rst b/doc/devdocs/promote-op.rst new file mode 100644 index 0000000000000..53a5a93768549 --- /dev/null +++ b/doc/devdocs/promote-op.rst @@ -0,0 +1,36 @@ +.. currentmodule:: Base + +.. _devdocs-promote-op: + +Operator-sensitive promotion +============================ + +In certain cases, the :ref:`simple rules for promotion +` may not be sufficient. For example, consider a +type that can represent an object with physical units, here restricted +to a single unit like "meter":: + + immutable MeterUnits{T,P} <: Number + val::T + end + MeterUnits{T}(val::T, pow::Int) = MeterUnits{T,pow}(val) + + 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 + +Now let's define the operations ``+`` and ``*`` for these objects: +``m+m`` should have the type of ``m`` but ``m*m`` should have the type +of ``m2``. When the result type depends on the operation, and not +just the input types, ``promote_rule`` will be inadequate. + +Fortunately, it's possible to provide such definitions via ``promote_op``:: + + Base.promote_op{R,S}(::typeof(+), ::Type{MeterUnits{R,1}}, ::Type{MeterUnits{S,1}}) = MeterUnits{promote_type(R,S),1} + Base.promote_op{R,S}(::typeof(*), ::Type{MeterUnits{R,1}}, ::Type{MeterUnits{S,1}}) = MeterUnits{promote_type(R,S),2} + Base.promote_op{R,S}(::typeof(.*), ::Type{MeterUnits{R,1}}, ::Type{MeterUnits{S,1}}) = MeterUnits{promote_type(R,S),2} + +The first one defines the promotion rule for ``+``, and the second one +for ``*``. + +It's worth noting that as julia's internal representation of functions +evolves, this interface may change in a future version of Julia. diff --git a/src/init.c b/src/init.c index a2d74fe60cc91..cb4758b8c56c0 100644 --- a/src/init.c +++ b/src/init.c @@ -217,7 +217,6 @@ static struct uv_shutdown_queue_item *next_shutdown_queue_item(struct uv_shutdow void jl_init_timing(void); void jl_destroy_timing(void); -void jl_uv_call_close_callback(jl_value_t *val); JL_DLLEXPORT void jl_atexit_hook(int exitcode) { @@ -271,13 +270,6 @@ JL_DLLEXPORT void jl_atexit_hook(int exitcode) continue; } switch(handle->type) { - case UV_PROCESS: - // cause Julia to forget about the Process object - if (handle->data) - jl_uv_call_close_callback((jl_value_t*)handle->data); - // and make libuv think it is already dead - ((uv_process_t*)handle)->pid = 0; - // fall-through case UV_TTY: case UV_UDP: case UV_TCP: @@ -291,6 +283,7 @@ JL_DLLEXPORT void jl_atexit_hook(int exitcode) case UV_PREPARE: case UV_CHECK: case UV_SIGNAL: + case UV_PROCESS: case UV_FILE: // These will be shutdown as appropriate by jl_close_uv jl_close_uv(handle); diff --git a/src/jl_uv.c b/src/jl_uv.c index 2c9f312ae682a..3cdc6c61340c1 100644 --- a/src/jl_uv.c +++ b/src/jl_uv.c @@ -78,17 +78,17 @@ void jl_init_signal_async(void) } #endif -void jl_uv_call_close_callback(jl_value_t *val) +static void jl_uv_call_close_callback(jl_value_t *val) { jl_value_t *args[2]; args[0] = jl_get_global(jl_base_relative_to(((jl_datatype_t*)jl_typeof(val))->name->module), jl_symbol("_uv_hook_close")); // topmod(typeof(val))._uv_hook_close args[1] = val; assert(args[0]); - jl_apply(args, 2); // TODO: wrap in try-catch? + jl_apply(args, 2); } -static void jl_uv_closeHandle(uv_handle_t *handle) +JL_DLLEXPORT void jl_uv_closeHandle(uv_handle_t *handle) { // if the user killed a stdio handle, // revert back to direct stdio FILE* writes @@ -107,7 +107,7 @@ static void jl_uv_closeHandle(uv_handle_t *handle) free(handle); } -static void jl_uv_shutdownCallback(uv_shutdown_t *req, int status) +JL_DLLEXPORT void jl_uv_shutdownCallback(uv_shutdown_t *req, int status) { /* * This happens if the remote machine closes the connecition while we're @@ -180,21 +180,8 @@ JL_DLLEXPORT int jl_init_pipe(uv_pipe_t *pipe, int writable, int readable, return err; } -static void jl_proc_exit_cleanup(uv_process_t *process, int64_t exit_status, int term_signal) -{ - uv_close((uv_handle_t*)process, (uv_close_cb)&free); -} - JL_DLLEXPORT void jl_close_uv(uv_handle_t *handle) { - if (handle->type == UV_PROCESS && ((uv_process_t*)handle)->pid != 0) { - // take ownership of this handle, - // so we can waitpid for the resource to exit and avoid leaving zombies - assert(handle->data == NULL); // make sure Julia has forgotten about it already - ((uv_process_t*)handle)->exit_cb = jl_proc_exit_cleanup; - return; - } - if (handle->type == UV_FILE) { uv_fs_t req; jl_uv_file_t *fd = (jl_uv_file_t*)handle; @@ -243,7 +230,7 @@ JL_DLLEXPORT void jl_close_uv(uv_handle_t *handle) JL_DLLEXPORT void jl_forceclose_uv(uv_handle_t *handle) { - uv_close(handle, &jl_uv_closeHandle); + uv_close(handle,&jl_uv_closeHandle); } JL_DLLEXPORT void jl_uv_associate_julia_struct(uv_handle_t *handle, diff --git a/test/arrayops.jl b/test/arrayops.jl index 0d735436338c3..bd66b597e1566 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -1424,6 +1424,7 @@ b = rand(6,7) @test_throws ArgumentError copy!(a,2:3,1:3,b,1:5,2:7) @test_throws ArgumentError Base.copy_transpose!(a,2:3,1:3,b,1:5,2:7) +# return type declarations (promote_op) module RetTypeDecl using Base.Test import Base: +, *, .*, convert @@ -1441,6 +1442,7 @@ module RetTypeDecl (*){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) convert{T,pow}(::Type{MeterUnits{T,pow}}, y::Real) = MeterUnits{T,pow}(convert(T,y)) + Base.promote_op{R,S}(::typeof(*), ::Type{MeterUnits{R,1}}, ::Type{MeterUnits{S,1}}) = MeterUnits{promote_type(R,S),2} @test @inferred(m+[m,m]) == [m+m,m+m] @test @inferred([m,m]+m) == [m+m,m+m] diff --git a/test/broadcast.jl b/test/broadcast.jl index 7cc1ceffa500f..f14788413f05a 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -225,11 +225,12 @@ let x = sin.(1:10) @test sin.(atan2.(x, 3.7)) == broadcast(x -> sin(atan2(x,3.7)), x) @test atan2.(x, 3.7) == broadcast(x -> atan2(x,3.7), x) == broadcast(atan2, x, 3.7) end -# Use side effects to check for loop fusion. +# Use side effects to check for loop fusion. Note that, due to #17314, +# a broadcasted function is currently called an extra time with an argument 1. let g = Int[] - f17300(x) = begin; push!(g, x); x+2; end + f17300(x) = begin; push!(g, x); x+1; end f17300.(f17300.(f17300.(1:3))) - @test g == [1,3,5, 2,4,6, 3,5,7] + @test g == [1,2,3, 1,2,3, 2,3,4, 3,4,5] end # fusion with splatted args: let x = sin.(1:10), a = [x] @@ -294,15 +295,3 @@ end let foo = [[1,2,3],[4,5,6],[7,8,9]] @test max.(foo...) == broadcast(max, foo...) == [7,8,9] end - -# Issue 17314 -@test broadcast(x->log(log(log(x))), [1000]) == [log(log(log(1000)))] -let f17314 = x -> x < 0 ? false : x - @test eltype(broadcast(f17314, 1:3)) === Int - @test eltype(broadcast(f17314, -1:1)) === Integer - @test eltype(broadcast(f17314, Int[])) === Union{} -end -let io = IOBuffer() - broadcast(x->print(io,x), 1:5) # broadcast with side effects - @test takebuf_array(io) == [0x31,0x32,0x33,0x34,0x35] -end diff --git a/test/linalg/matmul.jl b/test/linalg/matmul.jl index 4755f1d9ddd64..44bb9a6afa85b 100644 --- a/test/linalg/matmul.jl +++ b/test/linalg/matmul.jl @@ -320,10 +320,10 @@ end immutable RootInt i::Int end -import Base: *, transpose +import Base: *, transpose, promote_op (*)(x::RootInt, y::RootInt) = x.i*y.i transpose(x::RootInt) = x -@test Base.promote_op(*, RootInt, RootInt) === Int +promote_op(::typeof(*), ::Type{RootInt}, ::Type{RootInt}) = Int a = [RootInt(3)] C = [0] diff --git a/test/numbers.jl b/test/numbers.jl index a0ccc138e776f..8ef819c0685ae 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -2791,21 +2791,21 @@ let types = (Base.BitInteger_types..., BigInt, Bool, Complex{Int}, Complex{UInt}, Complex32, Complex64, Complex128) for S in types for op in (+, -) - T = @inferred Base._promote_op(op, S) + T = @inferred Base.promote_op(op, S) t = @inferred op(one(S)) @test T === typeof(t) end + end - for R in types - for op in (+, -, *, /, ^) - T = @inferred Base._promote_op(op, S, R) - t = @inferred op(one(S), one(R)) - @test T === typeof(t) - end + @test @inferred(Base.promote_op(!, Bool)) === Bool + + for R in types, S in types + for op in (+, -, *, /, ^) + T = @inferred Base.promote_op(op, R, S) + t = @inferred op(one(R), one(S)) + @test T === typeof(t) end end - - @test @inferred(Base._promote_op(!, Bool)) === Bool end let types = (Base.BitInteger_types..., BigInt, Bool, @@ -2813,23 +2813,23 @@ let types = (Base.BitInteger_types..., BigInt, Bool, Float16, Float32, Float64, BigFloat) for S in types, T in types for op in (<, >, <=, >=, (==)) - @test @inferred(Base._promote_op(op, S, T)) === Bool + @test @inferred(Base.promote_op(op, S, T)) === Bool end end end let types = (Base.BitInteger_types..., BigInt, Bool) for S in types - T = @inferred Base._promote_op(~, S) + T = @inferred Base.promote_op(~, S) t = @inferred ~one(S) @test T === typeof(t) + end - for R in types - for op in (&, |, <<, >>, (>>>), %, ÷) - T = @inferred Base._promote_op(op, S, R) - t = @inferred op(one(S), one(R)) - @test T === typeof(t) - end + for S in types, T in types + for op in (&, |, <<, >>, (>>>), %, ÷) + T = @inferred Base.promote_op(op, S, T) + t = @inferred op(one(S), one(T)) + @test T === typeof(t) end end end diff --git a/test/spawn.jl b/test/spawn.jl index 0040630cf2016..18433a6f83148 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -265,9 +265,9 @@ let bad = "bad\0name" end # issue #12829 -let out = Pipe(), echo = `$exename --startup-file=no -e 'print(STDOUT, " 1\t", readstring(STDIN))'`, ready = Condition(), t +let out = Pipe(), echo = `$exename --startup-file=no -e 'print(STDOUT, " 1\t", readstring(STDIN))'`, ready = Condition() @test_throws ArgumentError write(out, "not open error") - t = @async begin # spawn writer task + @async begin # spawn writer task open(echo, "w", out) do in1 open(echo, "w", out) do in2 notify(ready) @@ -282,13 +282,10 @@ let out = Pipe(), echo = `$exename --startup-file=no -e 'print(STDOUT, " 1\t", r @test isreadable(out) @test iswritable(out) close(out.in) - @test !isopen(out.in) - is_windows() || @test !isopen(out.out) # it takes longer to propagate EOF through the Windows event system @test_throws ArgumentError write(out, "now closed error") @test isreadable(out) @test !iswritable(out) - is_windows() && Base.process_events(false) # should be enough steps to fully propagate EOF now - @test !isopen(out) + @test isopen(out) end wait(ready) # wait for writer task to be ready before using `out` @test nb_available(out) == 0 @@ -311,7 +308,6 @@ let out = Pipe(), echo = `$exename --startup-file=no -e 'print(STDOUT, " 1\t", r @test isempty(read(out)) @test eof(out) @test desc == "Pipe(open => active, 0 bytes waiting)" - wait(t) end # issue #8529