Skip to content

Commit bcd089b

Browse files
committed
More promote_op fixes
1 parent 4e1ce13 commit bcd089b

9 files changed

+45
-46
lines changed

base/float.jl

+6
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,12 @@ promote_rule(::Type{Float32}, ::Type{Float16}) = Float32
196196
promote_rule(::Type{Float64}, ::Type{Float16}) = Float64
197197
promote_rule(::Type{Float64}, ::Type{Float32}) = Float64
198198

199+
promote_op{Op<:typeof(trunc),T<:Union{Float32,Float64}}(::Op, ::Type{Signed}, ::Type{T}) = Int
200+
promote_op{Op<:typeof(trunc),T<:Union{Float32,Float64}}(::Op, ::Type{Unsigned}, ::Type{T}) = UInt
201+
for f in (ceil, floor, round, trunc)
202+
@eval promote_op{Op<:$(typeof(f)),T}(::Op, ::Type{T}, ::Any) = T
203+
end
204+
199205
widen(::Type{Float16}) = Float32
200206
widen(::Type{Float32}) = Float64
201207

base/irrationals.jl

-4
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@ promote_rule{s}(::Type{Irrational{s}}, ::Type{Float32}) = Float32
1010
promote_rule{s,t}(::Type{Irrational{s}}, ::Type{Irrational{t}}) = Float64
1111
promote_rule{s,T<:Number}(::Type{Irrational{s}}, ::Type{T}) = promote_type(Float64,T)
1212

13-
promote_op{S<:Irrational,T<:Irrational}(::Any, ::Type{S}, ::Type{T}) = Float64
14-
promote_op{S<:Irrational,T<:Number}(::Any, ::Type{S}, ::Type{T}) = promote_type(S, T)
15-
promote_op{S<:Irrational,T<:Number}(::Any, ::Type{T}, ::Type{S}) = promote_type(T, S)
16-
1713
convert(::Type{AbstractFloat}, x::Irrational) = Float64(x)
1814
convert(::Type{Float16}, x::Irrational) = Float16(Float32(x))
1915
convert{T<:Real}(::Type{Complex{T}}, x::Irrational) = convert(Complex{T}, convert(T,x))

base/number.jl

+8-13
Original file line numberDiff line numberDiff line change
@@ -63,21 +63,16 @@ zero{T<:Number}(::Type{T}) = convert(T,0)
6363
one(x::Number) = oftype(x,1)
6464
one{T<:Number}(::Type{T}) = convert(T,1)
6565

66-
promote_op{S<:Number,T}(op::Type{T}, ::Type{S}) = T # to fix ambiguities
67-
function promote_op{S<:Number}(op::Any, ::Type{S})
68-
R = typeof(op(one(S)))
69-
R <: S ? S : R # preserve the most general (abstract) type when possible
66+
promote_op{R,S<:Number}(::Type{R}, ::Type{S}) = (@_pure_meta; R) # to fix ambiguities
67+
function promote_op{T<:Number}(op, ::Type{T})
68+
S = typeof(op(one(T)))
69+
# preserve the most general (abstract) type when possible
70+
return isleaftype(T) ? S : typejoin(S, T)
7071
end
71-
function promote_op{S<:Number,T<:Number}(op::Any, ::Type{S}, ::Type{T})
72-
R = typeof(op(one(S), one(T)))
72+
function promote_op{R<:Number,S<:Number}(op, ::Type{R}, ::Type{S})
73+
T = typeof(op(one(R), one(S)))
7374
# preserve the most general (abstract) type when possible
74-
if T <: S && R <: S
75-
return S
76-
elseif S <: T && R <: T
77-
return T
78-
else
79-
return R
80-
end
75+
return isleaftype(R) & isleaftype(S) ? T : typejoin(R, S, T)
8176
end
8277

8378
factorial(x::Number) = gamma(x + 1) # fallback for x not Integer

base/operators.jl

+4
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ end
4343
==(T::TypeVar, S::Type) = false
4444
==(T::Type, S::TypeVar) = false
4545

46+
for op in (<, >, <=, >=, (==))
47+
@eval promote_op{Op<:$(typeof(op))}(::Op, ::Any, ::Any) = ($(Expr(:meta, :pure)); Bool)
48+
end
49+
4650
## comparison fallbacks ##
4751

4852
!=(x,y) = !(x==y)

base/parse.jl

+2
Original file line numberDiff line numberDiff line change
@@ -194,3 +194,5 @@ function parse(str::AbstractString; raise::Bool=true)
194194
end
195195
return ex
196196
end
197+
198+
promote_op{Op<:typeof(parse),T}(::Op, ::Type{T}, ::Any) = T

base/promotion.jl

+3-2
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,10 @@ minmax(x::Real, y::Real) = minmax(promote(x, y)...)
222222
# for the multiplication of two types,
223223
# promote_op{R<:MyType,S<:MyType}(::typeof(*), ::Type{R}, ::Type{S}) = MyType{multype(R,S)}
224224
promote_op(::Any) = (@_pure_meta; Bottom)
225-
promote_op(::Any, T) = (@_pure_meta; T)
225+
promote_op(::Any, ::Any) = (@_pure_meta; Any)
226+
promote_op(::Any, ::Any, ::Any) = (@_pure_meta; Any)
226227
promote_op{T}(::Type{T}, ::Any) = (@_pure_meta; T)
227-
promote_op{R,S}(::Any, ::Type{R}, ::Type{S}) = (@_pure_meta; promote_type(R, S))
228+
promote_op{Op<:typeof(convert),T}(::Op, ::Type{T}, ::Any) = (@_pure_meta, T)
228229
promote_op(op, T, S, U, V...) = (@_pure_meta; promote_op(op, T, promote_op(op, S, U, V...)))
229230

230231
## catch-alls to prevent infinite recursion when definitions are missing ##

test/arrayops.jl

+3-5
Original file line numberDiff line numberDiff line change
@@ -1404,7 +1404,7 @@ b = rand(6,7)
14041404
# return type declarations (promote_op)
14051405
module RetTypeDecl
14061406
using Base.Test
1407-
import Base: +, *, .*, zero, one
1407+
import Base: +, *, .*, convert
14081408

14091409
immutable MeterUnits{T,P} <: Number
14101410
val::T
@@ -1418,10 +1418,8 @@ module RetTypeDecl
14181418
(*){T,pow}(x::Int, y::MeterUnits{T,pow}) = MeterUnits{typeof(x*one(T)),pow}(x*y.val)
14191419
(*){T}(x::MeterUnits{T,1}, y::MeterUnits{T,1}) = MeterUnits{T,2}(x.val*y.val)
14201420
(.*){T}(x::MeterUnits{T,1}, y::MeterUnits{T,1}) = MeterUnits{T,2}(x.val*y.val)
1421-
zero{T,pow}(x::MeterUnits{T,pow}) = MeterUnits{T,pow}(zero(T))
1422-
one{T,pow}(x::MeterUnits{T,pow}) = MeterUnits{T,pow}(one(T))
1423-
zero{T,pow}(x::Type{MeterUnits{T,pow}}) = MeterUnits{T,pow}(zero(T))
1424-
one{T,pow}(x::Type{MeterUnits{T,pow}}) = MeterUnits{T,pow}(one(T))
1421+
convert{T,pow}(::Type{MeterUnits{T,pow}}, y::Real) = MeterUnits{T,pow}(convert(T,y))
1422+
Base.promote_op{R,S}(::typeof(*), ::Type{MeterUnits{R,1}}, ::Type{MeterUnits{S,1}}) = MeterUnits{promote_type(R,S),2}
14251423

14261424
@test @inferred(m+[m,m]) == [m+m,m+m]
14271425
@test @inferred([m,m]+m) == [m+m,m+m]

test/broadcast.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,9 @@ m = [1:2;]'
165165
@test @inferred([0,1.2].+reshape([0,-2],1,1,2)) == reshape([0 -2; 1.2 -0.8],2,1,2)
166166
rt = Base.return_types(.+, Tuple{Array{Float64, 3}, Array{Int, 1}})
167167
@test length(rt) == 1 && rt[1] == Array{Float64, 3}
168-
rt = Base.return_types(broadcast, Tuple{typeof(+), Array{Float64, 3}, Array{Int, 1}})
168+
rt = Base.return_types(broadcast, Tuple{Float64, Array{Int, 3}})
169169
@test length(rt) == 1 && rt[1] == Array{Float64, 3}
170-
rt = Base.return_types(broadcast!, Tuple{typeof(+), Array{Float64, 3}, Array{Float64, 3}, Array{Int, 1}})
170+
rt = Base.return_types(broadcast!, Tuple{Function, Array{Float64, 3}, Array{Float64, 3}, Array{Int, 1}})
171171
@test length(rt) == 1 && rt[1] == Array{Float64, 3}
172172

173173
# f.(args...) syntax (#15032)

test/numbers.jl

+17-20
Original file line numberDiff line numberDiff line change
@@ -2750,20 +2750,19 @@ let types = (Base.BitInteger_types..., BigInt, Bool,
27502750
Complex{Int}, Complex{UInt}, Complex32, Complex64, Complex128)
27512751
for S in types
27522752
for op in (+, -)
2753-
@test Base.promote_op(op, S) === typeof(op(one(S)))
2754-
@inferred Base.promote_op(op, S)
2755-
@inferred op(one(S))
2753+
T = @inferred Base.promote_op(op, S)
2754+
t = @inferred op(one(S))
2755+
@test T === typeof(t)
27562756
end
27572757
end
27582758

2759-
@test Base.promote_op(!, Bool) === Bool
2760-
@inferred Base.promote_op(!, Bool)
2759+
@test @inferred(Base.promote_op(!, Bool)) === Bool
27612760

2762-
for S in types, T in types
2763-
for op in (+, -, *, /, ^, (==))
2764-
@test Base.promote_op(op, S, T) === typeof(op(one(S), one(T)))
2765-
@inferred Base.promote_op(op, S, T)
2766-
@inferred op(one(S), one(T))
2761+
for R in types, S in types
2762+
for op in (+, -, *, /, ^)
2763+
T = @inferred Base.promote_op(op, R, S)
2764+
t = @inferred op(one(R), one(S))
2765+
@test T === typeof(t)
27672766
end
27682767
end
27692768
end
@@ -2772,26 +2771,24 @@ let types = (Base.BitInteger_types..., BigInt, Bool,
27722771
Rational{Int}, Rational{BigInt},
27732772
Float16, Float32, Float64, BigFloat)
27742773
for S in types, T in types
2775-
for op in (<, >, <=, >=)
2776-
@test Base.promote_op(op, S, T) === typeof(op(one(S), one(T)))
2777-
@inferred Base.promote_op(op, S, T)
2778-
@inferred op(one(S), one(T))
2774+
for op in (<, >, <=, >=, (==))
2775+
@test @inferred(Base.promote_op(op, S, T)) === Bool
27792776
end
27802777
end
27812778
end
27822779

27832780
let types = (Base.BitInteger_types..., BigInt, Bool)
27842781
for S in types
2785-
@test Base.promote_op(~, S) === typeof(~one(S))
2786-
@inferred Base.promote_op(~, S)
2787-
@inferred ~one(S)
2782+
T = @inferred Base.promote_op(~, S)
2783+
t = @inferred ~one(S)
2784+
@test T === typeof(t)
27882785
end
27892786

27902787
for S in types, T in types
27912788
for op in (&, |, <<, >>, (>>>), %, ÷)
2792-
@test Base.promote_op(op, S, T) === typeof(op(one(S), one(T)))
2793-
@inferred Base.promote_op(op, S, T)
2794-
@inferred op(one(S), one(T))
2789+
T = @inferred Base.promote_op(op, S, T)
2790+
t = @inferred op(one(S), one(T))
2791+
@test T === typeof(t)
27952792
end
27962793
end
27972794
end

0 commit comments

Comments
 (0)