Skip to content

Commit

Permalink
change more convert methods to constructors
Browse files Browse the repository at this point in the history
deprecate a few more sketchy `convert` methods
  • Loading branch information
JeffBezanson committed Aug 23, 2017
1 parent 9e1abb8 commit 5e9f675
Show file tree
Hide file tree
Showing 23 changed files with 189 additions and 173 deletions.
7 changes: 4 additions & 3 deletions base/Enums.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ function basetype end

abstract type Enum{T<:Integer} end

Base.convert(::Type{Integer}, x::Enum{T}) where {T<:Integer} = bitcast(T, x)
Base.convert(::Type{T}, x::Enum{T2}) where {T<:Integer,T2<:Integer} = convert(T, bitcast(T2, x))
Integer(x::Enum{T}) where {T<:Integer} = bitcast(T, x)
(::Type{T})(x::Enum{T2}) where {T<:Integer,T2<:Integer} = T(bitcast(T2, x))::T
Base.cconvert(::Type{T}, x::Enum{T2}) where {T<:Integer,T2<:Integer} = T(x)
Base.write(io::IO, x::Enum{T}) where {T<:Integer} = write(io, T(x))
Base.read(io::IO, ::Type{T}) where {T<:Enum} = T(read(io, Enums.basetype(T)))

Expand Down Expand Up @@ -106,7 +107,7 @@ macro enum(T, syms...)
blk = quote
# enum definition
Base.@__doc__(primitive type $(esc(typename)) <: Enum{$(basetype)} $(sizeof(basetype) * 8) end)
function Base.convert(::Type{$(esc(typename))}, x::Integer)
function $(esc(typename))(x::Integer)
$(membershiptest(:x, values)) || enum_argument_error($(Expr(:quote, typename)), x)
return bitcast($(esc(typename)), convert($(basetype), x))
end
Expand Down
6 changes: 0 additions & 6 deletions base/bool.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

## boolean conversions ##

convert(::Type{Bool}, x::Bool) = x
convert(::Type{Bool}, x::Float16) = x==0 ? false : x==1 ? true : throw(InexactError(:convert, Bool, x))
convert(::Type{Bool}, x::Real) = x==0 ? false : x==1 ? true : throw(InexactError(:convert, Bool, x))

# promote Bool to any other numeric type
promote_rule(::Type{Bool}, ::Type{T}) where {T<:Number} = T

Expand Down
17 changes: 17 additions & 0 deletions base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -605,4 +605,21 @@ Int(x::Ptr) = bitcast(Int, x)
UInt(x::Ptr) = bitcast(UInt, x)
Ptr{T}(x::Union{Int,UInt,Ptr}) where {T} = bitcast(Ptr{T}, x)

Signed(x::UInt8) = Int8(x)
Unsigned(x::Int8) = UInt8(x)
Signed(x::UInt16) = Int16(x)
Unsigned(x::Int16) = UInt16(x)
Signed(x::UInt32) = Int32(x)
Unsigned(x::Int32) = UInt32(x)
Signed(x::UInt64) = Int64(x)
Unsigned(x::Int64) = UInt64(x)
Signed(x::UInt128) = Int128(x)
Unsigned(x::Int128) = UInt128(x)

Signed(x::Union{Float32, Float64, Bool}) = Int(x)
Unsigned(x::Union{Float32, Float64, Bool}) = UInt(x)

Integer(x::Integer) = x
Integer(x::Real) = Signed(x)::Integer

ccall(:jl_set_istopmod, Void, (Any, Bool), Core, true)
7 changes: 4 additions & 3 deletions base/char.jl
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

convert(::Type{Char}, x::UInt32) = reinterpret(Char, x)
convert(::Type{Char}, x::Number) = Char(UInt32(x))
convert(::Type{UInt32}, x::Char) = reinterpret(UInt32, x)
Char(x::UInt32) = reinterpret(Char, x)
Char(x::Number) = Char(UInt32(x))
convert(::Type{Char}, x::Number) = Char(x)
UInt32(x::Char) = reinterpret(UInt32, x)
convert(::Type{T}, x::Char) where {T<:Number} = convert(T, UInt32(x))

rem(x::Char, ::Type{T}) where {T<:Number} = rem(UInt32(x), T)
Expand Down
11 changes: 5 additions & 6 deletions base/complex.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,12 @@ const Complex128 = Complex{Float64}
const Complex64 = Complex{Float32}
const Complex32 = Complex{Float16}

convert(::Type{Complex{T}}, x::Real) where {T<:Real} = Complex{T}(x,0)
convert(::Type{Complex{T}}, z::Complex) where {T<:Real} = Complex{T}(real(z),imag(z))
convert(::Type{T}, z::Complex) where {T<:Real} =
isreal(z) ? convert(T,real(z)) : throw(InexactError(:convert, T, z))
Complex{T}(x::Real) where {T<:Real} = Complex{T}(x,0)
Complex{T}(z::Complex) where {T<:Real} = Complex{T}(real(z),imag(z))
(::Type{T})(z::Complex) where {T<:Real} =
isreal(z) ? T(real(z))::T : throw(InexactError(Symbol(string(T)), T, z))

convert(::Type{Complex}, z::Complex) = z
convert(::Type{Complex}, x::Real) = Complex(x)
Complex(z::Complex) = z

promote_rule(::Type{Complex{T}}, ::Type{S}) where {T<:Real,S<:Real} =
Complex{promote_type(T,S)}
Expand Down
12 changes: 12 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1704,6 +1704,18 @@ export hex2num
@deprecate convert(::Type{String}, v::Vector{UInt8}) String(v)
@deprecate convert(::Type{S}, g::UTF8proc.GraphemeIterator) where {S<:AbstractString} convert(S, g.s)

@deprecate convert(::Type{UInt128}, u::Random.UUID) UInt128(u)
@deprecate convert(::Type{Random.UUID}, s::AbstractString) Random.UUID(s)
@deprecate convert(::Type{Libc.FILE}, s::IO) Libc.FILE(s)
@deprecate convert(::Type{VersionNumber}, v::Integer) VersionNumber(v)
@deprecate convert(::Type{VersionNumber}, v::Tuple) VersionNumber(v)
@deprecate convert(::Type{VersionNumber}, v::AbstractString) VersionNumber(v)

@deprecate (convert(::Type{Integer}, x::Enum{T}) where {T<:Integer}) Integer(x)
@deprecate (convert(::Type{T}, x::Enum{T2}) where {T<:Integer,T2<:Integer}) T(x)

@deprecate convert(dt::Type{<:Integer}, ip::IPAddr) dt(ip)

# issue #5148, PR #23259
# warning for `const` on locals should be changed to an error in julia-syntax.scm

Expand Down
68 changes: 36 additions & 32 deletions base/float.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ A not-a-number value of type [`Float64`](@ref).
const NaN = NaN64

## conversions to floating-point ##
convert(::Type{Float16}, x::Integer) = convert(Float16, convert(Float32, x))
Float16(x::Integer) = convert(Float16, convert(Float32, x))
for t in (Int8, Int16, Int32, Int64, Int128, UInt8, UInt16, UInt32, UInt64, UInt128)
@eval promote_rule(::Type{Float16}, ::Type{$t}) = Float16
end
Expand All @@ -54,27 +54,28 @@ promote_rule(::Type{Float16}, ::Type{Bool}) = Float16
for t1 in (Float32, Float64)
for st in (Int8, Int16, Int32, Int64)
@eval begin
convert(::Type{$t1}, x::($st)) = sitofp($t1, x)
(::Type{$t1})(x::($st)) = sitofp($t1, x)
promote_rule(::Type{$t1}, ::Type{$st}) = $t1
end
end
for ut in (Bool, UInt8, UInt16, UInt32, UInt64)
@eval begin
convert(::Type{$t1}, x::($ut)) = uitofp($t1, x)
(::Type{$t1})(x::($ut)) = uitofp($t1, x)
promote_rule(::Type{$t1}, ::Type{$ut}) = $t1
end
end
end
convert(::Type{Integer}, x::Float16) = convert(Integer, Float32(x))
convert(::Type{T}, x::Float16) where {T<:Integer} = convert(T, Float32(x))
Integer(x::Float16) = Integer(Float32(x))
(::Type{T})(x::Float16) where {T<:Integer} = T(Float32(x))

Bool(x::Real) = x==0 ? false : x==1 ? true : throw(InexactError(:Bool, Bool, x))

promote_rule(::Type{Float64}, ::Type{UInt128}) = Float64
promote_rule(::Type{Float64}, ::Type{Int128}) = Float64
promote_rule(::Type{Float32}, ::Type{UInt128}) = Float32
promote_rule(::Type{Float32}, ::Type{Int128}) = Float32

function convert(::Type{Float64}, x::UInt128)
function Float64(x::UInt128)
x == 0 && return 0.0
n = 128-leading_zeros(x) # ndigits0z(x,2)
if n <= 53
Expand All @@ -88,7 +89,7 @@ function convert(::Type{Float64}, x::UInt128)
reinterpret(Float64, d + y)
end

function convert(::Type{Float64}, x::Int128)
function Float64(x::Int128)
x == 0 && return 0.0
s = ((x >>> 64) % UInt64) & 0x8000_0000_0000_0000 # sign bit
x = abs(x) % UInt128
Expand All @@ -104,7 +105,7 @@ function convert(::Type{Float64}, x::Int128)
reinterpret(Float64, s | d + y)
end

function convert(::Type{Float32}, x::UInt128)
function Float32(x::UInt128)
x == 0 && return 0f0
n = 128-leading_zeros(x) # ndigits0z(x,2)
if n <= 24
Expand All @@ -118,7 +119,7 @@ function convert(::Type{Float32}, x::UInt128)
reinterpret(Float32, d + y)
end

function convert(::Type{Float32}, x::Int128)
function Float32(x::Int128)
x == 0 && return 0f0
s = ((x >>> 96) % UInt32) & 0x8000_0000 # sign bit
x = abs(x) % UInt128
Expand All @@ -134,7 +135,7 @@ function convert(::Type{Float32}, x::Int128)
reinterpret(Float32, s | d + y)
end

function convert(::Type{Float16}, val::Float32)
function Float16(val::Float32)
f = reinterpret(UInt32, val)
if isnan(val)
t = 0x8000 (0x8000 & ((f >> 0x10) % UInt16))
Expand All @@ -157,7 +158,7 @@ function convert(::Type{Float16}, val::Float32)
reinterpret(Float16, h)
end

function convert(::Type{Float32}, val::Float16)
function Float32(val::Float16)
local ival::UInt32 = reinterpret(UInt16, val)
local sign::UInt32 = (ival & 0x8000) >> 15
local exp::UInt32 = (ival & 0x7c00) >> 10
Expand Down Expand Up @@ -235,33 +236,36 @@ for i = 0:255
shifttable[i|0x100+1] = 13
end
end

#convert(::Type{Float16}, x::Float32) = fptrunc(Float16, x)
convert(::Type{Float32}, x::Float64) = fptrunc(Float32, x)
convert(::Type{Float16}, x::Float64) = convert(Float16, convert(Float32, x))
Float32(x::Float64) = fptrunc(Float32, x)
Float16(x::Float64) = Float16(Float32(x))

#convert(::Type{Float32}, x::Float16) = fpext(Float32, x)
convert(::Type{Float64}, x::Float32) = fpext(Float64, x)
convert(::Type{Float64}, x::Float16) = convert(Float64, convert(Float32, x))

convert(::Type{AbstractFloat}, x::Bool) = convert(Float64, x)
convert(::Type{AbstractFloat}, x::Int8) = convert(Float64, x)
convert(::Type{AbstractFloat}, x::Int16) = convert(Float64, x)
convert(::Type{AbstractFloat}, x::Int32) = convert(Float64, x)
convert(::Type{AbstractFloat}, x::Int64) = convert(Float64, x) # LOSSY
convert(::Type{AbstractFloat}, x::Int128) = convert(Float64, x) # LOSSY
convert(::Type{AbstractFloat}, x::UInt8) = convert(Float64, x)
convert(::Type{AbstractFloat}, x::UInt16) = convert(Float64, x)
convert(::Type{AbstractFloat}, x::UInt32) = convert(Float64, x)
convert(::Type{AbstractFloat}, x::UInt64) = convert(Float64, x) # LOSSY
convert(::Type{AbstractFloat}, x::UInt128) = convert(Float64, x) # LOSSY
Float64(x::Float32) = fpext(Float64, x)
Float64(x::Float16) = Float64(Float32(x))

AbstractFloat(x::Bool) = Float64(x)
AbstractFloat(x::Int8) = Float64(x)
AbstractFloat(x::Int16) = Float64(x)
AbstractFloat(x::Int32) = Float64(x)
AbstractFloat(x::Int64) = Float64(x) # LOSSY
AbstractFloat(x::Int128) = Float64(x) # LOSSY
AbstractFloat(x::UInt8) = Float64(x)
AbstractFloat(x::UInt16) = Float64(x)
AbstractFloat(x::UInt32) = Float64(x)
AbstractFloat(x::UInt64) = Float64(x) # LOSSY
AbstractFloat(x::UInt128) = Float64(x) # LOSSY

Bool(x::Float16) = x==0 ? false : x==1 ? true : throw(InexactError(:Bool, Bool, x))

"""
float(x)
Convert a number or array to a floating point data type.
When passed a string, this function is equivalent to `parse(Float64, x)`.
"""
float(x) = convert(AbstractFloat, x)
float(x) = AbstractFloat(x)

"""
float(T::Type)
Expand Down Expand Up @@ -675,11 +679,11 @@ for Ti in (Int8, Int16, Int32, Int64, Int128, UInt8, UInt16, UInt32, UInt64, UIn
throw(InexactError(:trunc, $Ti, x))
end
end
function convert(::Type{$Ti}, x::$Tf)
function (::Type{$Ti})(x::$Tf)
if ($(Tf(typemin(Ti))) <= x <= $(Tf(typemax(Ti)))) && (trunc(x) == x)
return unsafe_trunc($Ti,x)
else
throw(InexactError(:convert, $Ti, x))
throw(InexactError($(Expr(:quote,Ti.name.name)), $Ti, x))
end
end
end
Expand All @@ -696,11 +700,11 @@ for Ti in (Int8, Int16, Int32, Int64, Int128, UInt8, UInt16, UInt32, UInt64, UIn
throw(InexactError(:trunc, $Ti, x))
end
end
function convert(::Type{$Ti}, x::$Tf)
function (::Type{$Ti})(x::$Tf)
if ($(Tf(typemin(Ti))) <= x < $(Tf(typemax(Ti)))) && (trunc(x) == x)
return unsafe_trunc($Ti,x)
else
throw(InexactError(:convert, $Ti, x))
throw(InexactError($(Expr(:quote,Ti.name.name)), $Ti, x))
end
end
end
Expand Down
36 changes: 18 additions & 18 deletions base/gmp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ widen(::Type{BigInt}) = BigInt

signed(x::BigInt) = x

convert(::Type{BigInt}, x::BigInt) = x
BigInt(x::BigInt) = x

hastypemax(::Type{BigInt}) = false

Expand Down Expand Up @@ -263,14 +263,14 @@ function tryparse_internal(::Type{BigInt}, s::AbstractString, startpos::Int, end
Nullable(flipsign!(z, sgn))
end

convert(::Type{BigInt}, x::Union{Clong,Int32}) = MPZ.set_si(x)
convert(::Type{BigInt}, x::Union{Culong,UInt32}) = MPZ.set_ui(x)
convert(::Type{BigInt}, x::Bool) = BigInt(UInt(x))
BigInt(x::Union{Clong,Int32}) = MPZ.set_si(x)
BigInt(x::Union{Culong,UInt32}) = MPZ.set_ui(x)
BigInt(x::Bool) = BigInt(UInt(x))

unsafe_trunc(::Type{BigInt}, x::Union{Float32,Float64}) = MPZ.set_d(x)

function convert(::Type{BigInt}, x::Union{Float32,Float64})
isinteger(x) || throw(InexactError(:convert, BigInt, x))
function BigInt(x::Union{Float32,Float64})
isinteger(x) || throw(InexactError(:BigInt, BigInt, x))
unsafe_trunc(BigInt,x)
end

Expand All @@ -279,10 +279,10 @@ function trunc(::Type{BigInt}, x::Union{Float32,Float64})
unsafe_trunc(BigInt,x)
end

convert(::Type{BigInt}, x::Float16) = BigInt(Float64(x))
convert(::Type{BigInt}, x::Float32) = BigInt(Float64(x))
BigInt(x::Float16) = BigInt(Float64(x))
BigInt(x::Float32) = BigInt(Float64(x))

function convert(::Type{BigInt}, x::Integer)
function BigInt(x::Integer)
if x < 0
if typemin(Clong) <= x
return BigInt(convert(Clong,x))
Expand Down Expand Up @@ -324,26 +324,26 @@ function rem(x::BigInt, ::Type{T}) where T<:Union{Unsigned,Signed}
flipsign(u, x.size)
end

rem(x::Integer, ::Type{BigInt}) = convert(BigInt, x)
rem(x::Integer, ::Type{BigInt}) = BigInt(x)

function convert(::Type{T}, x::BigInt) where T<:Unsigned
function (::Type{T})(x::BigInt) where T<:Unsigned
if sizeof(T) < sizeof(Limb)
convert(T, convert(Limb,x))
else
0 <= x.size <= cld(sizeof(T),sizeof(Limb)) || throw(InexactError(:convert, T, x))
0 <= x.size <= cld(sizeof(T),sizeof(Limb)) || throw(InexactError(Symbol(string(T)), T, x))
x % T
end
end

function convert(::Type{T}, x::BigInt) where T<:Signed
function (::Type{T})(x::BigInt) where T<:Signed
n = abs(x.size)
if sizeof(T) < sizeof(Limb)
SLimb = typeof(Signed(one(Limb)))
convert(T, convert(SLimb, x))
else
0 <= n <= cld(sizeof(T),sizeof(Limb)) || throw(InexactError(:convert, T, x))
0 <= n <= cld(sizeof(T),sizeof(Limb)) || throw(InexactError(Symbol(string(T)), T, x))
y = x % T
ispos(x) (y > 0) && throw(InexactError(:convert, T, x)) # catch overflow
ispos(x) (y > 0) && throw(InexactError(Symbol(string(T)), T, x)) # catch overflow
y
end
end
Expand Down Expand Up @@ -386,9 +386,9 @@ function (::Type{T})(n::BigInt, ::RoundingMode{:Nearest}) where T<:CdoubleMax
x
end

convert(::Type{Float64}, n::BigInt) = Float64(n,RoundNearest)
convert(::Type{Float32}, n::BigInt) = Float32(n,RoundNearest)
convert(::Type{Float16}, n::BigInt) = Float16(n,RoundNearest)
Float64(n::BigInt) = Float64(n, RoundNearest)
Float32(n::BigInt) = Float32(n, RoundNearest)
Float16(n::BigInt) = Float16(n, RoundNearest)

promote_rule(::Type{BigInt}, ::Type{<:Integer}) = BigInt

Expand Down
7 changes: 5 additions & 2 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1683,6 +1683,7 @@ function abstract_call_gf_by_type(@nospecialize(f), @nospecialize(atype), sv::In
isa(ft, DataType) || return Any # the function being called is unknown. can't properly handle this backedge right now
ftname = ft.name
isdefined(ftname, :mt) || return Any # not callable. should be Bottom, but can't track this backedge right now
max_methods = sv.params.MAX_METHODS
if ftname === _Type_name
tname = ft.parameters[1]
if isa(tname, TypeVar)
Expand All @@ -1694,6 +1695,8 @@ function abstract_call_gf_by_type(@nospecialize(f), @nospecialize(atype), sv::In
# for things like Union
return Any
end
# many types have many matching constructors
max_methods = max(max_methods, 15)
end
min_valid = UInt[typemin(UInt)]
max_valid = UInt[typemax(UInt)]
Expand All @@ -1702,12 +1705,12 @@ function abstract_call_gf_by_type(@nospecialize(f), @nospecialize(atype), sv::In
splitsigs = switchtupleunion(argtype)
applicable = Any[]
for sig_n in splitsigs
xapplicable = _methods_by_ftype(sig_n, sv.params.MAX_METHODS, sv.params.world, min_valid, max_valid)
xapplicable = _methods_by_ftype(sig_n, max_methods, sv.params.world, min_valid, max_valid)
xapplicable === false && return Any
append!(applicable, xapplicable)
end
else
applicable = _methods_by_ftype(argtype, sv.params.MAX_METHODS, sv.params.world, min_valid, max_valid)
applicable = _methods_by_ftype(argtype, max_methods, sv.params.world, min_valid, max_valid)
if applicable === false
# this means too many methods matched
return Any
Expand Down
Loading

0 comments on commit 5e9f675

Please sign in to comment.