From 97e7c0c8dfaa48aeaaefc7eb51ee26036e224d0a Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 15 Aug 2017 16:00:41 -0400 Subject: [PATCH 1/5] remove fallback constructor from Core.Inference Instead, define explicit constructors for built-in integer types in boot.jl. --- base/array.jl | 2 +- base/boot.jl | 179 ++++++++++++++++++++++++++++++++++++++++++++++++ base/char.jl | 12 ++-- base/coreimg.jl | 3 - base/int.jl | 60 +--------------- base/pointer.jl | 6 +- src/jltypes.c | 2 + 7 files changed, 192 insertions(+), 72 deletions(-) diff --git a/base/array.jl b/base/array.jl index fb7925e37482b..1cf9e506de7fe 100644 --- a/base/array.jl +++ b/base/array.jl @@ -381,7 +381,7 @@ function ones end for (fname, felt) in ((:zeros, :zero), (:ones, :one)) @eval begin - $fname(::Type{T}, dims::NTuple{N, Any}) where {T, N} = fill!(Array{T,N}(uninitialized, Dims(dims)), $felt(T)) + $fname(::Type{T}, dims::NTuple{N, Any}) where {T, N} = fill!(Array{T,N}(uninitialized, convert(Dims, dims)::Dims), $felt(T)) $fname(dims::Tuple) = ($fname)(Float64, dims) $fname(::Type{T}, dims...) where {T} = $fname(T, dims) $fname(dims...) = $fname(dims) diff --git a/base/boot.jl b/base/boot.jl index d9194a79f1b87..1731374852864 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -204,6 +204,10 @@ struct ErrorException <: Exception msg::AbstractString end +macro _inline_meta() + Expr(:meta, :inline) +end + macro _noinline_meta() Expr(:meta, :noinline) end @@ -508,4 +512,179 @@ function NamedTuple{names,T}(args::T) where {names, T <: Tuple} end end +# constructors for built-in types + +import .Intrinsics: eq_int, trunc_int, lshr_int, sub_int, shl_int, bitcast, sext_int, zext_int, and_int + +throw_inexacterror(f::Symbol, T::Type, val) = (@_noinline_meta; throw(InexactError(f, T, val))) + +function is_top_bit_set(x) + @_inline_meta + eq_int(trunc_int(Int8, lshr_int(x, sub_int(shl_int(sizeof(x), 3), 1))), trunc_int(Int8, 1)) +end + +function is_top_bit_set(x::Union{Int8,UInt8}) + @_inline_meta + eq_int(lshr_int(x, 7), trunc_int(typeof(x), 1)) +end + +function check_top_bit(x) + @_inline_meta + is_top_bit_set(x) && throw_inexacterror(:check_top_bit, typeof(x), x) + x +end + +function checked_trunc_sint(::Type{To}, x::From) where {To,From} + @_inline_meta + y = trunc_int(To, x) + back = sext_int(From, y) + eq_int(x, back) || throw_inexacterror(:trunc, To, x) + y +end + +function checked_trunc_uint(::Type{To}, x::From) where {To,From} + @_inline_meta + y = trunc_int(To, x) + back = zext_int(From, y) + eq_int(x, back) || throw_inexacterror(:trunc, To, x) + y +end + +toInt8(x::Int8) = x +toInt8(x::Int16) = checked_trunc_sint(Int8, x) +toInt8(x::Int32) = checked_trunc_sint(Int8, x) +toInt8(x::Int64) = checked_trunc_sint(Int8, x) +toInt8(x::Int128) = checked_trunc_sint(Int8, x) +toInt8(x::UInt8) = bitcast(Int8, check_top_bit(x)) +toInt8(x::UInt16) = checked_trunc_sint(Int8, check_top_bit(x)) +toInt8(x::UInt32) = checked_trunc_sint(Int8, check_top_bit(x)) +toInt8(x::UInt64) = checked_trunc_sint(Int8, check_top_bit(x)) +toInt8(x::UInt128) = checked_trunc_sint(Int8, check_top_bit(x)) +toInt8(x::Bool) = and_int(zext_int(Int8, x), Int8(1)) +toInt16(x::Int8) = sext_int(Int16, x) +toInt16(x::Int16) = x +toInt16(x::Int32) = checked_trunc_sint(Int16, x) +toInt16(x::Int64) = checked_trunc_sint(Int16, x) +toInt16(x::Int128) = checked_trunc_sint(Int16, x) +toInt16(x::UInt8) = zext_int(Int16, x) +toInt16(x::UInt16) = bitcast(Int16, check_top_bit(x)) +toInt16(x::UInt32) = checked_trunc_sint(Int16, check_top_bit(x)) +toInt16(x::UInt64) = checked_trunc_sint(Int16, check_top_bit(x)) +toInt16(x::UInt128) = checked_trunc_sint(Int16, check_top_bit(x)) +toInt16(x::Bool) = and_int(zext_int(Int16, x), Int16(1)) +toInt32(x::Int8) = sext_int(Int32, x) +toInt32(x::Int16) = sext_int(Int32, x) +toInt32(x::Int32) = x +toInt32(x::Int64) = checked_trunc_sint(Int32, x) +toInt32(x::Int128) = checked_trunc_sint(Int32, x) +toInt32(x::UInt8) = zext_int(Int32, x) +toInt32(x::UInt16) = zext_int(Int32, x) +toInt32(x::UInt32) = bitcast(Int32, check_top_bit(x)) +toInt32(x::UInt64) = checked_trunc_sint(Int32, check_top_bit(x)) +toInt32(x::UInt128) = checked_trunc_sint(Int32, check_top_bit(x)) +toInt32(x::Bool) = and_int(zext_int(Int32, x), Int32(1)) +toInt64(x::Int8) = sext_int(Int64, x) +toInt64(x::Int16) = sext_int(Int64, x) +toInt64(x::Int32) = sext_int(Int64, x) +toInt64(x::Int64) = x +toInt64(x::Int128) = checked_trunc_sint(Int64, x) +toInt64(x::UInt8) = zext_int(Int64, x) +toInt64(x::UInt16) = zext_int(Int64, x) +toInt64(x::UInt32) = zext_int(Int64, x) +toInt64(x::UInt64) = bitcast(Int64, check_top_bit(x)) +toInt64(x::UInt128) = checked_trunc_sint(Int64, check_top_bit(x)) +toInt64(x::Bool) = and_int(zext_int(Int64, x), Int64(1)) +toInt128(x::Int8) = sext_int(Int128, x) +toInt128(x::Int16) = sext_int(Int128, x) +toInt128(x::Int32) = sext_int(Int128, x) +toInt128(x::Int64) = sext_int(Int128, x) +toInt128(x::Int128) = x +toInt128(x::UInt8) = zext_int(Int128, x) +toInt128(x::UInt16) = zext_int(Int128, x) +toInt128(x::UInt32) = zext_int(Int128, x) +toInt128(x::UInt64) = zext_int(Int128, x) +toInt128(x::UInt128) = bitcast(Int128, check_top_bit(x)) +toInt128(x::Bool) = and_int(zext_int(Int128, x), Int128(1)) +toUInt8(x::Int8) = bitcast(UInt8, check_top_bit(x)) +toUInt8(x::Int16) = checked_trunc_uint(UInt8, x) +toUInt8(x::Int32) = checked_trunc_uint(UInt8, x) +toUInt8(x::Int64) = checked_trunc_uint(UInt8, x) +toUInt8(x::Int128) = checked_trunc_uint(UInt8, x) +toUInt8(x::UInt8) = x +toUInt8(x::UInt16) = checked_trunc_uint(UInt8, x) +toUInt8(x::UInt32) = checked_trunc_uint(UInt8, x) +toUInt8(x::UInt64) = checked_trunc_uint(UInt8, x) +toUInt8(x::UInt128) = checked_trunc_uint(UInt8, x) +toUInt8(x::Bool) = and_int(zext_int(UInt8, x), UInt8(1)) +toUInt16(x::Int8) = sext_int(UInt16, check_top_bit(x)) +toUInt16(x::Int16) = bitcast(UInt16, check_top_bit(x)) +toUInt16(x::Int32) = checked_trunc_uint(UInt16, x) +toUInt16(x::Int64) = checked_trunc_uint(UInt16, x) +toUInt16(x::Int128) = checked_trunc_uint(UInt16, x) +toUInt16(x::UInt8) = zext_int(UInt16, x) +toUInt16(x::UInt16) = x +toUInt16(x::UInt32) = checked_trunc_uint(UInt16, x) +toUInt16(x::UInt64) = checked_trunc_uint(UInt16, x) +toUInt16(x::UInt128) = checked_trunc_uint(UInt16, x) +toUInt16(x::Bool) = and_int(zext_int(UInt16, x), UInt16(1)) +toUInt32(x::Int8) = sext_int(UInt32, check_top_bit(x)) +toUInt32(x::Int16) = sext_int(UInt32, check_top_bit(x)) +toUInt32(x::Int32) = bitcast(UInt32, check_top_bit(x)) +toUInt32(x::Int64) = checked_trunc_uint(UInt32, x) +toUInt32(x::Int128) = checked_trunc_uint(UInt32, x) +toUInt32(x::UInt8) = zext_int(UInt32, x) +toUInt32(x::UInt16) = zext_int(UInt32, x) +toUInt32(x::UInt32) = x +toUInt32(x::UInt64) = checked_trunc_uint(UInt32, x) +toUInt32(x::UInt128) = checked_trunc_uint(UInt32, x) +toUInt32(x::Bool) = and_int(zext_int(UInt32, x), UInt32(1)) +toUInt64(x::Int8) = sext_int(UInt64, check_top_bit(x)) +toUInt64(x::Int16) = sext_int(UInt64, check_top_bit(x)) +toUInt64(x::Int32) = sext_int(UInt64, check_top_bit(x)) +toUInt64(x::Int64) = bitcast(UInt64, check_top_bit(x)) +toUInt64(x::Int128) = checked_trunc_uint(UInt64, x) +toUInt64(x::UInt8) = zext_int(UInt64, x) +toUInt64(x::UInt16) = zext_int(UInt64, x) +toUInt64(x::UInt32) = zext_int(UInt64, x) +toUInt64(x::UInt64) = x +toUInt64(x::UInt128) = checked_trunc_uint(UInt64, x) +toUInt64(x::Bool) = and_int(zext_int(UInt64, x), UInt64(1)) +toUInt128(x::Int8) = sext_int(UInt128, check_top_bit(x)) +toUInt128(x::Int16) = sext_int(UInt128, check_top_bit(x)) +toUInt128(x::Int32) = sext_int(UInt128, check_top_bit(x)) +toUInt128(x::Int64) = sext_int(UInt128, check_top_bit(x)) +toUInt128(x::Int128) = bitcast(UInt128, check_top_bit(x)) +toUInt128(x::UInt8) = zext_int(UInt128, x) +toUInt128(x::UInt16) = zext_int(UInt128, x) +toUInt128(x::UInt32) = zext_int(UInt128, x) +toUInt128(x::UInt64) = zext_int(UInt128, x) +toUInt128(x::UInt128) = x +toUInt128(x::Bool) = and_int(zext_int(UInt128, x), UInt128(1)) + +# TODO: this is here to work around the 4 method limit in inference (#23210). +const BuiltinInts = Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8, Bool} +Int8(x::BuiltinInts) = toInt8(x)::Int8 +Int16(x::BuiltinInts) = toInt16(x)::Int16 +Int32(x::BuiltinInts) = toInt32(x)::Int32 +Int64(x::BuiltinInts) = toInt64(x)::Int64 +Int128(x::BuiltinInts) = toInt128(x)::Int128 +UInt8(x::BuiltinInts) = toUInt8(x)::UInt8 +UInt16(x::BuiltinInts) = toUInt16(x)::UInt16 +UInt32(x::BuiltinInts) = toUInt32(x)::UInt32 +UInt64(x::BuiltinInts) = toUInt64(x)::UInt64 +UInt128(x::BuiltinInts) = toUInt128(x)::UInt128 + +Char(x::Number) = Char(UInt32(x)) +(::Type{T})(x::Char) where {T<:Number} = T(UInt32(x)) + +(::Type{T})(x::T) where {T<:Number} = x + +Int(x::Ptr) = bitcast(Int, x) +UInt(x::Ptr) = bitcast(UInt, x) +if Int === Int32 +Int64(x::Ptr) = Int64(UInt32(x)) +UInt64(x::Ptr) = UInt64(UInt32(x)) +end +Ptr{T}(x::Union{Int,UInt,Ptr}) where {T} = bitcast(Ptr{T}, x) + ccall(:jl_set_istopmod, Cvoid, (Any, Bool), Core, true) diff --git a/base/char.jl b/base/char.jl index 0a6cab5b4b8ac..7c7595309aa7a 100644 --- a/base/char.jl +++ b/base/char.jl @@ -22,7 +22,7 @@ function isoverlong(c::Char) (u >> 24 == 0xc0) | (u >> 21 == 0x0704) | (u >> 20 == 0x0f08) end -function convert(::Type{UInt32}, c::Char) +function UInt32(c::Char) # TODO: use optimized inline LLVM u = reinterpret(UInt32, c) u < 0x80000000 && return reinterpret(UInt32, u >> 24) @@ -37,7 +37,7 @@ function convert(::Type{UInt32}, c::Char) (u & 0x007f0000 >> 4) | (u & 0x7f000000 >> 6) end -function convert(::Type{Char}, u::UInt32) +function Char(u::UInt32) u < 0x80 && return reinterpret(Char, u << 24) u < 0x00200000 || code_point_err(u)::Union{} c = ((u << 0) & 0x0000003f) | ((u << 2) & 0x00003f00) | @@ -48,17 +48,17 @@ function convert(::Type{Char}, u::UInt32) reinterpret(Char, c) end -function convert(::Type{T}, c::Char) where T <: Union{Int8,UInt8} +function (T::Union{Type{Int8},Type{UInt8}})(c::Char) i = reinterpret(Int32, c) i ≥ 0 ? ((i >>> 24) % T) : T(UInt32(c)) end -function convert(::Type{Char}, b::Union{Int8,UInt8}) +function Char(b::Union{Int8,UInt8}) 0 ≤ b ≤ 0x7f ? reinterpret(Char, (b % UInt32) << 24) : Char(UInt32(b)) end -convert(::Type{Char}, x::Number) = Char(UInt32(x)) -convert(::Type{T}, x::Char) where {T<:Number} = convert(T, UInt32(x)) +convert(::Type{Char}, x::Number) = Char(x) +convert(::Type{T}, x::Char) where {T<:Number} = T(x) rem(x::Char, ::Type{T}) where {T<:Number} = rem(UInt32(x), T) diff --git a/base/coreimg.jl b/base/coreimg.jl index de91ed1536975..685e73a936d45 100644 --- a/base/coreimg.jl +++ b/base/coreimg.jl @@ -15,9 +15,6 @@ eval(m, x) = Core.eval(m, x) include(x) = Core.include(Inference, x) include(mod, x) = Core.include(mod, x) -# conditional to allow redefining Core.Inference after base exists -isdefined(Main, :Base) || ((::Type{T})(arg) where {T} = convert(T, arg)::T) - function return_type end ## Load essential files and libraries diff --git a/base/int.jl b/base/int.jl index 4620784e3c3a8..9e050c4cdbdc8 100644 --- a/base/int.jl +++ b/base/int.jl @@ -31,8 +31,8 @@ const BitUnsigned64T = Union{Type{UInt8}, Type{UInt16}, Type{UInt32}, Type{UIn const BitIntegerType = Union{map(T->Type{T}, BitInteger_types)...} -throw_inexacterror(f::Symbol, ::Type{T}, val) where T = - (@_noinline_meta; throw(InexactError(f, T, val))) +# calls constructors defined in boot.jl +convert(T::BitIntegerType, x::Union{BitInteger, Bool}) = T(x) ## integer comparisons ## @@ -419,75 +419,19 @@ trailing_ones(x::Integer) = trailing_zeros(~x) >>>(x::BitInteger, y::Int) = select_value(0 <= y, x >>> unsigned(y), x << unsigned(-y)) -function is_top_bit_set(x::BitInteger) - @_inline_meta - lshr_int(x, (sizeof(x) << 0x03) - 1) == rem(0x01, typeof(x)) -end -function check_top_bit(x::BitInteger) - @_inline_meta - is_top_bit_set(x) && throw_inexacterror(:check_top_bit, typeof(x), x) - x -end - -## integer conversions ## - -function checked_trunc_sint(::Type{To}, x::From) where {To,From} - @_inline_meta - y = trunc_int(To, x) - back = sext_int(From, y) - x == back || throw_inexacterror(:trunc, To, x) - y -end - -function checked_trunc_uint(::Type{To}, x::From) where {To,From} - @_inline_meta - y = trunc_int(To, x) - back = zext_int(From, y) - x == back || throw_inexacterror(:trunc, To, x) - y -end - for to in BitInteger_types, from in (BitInteger_types..., Bool) if !(to === from) if to.size < from.size - if to <: Signed - if from <: Unsigned - @eval convert(::Type{$to}, x::($from)) = - checked_trunc_sint($to, check_top_bit(x)) - else - @eval convert(::Type{$to}, x::($from)) = - checked_trunc_sint($to, x) - end - else - @eval convert(::Type{$to}, x::($from)) = - checked_trunc_uint($to, x) - end @eval rem(x::($from), ::Type{$to}) = trunc_int($to, x) elseif from === Bool - # Bools use i8 storage and may have garbage in their 7 high bits - @eval convert(::Type{$to}, x::($from)) = zext_int($to, x) & $to(1) @eval rem(x::($from), ::Type{$to}) = convert($to, x) elseif from.size < to.size if from <: Signed - if to <: Unsigned - @eval convert(::Type{$to}, x::($from)) = - sext_int($to, check_top_bit(x)) - else - @eval convert(::Type{$to}, x::($from)) = - sext_int($to, x) - end @eval rem(x::($from), ::Type{$to}) = sext_int($to, x) else - @eval convert(::Type{$to}, x::($from)) = zext_int($to, x) @eval rem(x::($from), ::Type{$to}) = convert($to, x) end else - if !((from <: Signed) === (to <: Signed)) - # raise InexactError if x's top bit is set - @eval convert(::Type{$to}, x::($from)) = bitcast($to, check_top_bit(x)) - else - @eval convert(::Type{$to}, x::($from)) = bitcast($to, x) - end @eval rem(x::($from), ::Type{$to}) = bitcast($to, x) end end diff --git a/base/pointer.jl b/base/pointer.jl index fb4c12b57f357..95c305661652a 100644 --- a/base/pointer.jl +++ b/base/pointer.jl @@ -20,12 +20,10 @@ const C_NULL = bitcast(Ptr{Cvoid}, 0) # TODO: deprecate these conversions. C doesn't even allow them. # pointer to integer -convert(::Type{T}, x::Ptr) where {T<:Union{Int,UInt}} = bitcast(T, x) -convert(::Type{T}, x::Ptr) where {T<:Integer} = convert(T, convert(UInt, x)) +convert(::Type{T}, x::Ptr) where {T<:Integer} = T(UInt(x)) # integer to pointer -convert(::Type{Ptr{T}}, x::UInt) where {T} = bitcast(Ptr{T}, x) -convert(::Type{Ptr{T}}, x::Int) where {T} = bitcast(Ptr{T}, x) +convert(::Type{Ptr{T}}, x::Union{Int,UInt}) where {T} = Ptr{T}(x) # pointer to pointer convert(::Type{Ptr{T}}, p::Ptr{T}) where {T} = p diff --git a/src/jltypes.c b/src/jltypes.c index be7728eb89bd1..d8830d34c7589 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -405,6 +405,8 @@ static void flatten_type_union(jl_value_t **types, size_t n, jl_value_t **out, s STATIC_INLINE const char *datatype_module_name(jl_value_t *t) { + if (((jl_datatype_t*)t)->name->module == NULL) + return NULL; return jl_symbol_name(((jl_datatype_t*)t)->name->module->name); } From 0e726e6cdb5480565dfe561a476265d957bacc9c Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 22 Aug 2017 14:22:52 -0400 Subject: [PATCH 2/5] change more `convert` methods to constructors deprecate a few more sketchy `convert` methods --- base/Enums.jl | 6 ++-- base/asyncmap.jl | 2 +- base/bool.jl | 6 ---- base/boot.jl | 17 +++++++++++ base/c.jl | 19 +++++++----- base/complex.jl | 11 ++++--- base/deprecated.jl | 13 ++++++++ base/float.jl | 67 ++++++++++++++++++++++-------------------- base/gmp.jl | 38 ++++++++++++------------ base/int.jl | 13 -------- base/irrationals.jl | 20 ++++++------- base/libc.jl | 1 - base/libgit2/error.jl | 9 +++--- base/mpfr.jl | 46 +++++++++++++---------------- base/number.jl | 5 ++++ base/pkg/read.jl | 4 +-- base/pkg/reqs.jl | 2 +- base/random/misc.jl | 5 ++-- base/rational.jl | 29 ++++++++---------- base/socket.jl | 2 +- base/strings/basic.jl | 2 +- base/strings/io.jl | 2 +- base/strings/string.jl | 2 +- base/strings/util.jl | 2 +- base/version.jl | 11 +++---- test/enums.jl | 32 ++++++++++---------- test/file.jl | 2 +- test/ranges.jl | 4 +-- test/strings/basic.jl | 2 +- test/version.jl | 14 ++++----- 30 files changed, 199 insertions(+), 189 deletions(-) diff --git a/base/Enums.jl b/base/Enums.jl index 83c9afab5bdb3..48c7233178359 100644 --- a/base/Enums.jl +++ b/base/Enums.jl @@ -9,8 +9,8 @@ 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)) +(::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))) @@ -106,7 +106,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 diff --git a/base/asyncmap.jl b/base/asyncmap.jl index 83b3c25579271..b92ba3cf3c43b 100644 --- a/base/asyncmap.jl +++ b/base/asyncmap.jl @@ -248,7 +248,7 @@ end function asyncmap(f, s::AbstractString; kwargs...) s2 = Vector{Char}(uninitialized, length(s)) asyncmap!(f, s2, s; kwargs...) - return convert(String, s2) + return String(s2) end # map on a single BitArray returns a BitArray if the mapping function is boolean. diff --git a/base/bool.jl b/base/bool.jl index be60d2758337e..135390cdf9859 100644 --- a/base/bool.jl +++ b/base/bool.jl @@ -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 diff --git a/base/boot.jl b/base/boot.jl index 1731374852864..3aa379d3a45ae 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -687,4 +687,21 @@ UInt64(x::Ptr) = UInt64(UInt32(x)) end 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::Union{Float32, Float64}) = Int(x) + ccall(:jl_set_istopmod, Cvoid, (Any, Bool), Core, true) diff --git a/base/c.jl b/base/c.jl index 8972a809d1e11..61163a93fcbc4 100644 --- a/base/c.jl +++ b/base/c.jl @@ -90,14 +90,16 @@ Cwchar_t end end -# construction from typed pointers -convert(::Type{Cstring}, p::Ptr{<:Union{Int8,UInt8}}) = bitcast(Cstring, p) -convert(::Type{Cwstring}, p::Ptr{Cwchar_t}) = bitcast(Cwstring, p) -convert(::Type{Ptr{T}}, p::Cstring) where {T<:Union{Int8,UInt8}} = bitcast(Ptr{T}, p) -convert(::Type{Ptr{Cwchar_t}}, p::Cwstring) = bitcast(Ptr{Cwchar_t}, p) +# construction from pointers +Cstring(p::Union{Ptr{Int8},Ptr{UInt8},Ptr{Cvoid}}) = bitcast(Cstring, p) +Cwstring(p::Union{Ptr{Cwchar_t},Ptr{Cvoid}}) = bitcast(Cwstring, p) +(::Type{Ptr{T}})(p::Cstring) where {T<:Union{Int8,UInt8,Cvoid}} = bitcast(Ptr{T}, p) +(::Type{Ptr{T}})(p::Cwstring) where {T<:Union{Cwchar_t,Cvoid}} = bitcast(Ptr{Cwchar_t}, p) -# construction from untyped pointers -convert(::Type{T}, p::Ptr{Cvoid}) where {T<:Union{Cstring,Cwstring}} = bitcast(T, p) +convert(::Type{Cstring}, p::Union{Ptr{Int8},Ptr{UInt8},Ptr{Cvoid}}) = Cstring(p) +convert(::Type{Cwstring}, p::Union{Ptr{Cwchar_t},Ptr{Cvoid}}) = Cwstring(p) +convert(::Type{Ptr{T}}, p::Cstring) where {T<:Union{Int8,UInt8,Cvoid}} = Ptr{T}(p) +convert(::Type{Ptr{T}}, p::Cwstring) where {T<:Union{Cwchar_t,Cvoid}} = Ptr{T}(p) """ pointer(array [, index]) @@ -157,7 +159,8 @@ function unsafe_convert(::Type{Cwstring}, v::Vector{Cwchar_t}) end # symbols are guaranteed not to contain embedded NUL -convert(::Type{Cstring}, s::Symbol) = Cstring(unsafe_convert(Ptr{Cchar}, s)) +cconvert(::Type{Cstring}, s::Symbol) = s +unsafe_convert(::Type{Cstring}, s::Symbol) = Cstring(unsafe_convert(Ptr{Cchar}, s)) @static if ccall(:jl_get_UNAME, Any, ()) === :NT """ diff --git a/base/complex.jl b/base/complex.jl index 1ea172e6f8a7a..0ef1255ebeff3 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -32,13 +32,12 @@ const ComplexF64 = Complex{Float64} const ComplexF32 = Complex{Float32} const ComplexF16 = 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)} diff --git a/base/deprecated.jl b/base/deprecated.jl index 26494dcc66822..cbfe708942b80 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1552,6 +1552,19 @@ export hex2num @deprecate convert(::Type{String}, s::Symbol) String(s) @deprecate convert(::Type{String}, v::Vector{UInt8}) String(v) @deprecate convert(::Type{S}, g::Unicode.GraphemeIterator) where {S<:AbstractString} convert(S, g.s) +@deprecate convert(::Type{String}, v::AbstractVector{Char}) String(v) + +@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 #19923 @deprecate ror circshift diff --git a/base/float.jl b/base/float.jl index 9ecd70eb5a976..a441be412b26a 100644 --- a/base/float.jl +++ b/base/float.jl @@ -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 @@ -54,27 +54,27 @@ 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)) +(::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 @@ -88,7 +88,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 @@ -104,7 +104,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 @@ -118,7 +118,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 @@ -134,7 +134,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)) @@ -157,7 +157,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 @@ -235,25 +235,28 @@ 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) @@ -261,7 +264,7 @@ convert(::Type{AbstractFloat}, x::UInt128) = convert(Float64, x) # LOSSY 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) @@ -675,11 +678,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 @@ -696,11 +699,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 diff --git a/base/gmp.jl b/base/gmp.jl index 34895f01d6b2d..1acaa6a10e1f6 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -231,8 +231,8 @@ widen(::Type{BigInt}) = BigInt signed(x::BigInt) = x -convert(::Type{BigInt}, x::BigInt) = x -convert(::Type{Signed}, x::BigInt) = x +BigInt(x::BigInt) = x +Signed(x::BigInt) = x hastypemax(::Type{BigInt}) = false @@ -262,14 +262,14 @@ function tryparse_internal(::Type{BigInt}, s::AbstractString, startpos::Int, end 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 @@ -278,10 +278,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)) @@ -323,26 +323,26 @@ function rem(x::BigInt, ::Type{T}) where T<:Union{Base.BitUnsigned,Base.BitSigne 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<:Base.BitUnsigned +function (::Type{T})(x::BigInt) where T<:Base.BitUnsigned 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<:Base.BitSigned +function (::Type{T})(x::BigInt) where T<:Base.BitSigned 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 @@ -385,9 +385,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 diff --git a/base/int.jl b/base/int.jl index 9e050c4cdbdc8..554a0af63d68f 100644 --- a/base/int.jl +++ b/base/int.jl @@ -31,9 +31,6 @@ const BitUnsigned64T = Union{Type{UInt8}, Type{UInt16}, Type{UInt32}, Type{UIn const BitIntegerType = Union{map(T->Type{T}, BitInteger_types)...} -# calls constructors defined in boot.jl -convert(T::BitIntegerType, x::Union{BitInteger, Bool}) = T(x) - ## integer comparisons ## (<)(x::T, y::T) where {T<:BitSigned} = slt_int(x, y) @@ -466,16 +463,6 @@ rem(x::Integer, ::Type{Bool}) = ((x & 1) != 0) mod(x::Integer, ::Type{T}) where {T<:Integer} = rem(x, T) unsafe_trunc(::Type{T}, x::Integer) where {T<:Integer} = rem(x, T) -for (Ts, Tu) in ((Int8, UInt8), (Int16, UInt16), (Int32, UInt32), (Int64, UInt64), (Int128, UInt128)) - @eval convert(::Type{Signed}, x::$Tu) = convert($Ts, x) - @eval convert(::Type{Unsigned}, x::$Ts) = convert($Tu, x) -end - -convert(::Type{Signed}, x::Union{Float32, Float64, Bool}) = convert(Int, x) -convert(::Type{Unsigned}, x::Union{Float32, Float64, Bool}) = convert(UInt, x) - -convert(::Type{Integer}, x::Integer) = x -convert(::Type{Integer}, x::Real) = convert(Signed, x) """ trunc([T,] x, [digits, [base]]) diff --git a/base/irrationals.jl b/base/irrationals.jl index 7a1509a2ff01f..4f55783514fe1 100644 --- a/base/irrationals.jl +++ b/base/irrationals.jl @@ -24,11 +24,11 @@ promote_rule(::Type{<:AbstractIrrational}, ::Type{Float32}) = Float32 promote_rule(::Type{<:AbstractIrrational}, ::Type{<:AbstractIrrational}) = Float64 promote_rule(::Type{<:AbstractIrrational}, ::Type{T}) where {T<:Number} = promote_type(Float64, T) -convert(::Type{AbstractFloat}, x::AbstractIrrational) = Float64(x) -convert(::Type{Float16}, x::AbstractIrrational) = Float16(Float32(x)) -convert(::Type{Complex{T}}, x::AbstractIrrational) where {T<:Real} = convert(Complex{T}, convert(T,x)) +AbstractFloat(x::AbstractIrrational) = Float64(x) +Float16(x::AbstractIrrational) = Float16(Float32(x)) +Complex{T}(x::AbstractIrrational) where {T<:Real} = Complex{T}(T(x)) -@pure function convert(::Type{Rational{T}}, x::AbstractIrrational) where T<:Integer +@pure function Rational{T}(x::AbstractIrrational) where T<:Integer o = precision(BigFloat) p = 256 while true @@ -42,7 +42,7 @@ convert(::Type{Complex{T}}, x::AbstractIrrational) where {T<:Real} = convert(Com p += 32 end end -convert(::Type{Rational{BigInt}}, x::AbstractIrrational) = throw(ArgumentError("Cannot convert an AbstractIrrational to a Rational{BigInt}: use rationalize(Rational{BigInt}, x) instead")) +(::Type{Rational{BigInt}})(x::AbstractIrrational) = throw(ArgumentError("Cannot convert an AbstractIrrational to a Rational{BigInt}: use rationalize(Rational{BigInt}, x) instead")) @pure function (t::Type{T})(x::AbstractIrrational, r::RoundingMode) where T<:Union{Float32,Float64} setprecision(BigFloat, 256) do @@ -126,27 +126,27 @@ macro irrational(sym, val, def) esym = esc(sym) qsym = esc(Expr(:quote, sym)) bigconvert = isa(def,Symbol) ? quote - function Base.convert(::Type{BigFloat}, ::Irrational{$qsym}) + function Base.BigFloat(::Irrational{$qsym}) c = BigFloat() ccall(($(string("mpfr_const_", def)), :libmpfr), Cint, (Ref{BigFloat}, Int32), c, MPFR.ROUNDING_MODE[]) return c end end : quote - Base.convert(::Type{BigFloat}, ::Irrational{$qsym}) = $(esc(def)) + Base.BigFloat(::Irrational{$qsym}) = $(esc(def)) end quote const $esym = Irrational{$qsym}() $bigconvert - Base.convert(::Type{Float64}, ::Irrational{$qsym}) = $val - Base.convert(::Type{Float32}, ::Irrational{$qsym}) = $(Float32(val)) + Base.Float64(::Irrational{$qsym}) = $val + Base.Float32(::Irrational{$qsym}) = $(Float32(val)) @assert isa(big($esym), BigFloat) @assert Float64($esym) == Float64(big($esym)) @assert Float32($esym) == Float32(big($esym)) end end -big(x::AbstractIrrational) = convert(BigFloat,x) +big(x::AbstractIrrational) = BigFloat(x) big(::Type{<:AbstractIrrational}) = BigFloat # align along = for nice Array printing diff --git a/base/libc.jl b/base/libc.jl index fd7e5858a3fc9..cbe3323c2ef23 100644 --- a/base/libc.jl +++ b/base/libc.jl @@ -83,7 +83,6 @@ end Base.unsafe_convert(T::Union{Type{Ptr{Cvoid}},Type{Ptr{FILE}}}, f::FILE) = convert(T, f.ptr) Base.close(f::FILE) = systemerror("fclose", ccall(:fclose, Cint, (Ptr{Cvoid},), f.ptr) != 0) -Base.convert(::Type{FILE}, s::IO) = FILE(s) function Base.seek(h::FILE, offset::Integer) systemerror("fseek", ccall(:fseek, Cint, (Ptr{Cvoid}, Clong, Cint), diff --git a/base/libgit2/error.jl b/base/libgit2/error.jl index 2f5739e0af879..b64e9f1b8d923 100644 --- a/base/libgit2/error.jl +++ b/base/libgit2/error.jl @@ -74,17 +74,17 @@ function last_error() err = ccall((:giterr_last, :libgit2), Ptr{ErrorStruct}, ()) if err != C_NULL err_obj = unsafe_load(err) - err_class = Class[err_obj.class][] + err_class = Class(err_obj.class) err_msg = unsafe_string(err_obj.message) else - err_class = Class[0][] + err_class = Class(0) err_msg = "No errors" end return (err_class, err_msg) end function GitError(code::Integer) - err_code = Code[code][] + err_code = Code(code) err_class, err_msg = last_error() return GitError(err_class, err_code, err_msg) end @@ -93,8 +93,7 @@ end # Error module macro check(git_func) quote - local err::Cint - err = $(esc(git_func::Expr)) + err = Cint($(esc(git_func::Expr))) if err < 0 throw(Error.GitError(err)) end diff --git a/base/mpfr.jl b/base/mpfr.jl index 016462f26937e..483903d0638fd 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -94,12 +94,12 @@ BigFloat(x) widen(::Type{Float64}) = BigFloat widen(::Type{BigFloat}) = BigFloat -convert(::Type{BigFloat}, x::BigFloat) = x +BigFloat(x::BigFloat) = x # convert to BigFloat for (fJ, fC) in ((:si,:Clong), (:ui,:Culong), (:d,:Float64)) @eval begin - function convert(::Type{BigFloat}, x::($fC)) + function BigFloat(x::($fC)) z = BigFloat() ccall(($(string(:mpfr_set_,fJ)), :libmpfr), Int32, (Ref{BigFloat}, $fC, Int32), z, x, ROUNDING_MODE[]) return z @@ -107,19 +107,19 @@ for (fJ, fC) in ((:si,:Clong), (:ui,:Culong), (:d,:Float64)) end end -function convert(::Type{BigFloat}, x::BigInt) +function BigFloat(x::BigInt) z = BigFloat() ccall((:mpfr_set_z, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigInt}, Int32), z, x, ROUNDING_MODE[]) return z end -convert(::Type{BigFloat}, x::Integer) = BigFloat(BigInt(x)) +BigFloat(x::Integer) = BigFloat(BigInt(x)) -convert(::Type{BigFloat}, x::Union{Bool,Int8,Int16,Int32}) = BigFloat(convert(Clong, x)) -convert(::Type{BigFloat}, x::Union{UInt8,UInt16,UInt32}) = BigFloat(convert(Culong, x)) +BigFloat(x::Union{Bool,Int8,Int16,Int32}) = BigFloat(convert(Clong, x)) +BigFloat(x::Union{UInt8,UInt16,UInt32}) = BigFloat(convert(Culong, x)) -convert(::Type{BigFloat}, x::Union{Float16,Float32}) = BigFloat(Float64(x)) -convert(::Type{BigFloat}, x::Rational) = BigFloat(numerator(x)) / BigFloat(denominator(x)) +BigFloat(x::Union{Float16,Float32}) = BigFloat(Float64(x)) +BigFloat(x::Rational) = BigFloat(numerator(x)) / BigFloat(denominator(x)) function tryparse(::Type{BigFloat}, s::AbstractString, base::Int=0) !isempty(s) && Base.Unicode.isspace(s[end]) && return tryparse(BigFloat, rstrip(s), base) @@ -128,8 +128,8 @@ function tryparse(::Type{BigFloat}, s::AbstractString, base::Int=0) err == 0 ? z : nothing end -convert(::Type{Rational}, x::BigFloat) = convert(Rational{BigInt}, x) -convert(::Type{AbstractFloat}, x::BigInt) = BigFloat(x) +Rational(x::BigFloat) = convert(Rational{BigInt}, x) +AbstractFloat(x::BigInt) = BigFloat(x) float(::Type{BigInt}) = BigFloat @@ -231,32 +231,28 @@ floor(::Type{Integer}, x::BigFloat) = floor(BigInt, x) ceil(::Type{Integer}, x::BigFloat) = ceil(BigInt, x) round(::Type{Integer}, x::BigFloat) = round(BigInt, x) -function convert(::Type{Bool}, x::BigFloat) +function Bool(x::BigFloat) iszero(x) && return false isone(x) && return true - throw(InexactError(:convert, Bool, x)) + throw(InexactError(:Bool, Bool, x)) end -function convert(::Type{BigInt},x::BigFloat) - isinteger(x) || throw(InexactError(:convert, BigInt, x)) - trunc(BigInt,x) +function BigInt(x::BigFloat) + isinteger(x) || throw(InexactError(:BigInt, BigInt, x)) + trunc(BigInt, x) end -function convert(::Type{Integer}, x::BigFloat) - isinteger(x) || throw(InexactError(:convert, Integer, x)) - trunc(Integer,x) -end -function convert(::Type{T},x::BigFloat) where T<:Integer - isinteger(x) || throw(InexactError(:convert, T, x)) +function (::Type{T})(x::BigFloat) where T<:Integer + isinteger(x) || throw(InexactError(Symbol(string(T)), T, x)) trunc(T,x) end ## BigFloat -> AbstractFloat -convert(::Type{Float64}, x::BigFloat) = +Float64(x::BigFloat) = ccall((:mpfr_get_d,:libmpfr), Float64, (Ref{BigFloat}, Int32), x, ROUNDING_MODE[]) -convert(::Type{Float32}, x::BigFloat) = +Float32(x::BigFloat) = ccall((:mpfr_get_flt,:libmpfr), Float32, (Ref{BigFloat}, Int32), x, ROUNDING_MODE[]) # TODO: avoid double rounding -convert(::Type{Float16}, x::BigFloat) = convert(Float16, convert(Float32, x)) +Float16(x::BigFloat) = convert(Float16, convert(Float32, x)) Float64(x::BigFloat, r::RoundingMode) = ccall((:mpfr_get_d,:libmpfr), Float64, (Ref{BigFloat}, Int32), x, to_mpfr(r)) @@ -271,7 +267,7 @@ promote_rule(::Type{BigFloat}, ::Type{<:AbstractFloat}) = BigFloat big(::Type{<:AbstractFloat}) = BigFloat -function convert(::Type{Rational{BigInt}}, x::AbstractFloat) +function (::Type{Rational{BigInt}})(x::AbstractFloat) isnan(x) && return zero(BigInt) // zero(BigInt) isinf(x) && return copysign(one(BigInt),x) // zero(BigInt) iszero(x) && return zero(BigInt) // one(BigInt) diff --git a/base/number.jl b/base/number.jl index 18f63c386f578..71090b80257c0 100644 --- a/base/number.jl +++ b/base/number.jl @@ -1,6 +1,11 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license ## generic operations on numbers ## + +# Numbers are convertible +convert(::Type{T}, x::T) where {T<:Number} = x +convert(::Type{T}, x::Number) where {T<:Number} = T(x) + """ isinteger(x) -> Bool diff --git a/base/pkg/read.jl b/base/pkg/read.jl index eda9e6127390c..721ac55b907df 100644 --- a/base/pkg/read.jl +++ b/base/pkg/read.jl @@ -21,7 +21,7 @@ function available(names=readdir("METADATA")) ismatch(Base.VERSION_REGEX, ver) || continue isfile(versdir, ver, "sha1") || continue haskey(pkgs,pkg) || (pkgs[pkg] = Dict{VersionNumber,Available}()) - pkgs[pkg][convert(VersionNumber,ver)] = Available( + pkgs[pkg][VersionNumber(ver)] = Available( readchomp(joinpath(versdir,ver,"sha1")), Reqs.parse(joinpath(versdir,ver,"requires")) ) @@ -41,7 +41,7 @@ function latest(names=readdir("METADATA")) for ver in readdir(versdir) ismatch(Base.VERSION_REGEX, ver) || continue isfile(versdir, ver, "sha1") || continue - push!(pkgversions, convert(VersionNumber,ver)) + push!(pkgversions, VersionNumber(ver)) end isempty(pkgversions) && continue ver = string(maximum(pkgversions)) diff --git a/base/pkg/reqs.jl b/base/pkg/reqs.jl index b84ce5614993d..bcd77d733c0e8 100644 --- a/base/pkg/reqs.jl +++ b/base/pkg/reqs.jl @@ -28,7 +28,7 @@ struct Requirement <: Line package = shift!(fields) all(field->ismatch(Base.VERSION_REGEX, field), fields) || throw(PkgError("invalid requires entry for $package: $content")) - versions = VersionNumber[fields...] + versions = map(VersionNumber, fields) issorted(versions) || throw(PkgError("invalid requires entry for $package: $content")) new(content, package, VersionSet(versions), system) end diff --git a/base/random/misc.jl b/base/random/misc.jl index ff01c16e169e7..6c20d1a943d35 100644 --- a/base/random/misc.jl +++ b/base/random/misc.jl @@ -425,10 +425,11 @@ julia> Base.Random.uuid_version(Base.Random.uuid4(rng)) """ uuid_version(u::UUID) = Int((u.value >> 76) & 0xf) -Base.convert(::Type{UInt128}, u::UUID) = u.value +UInt128(u::UUID) = u.value let groupings = [1:8; 10:13; 15:18; 20:23; 25:36] - function Base.convert(::Type{UUID}, s::AbstractString) + global UUID + function UUID(s::AbstractString) s = Base.Unicode.lowercase(s) if !ismatch(r"^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$", s) diff --git a/base/rational.jl b/base/rational.jl index 43a4332b512fb..cf0c3de1e5749 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -74,32 +74,29 @@ function write(s::IO, z::Rational) write(s,numerator(z),denominator(z)) end -convert(::Type{Rational{T}}, x::Rational) where {T<:Integer} = Rational{T}(convert(T,x.num),convert(T,x.den)) -convert(::Type{Rational{T}}, x::Integer) where {T<:Integer} = Rational{T}(convert(T,x), convert(T,1)) +Rational{T}(x::Rational) where {T<:Integer} = Rational{T}(convert(T,x.num), convert(T,x.den)) +Rational{T}(x::Integer) where {T<:Integer} = Rational{T}(convert(T,x), convert(T,1)) -convert(::Type{Rational}, x::Rational) = x -convert(::Type{Rational}, x::Integer) = convert(Rational{typeof(x)},x) +Rational(x::Rational) = x -convert(::Type{Bool}, x::Rational) = x==0 ? false : x==1 ? true : - throw(InexactError(:convert, Bool, x)) # to resolve ambiguity -convert(::Type{Integer}, x::Rational) = (isinteger(x) ? convert(Integer, x.num) : - throw(InexactError(:convert, Integer, x))) -convert(::Type{T}, x::Rational) where {T<:Integer} = (isinteger(x) ? convert(T, x.num) : - throw(InexactError(:convert, T, x))) +Bool(x::Rational) = x==0 ? false : x==1 ? true : + throw(InexactError(:Bool, Bool, x)) # to resolve ambiguity +(::Type{T})(x::Rational) where {T<:Integer} = (isinteger(x) ? convert(T, x.num) : + throw(InexactError(Symbol(string(T)), T, x))) -convert(::Type{AbstractFloat}, x::Rational) = float(x.num)/float(x.den) -function convert(::Type{T}, x::Rational{S}) where T<:AbstractFloat where S +AbstractFloat(x::Rational) = float(x.num)/float(x.den) +function (::Type{T})(x::Rational{S}) where T<:AbstractFloat where S P = promote_type(T,S) convert(T, convert(P,x.num)/convert(P,x.den)) end -function convert(::Type{Rational{T}}, x::AbstractFloat) where T<:Integer +function Rational{T}(x::AbstractFloat) where T<:Integer r = rationalize(T, x, tol=0) - x == convert(typeof(x), r) || throw(InexactError(:convert, Rational{T}, x)) + x == convert(typeof(x), r) || throw(InexactError(:Rational, Rational{T}, x)) r end -convert(::Type{Rational}, x::Float64) = convert(Rational{Int64}, x) -convert(::Type{Rational}, x::Float32) = convert(Rational{Int}, x) +Rational(x::Float64) = Rational{Int64}(x) +Rational(x::Float32) = Rational{Int}(x) big(z::Complex{<:Rational{<:Integer}}) = Complex{Rational{BigInt}}(z) diff --git a/base/socket.jl b/base/socket.jl index 57dc7dd0278cf..3d339010cc189 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -4,7 +4,7 @@ abstract type IPAddr end Base.isless(a::T, b::T) where {T<:IPAddr} = isless(a.host, b.host) -Base.convert(dt::Type{<:Integer}, ip::IPAddr) = dt(ip.host) +(dt::Type{<:Integer})(ip::IPAddr) = dt(ip.host) struct IPv4 <: IPAddr host::UInt32 diff --git a/base/strings/basic.jl b/base/strings/basic.jl index 0f8d8f462d703..703e455a6306b 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -605,7 +605,7 @@ julia> repeat("ha", 3) "hahaha" ``` """ -repeat(s::AbstractString, r::Integer) = repeat(convert(String, s), r) +repeat(s::AbstractString, r::Integer) = repeat(String(s), r) """ ^(s::Union{AbstractString,Char}, n::Integer) diff --git a/base/strings/io.jl b/base/strings/io.jl index 06912b6c37578..538d7a55242e6 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -496,7 +496,7 @@ function unindent(str::AbstractString, indent::Int; tabwidth=8) String(take!(buf)) end -function convert(::Type{String}, chars::AbstractVector{Char}) +function String(chars::AbstractVector{Char}) sprint(sizehint=length(chars)) do io for c in chars write(io, c) diff --git a/base/strings/string.jl b/base/strings/string.jl index b3b442e030932..888cda75c6046 100644 --- a/base/strings/string.jl +++ b/base/strings/string.jl @@ -58,7 +58,7 @@ Convert a string to a contiguous byte array representation encoded as UTF-8 byte This representation is often appropriate for passing strings to C. """ String(s::AbstractString) = print_to_string(s) -String(s::Symbol) = unsafe_string(Cstring(s)) +String(s::Symbol) = unsafe_string(unsafe_convert(Ptr{UInt8}, s)) (::Type{Vector{UInt8}})(s::String) = ccall(:jl_string_to_array, Ref{Vector{UInt8}}, (Any,), s) diff --git a/base/strings/util.jl b/base/strings/util.jl index c709f94ff46b3..152762db334cf 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -561,4 +561,4 @@ julia> ascii("abcdefgh") "abcdefgh" ``` """ -ascii(x::AbstractString) = ascii(convert(String, x)) +ascii(x::AbstractString) = ascii(String(x)) diff --git a/base/version.jl b/base/version.jl index 7ccbf138aa0a7..66cc198466d9f 100644 --- a/base/version.jl +++ b/base/version.jl @@ -47,6 +47,8 @@ VersionNumber(major::Integer, minor::Integer = 0, patch::Integer = 0, map(x->x isa Integer ? UInt64(x) : String(x), pre), map(x->x isa Integer ? UInt64(x) : String(x), bld)) +VersionNumber(v::Tuple) = VersionNumber(v...) + function print(io::IO, v::VersionNumber) v == typemax(VersionNumber) && return print(io, "∞") print(io, v.major) @@ -65,9 +67,6 @@ function print(io::IO, v::VersionNumber) end show(io::IO, v::VersionNumber) = print(io, "v\"", v, "\"") -convert(::Type{VersionNumber}, v::Integer) = VersionNumber(v) -convert(::Type{VersionNumber}, v::Tuple) = VersionNumber(v...) - const VERSION_REGEX = r"^ v? # prefix (optional) (\d+) # major (required) @@ -104,8 +103,6 @@ function VersionNumber(v::AbstractString) return VersionNumber(major, minor, patch, prerl, build) end -convert(::Type{VersionNumber}, v::AbstractString) = VersionNumber(v) - macro v_str(v); VersionNumber(v); end typemin(::Type{VersionNumber}) = v"0-" @@ -215,7 +212,7 @@ A `VersionNumber` object describing which version of Julia is in use. For detail [Version Number Literals](@ref man-version-number-literals). """ const VERSION = try - ver = convert(VersionNumber, VERSION_STRING) + ver = VersionNumber(VERSION_STRING) if !isempty(ver.prerelease) if GIT_VERSION_INFO.build_number >= 0 ver = VersionNumber(ver.major, ver.minor, ver.patch, (ver.prerelease..., GIT_VERSION_INFO.build_number), ver.build) @@ -232,7 +229,7 @@ catch e VersionNumber(0) end -const libllvm_version = convert(VersionNumber, libllvm_version_string) +const libllvm_version = VersionNumber(libllvm_version_string) function banner(io::IO = STDOUT) if GIT_VERSION_INFO.tagged_commit diff --git a/test/enums.jl b/test/enums.jl index a4cd797ce9035..068aafff29e49 100644 --- a/test/enums.jl +++ b/test/enums.jl @@ -36,19 +36,19 @@ end @test_throws MethodError Fruit(0.0) @test typemin(Fruit) == apple @test typemax(Fruit) == kiwi -@test convert(Fruit,0) == apple -@test convert(Fruit,1) == orange -@test convert(Fruit,2) == kiwi -@test_throws ArgumentError convert(Fruit,3) -@test_throws ArgumentError convert(Fruit,-1) -@test convert(UInt8,apple) === 0x00 -@test convert(UInt16,orange) === 0x0001 -@test convert(UInt128,kiwi) === 0x00000000000000000000000000000002 -@test typeof(convert(BigInt,apple)) <: BigInt -@test convert(BigInt,apple) == 0 -@test convert(Bool,apple) == false -@test convert(Bool,orange) == true -@test_throws InexactError convert(Bool,kiwi) +@test Fruit(0) == apple +@test Fruit(1) == orange +@test Fruit(2) == kiwi +@test_throws ArgumentError Fruit(3) +@test_throws ArgumentError Fruit(-1) +@test UInt8(apple) === 0x00 +@test UInt16(orange) === 0x0001 +@test UInt128(kiwi) === 0x00000000000000000000000000000002 +@test typeof(BigInt(apple)) <: BigInt +@test BigInt(apple) == 0 +@test Bool(apple) == false +@test Bool(orange) == true +@test_throws InexactError Bool(kiwi) @test instances(Fruit) == (apple, orange, kiwi) f(x::Fruit) = "hey, I'm a Fruit" @@ -76,7 +76,7 @@ end @enum Negative _neg1=-1 _neg2=-2 @test Int(_neg1) === -1 @test Int(_neg2) === -2 -@test_throws InexactError convert(UInt8, _neg1) +@test_throws InexactError UInt8(_neg1) @enum Negative2 _neg5=-5 _neg4 _neg3 @test Int(_neg5) === -5 @test Int(_neg4) === -4 @@ -98,7 +98,7 @@ end # other Integer types of enum members @enum Test3::UInt8 _one_Test3=0x01 _two_Test3=0x02 _three_Test3=0x03 @test Test3.size == 1 -@test convert(UInt8, _one_Test3) === 0x01 +@test UInt8(_one_Test3) === 0x01 @test length(instances(Test3)) == 3 @enum Test4::UInt16 _one_Test4=0x01 _two_Test4=0x0002 _three_Test4=0x03 @@ -109,7 +109,7 @@ end @enum Test6::UInt128 _one_Test6=0x00000000000000000000000000000001 _two_Test6=0x00000000000000000000000000000002 @test Test6.size == 16 -@test typeof(convert(Integer, _one_Test6)) == UInt128 +@test typeof(Integer(_one_Test6)) == UInt128 # enum values must be integers @test_throws ArgumentError("invalid value for Enum Test7, _zero = \"zero\"=zero; values must be integers") @macrocall(@enum Test7 _zero="zero") diff --git a/test/file.jl b/test/file.jl index e5db8bbf3ab7e..4c51cf2616b55 100644 --- a/test/file.jl +++ b/test/file.jl @@ -829,7 +829,7 @@ let f = open(file, "w") write(f, "Hello, world!") close(f) f = open(file, "r") - test_LibcFILE(convert(Libc.FILE, f)) + test_LibcFILE(Libc.FILE(f)) close(f) if Sys.iswindows() f = RawFD(ccall(:_open, Cint, (Cstring, Cint), file, Base.Filesystem.JL_O_RDONLY)) diff --git a/test/ranges.jl b/test/ranges.jl index 75eca6ad821fa..db15dc9e98821 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -1175,8 +1175,8 @@ Base.isless(x, y::NotReal) = isless(x, y.val) isdefined(Main, :TestHelpers) || @eval Main include("TestHelpers.jl") using Main.TestHelpers.Furlong @testset "dimensional correctness" begin - @test_throws MethodError collect(Furlong(2):Furlong(10)) # step size is ambiguous - @test_throws MethodError range(Furlong(2), 9) # step size is ambiguous + @test length(collect(Furlong(2):Furlong(10))) == 9 + @test length(range(Furlong(2), 9)) == 9 @test collect(Furlong(2):Furlong(1):Furlong(10)) == collect(range(Furlong(2),Furlong(1),9)) == Furlong.(2:10) @test collect(Furlong(1.0):Furlong(0.5):Furlong(10.0)) == collect(Furlong(1):Furlong(0.5):Furlong(10)) == Furlong.(1:0.5:10) diff --git a/test/strings/basic.jl b/test/strings/basic.jl index 687d64ba56a9d..092828c6c4c76 100644 --- a/test/strings/basic.jl +++ b/test/strings/basic.jl @@ -302,7 +302,7 @@ end end let s = Base.Unicode.normalize("tést",:NFKC) @test unsafe_string(Base.unsafe_convert(Cstring, Base.cconvert(Cstring, s))) == s - @test unsafe_string(convert(Cstring, Symbol(s))) == s + @test unsafe_string(Base.unsafe_convert(Cstring, Symbol(s))) == s end @test_throws ArgumentError Base.unsafe_convert(Cstring, Base.cconvert(Cstring, "ba\0d")) diff --git a/test/version.jl b/test/version.jl index f1e94fd0df477..e45639fe16c69 100644 --- a/test/version.jl +++ b/test/version.jl @@ -82,15 +82,15 @@ io = IOBuffer() show(io,v"4.3.2+1.a") @test length(String(take!(io))) == 12 -# conversion from Int -@test convert(VersionNumber, 2) == v"2.0.0" +# construction from Int +@test VersionNumber(2) == v"2.0.0" -# conversion from Tuple -@test convert(VersionNumber, (2,)) == v"2.0.0" -@test convert(VersionNumber, (3, 2)) == v"3.2.0" +# construction from Tuple +@test VersionNumber((2,)) == v"2.0.0" +@test VersionNumber((3, 2)) == v"3.2.0" -# conversion from AbstractString -@test convert(VersionNumber, "4.3.2+1.a") == v"4.3.2+1.a" +# construction from AbstractString +@test VersionNumber("4.3.2+1.a") == v"4.3.2+1.a" # typemin and typemax @test typemin(VersionNumber) == v"0-" From 25f26e1aa7662e52f8227400b6179cbbbae0f617 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 30 Aug 2017 14:01:28 -0400 Subject: [PATCH 3/5] update manual to explain the new mental model of `convert` vs. construct --- doc/src/manual/constructors.md | 23 ---- doc/src/manual/conversion-and-promotion.md | 149 ++++++++++----------- doc/src/manual/methods.md | 2 +- 3 files changed, 70 insertions(+), 104 deletions(-) diff --git a/doc/src/manual/constructors.md b/doc/src/manual/constructors.md index 330ed28bd8625..7aef476e97ae9 100644 --- a/doc/src/manual/constructors.md +++ b/doc/src/manual/constructors.md @@ -504,29 +504,6 @@ of its arguments are complex integers, it will return an instance of `Complex{Ou The interested reader should consider perusing the rest of [`rational.jl`](https://github.com/JuliaLang/julia/blob/master/base/rational.jl): it is short, self-contained, and implements an entire basic Julia type. -## [Constructors and Conversion](@id constructors-and-conversion) - -Constructors `T(args...)` in Julia are implemented like other callable objects: methods are added -to their types. The type of a type is `Type`, so all constructor methods are stored in the method -table for the `Type` type. This means that you can declare more flexible constructors, e.g. constructors -for abstract types, by explicitly defining methods for the appropriate types. - -However, in some cases you could consider adding methods to `Base.convert` *instead* of defining -a constructor, because Julia falls back to calling [`convert`](@ref) if no matching constructor -is found. For example, if no constructor `T(args...) = ...` exists `Base.convert(::Type{T}, args...) = ...` -is called. - -`convert` is used extensively throughout Julia whenever one type needs to be converted to another -(e.g. in assignment, [`ccall`](@ref), etcetera), and should generally only be defined (or successful) -if the conversion is lossless. For example, `convert(Int, 3.0)` produces `3`, but `convert(Int, 3.2)` -throws an `InexactError`. If you want to define a constructor for a lossless conversion from -one type to another, you should probably define a `convert` method instead. - -On the other hand, if your constructor does not represent a lossless conversion, or doesn't represent -"conversion" at all, it is better to leave it as a constructor rather than a `convert` method. -For example, the `Array{Int,0}(uninitialized)` constructor creates a zero-dimensional `Array` of the type `Int`, -but is not really a "conversion" from `Int` to an `Array`. - ## Outer-only constructors As we have seen, a typical parametric type has inner constructors that are called when type parameters diff --git a/doc/src/manual/conversion-and-promotion.md b/doc/src/manual/conversion-and-promotion.md index 4c4a823db56a3..56fe28341b089 100644 --- a/doc/src/manual/conversion-and-promotion.md +++ b/doc/src/manual/conversion-and-promotion.md @@ -41,10 +41,17 @@ of promotion rules defining what types they should promote to when mixed with ot ## Conversion -Conversion of values to various types is performed by the `convert` function. The `convert` function -generally takes two arguments: the first is a type object while the second is a value to convert -to that type; the returned value is the value converted to an instance of given type. The simplest -way to understand this function is to see it in action: +The standard way to obtain a value of a certain type `T` is to call the type's constructor, `T(x)`. +However, there are cases where it's convenient to convert a value from one type to another +without the programmer asking for it explicitly. +One example is assigning a value into an array: if `A` is a `Vector{Float64}`, the expression +`A[1] = 2` should work by automatically converting the `2` from `Int` to `Float64`, and +storing the result in the array. +This is done via the `convert` function. + +The `convert` function generally takes two arguments: the first is a type object and the second is +a value to convert to that type. The returned value is the value converted to an instance of given type. +The simplest way to understand this function is to see it in action: ```jldoctest julia> x = 12 @@ -81,9 +88,7 @@ doesn't know how to perform the requested conversion: ```jldoctest julia> convert(AbstractFloat, "foo") -ERROR: MethodError: Cannot `convert` an object of type String to an object of type AbstractFloat -This may have arisen from a call to the constructor AbstractFloat(...), -since type constructors fall back to convert methods. +ERROR: MethodError: Cannot `convert` an object of type String to an object of type AbstractFloat. ``` Some languages consider parsing strings as numbers or formatting numbers as strings to be conversions @@ -92,93 +97,77 @@ not: even though some strings can be parsed as numbers, most strings are not val of numbers, and only a very limited subset of them are. Therefore in Julia the dedicated `parse` function must be used to perform this operation, making it more explicit. +### When is `convert` called? + +The following language constructs call `convert`: + + * Assigning to an array converts to the array's element type. + * Assigning to a field of an object converts to the declared type of the field. + * Constructing an object with `new` converts to the object's declared field types. + * Assigning to a variable with a declared type (e.g. `local x::T`) converts to that type. + * A function with a declared return type converts its return value to that type. + * Passing a value to `ccall` converts it to the corresponding argument type. + +### Conversion vs. Construction + +Note that the behavior of `convert(T, x)` appears to be nearly identical to `T(x)`. +Indeed, it usually is. +However, there is a key semantic difference: since `convert` can be called implicitly, +its methods are restricted to cases that are considered "safe" or "unsurprising". +`convert` will only convert between types that represent the same basic kind of thing +(e.g. different representations of numbers, or different string encodings). +It is also usually lossless; converting a value to a different type and back again +should result in the exact same value. + +Notice that some constructors don't implement the concept of "conversion". +For example, `Vector{Int}(5)` constructs a 5-element vector, which is not really a +"conversion" from an integer to a vector. + +Finally, `convert(T, x)` is expected to return the original `x` if `x` is already of type `T`. +In contrast, if `T` is a mutable collection type then `T(x)` should always make a new +collection (copying elements from `x`). + ### Defining New Conversions -To define a new conversion, simply provide a new method for `convert`. That's really all there -is to it. For example, the method to convert a real number to a boolean is this: +When defining a new type, initially all ways of creating it should be defined as +constructors. +If it becomes clear that implicit conversion would be useful, and that some +constructors meet the above "safety" criteria, then `convert` methods can be added. +These methods are typically quite simple, as they only need to call the appropriate +constructor. +Such a definition might look like this: ```julia -convert(::Type{Bool}, x::Real) = x==0 ? false : x==1 ? true : throw(InexactError()) +convert(::Type{MyType}, x) = MyType(x) ``` The type of the first argument of this method is a [singleton type](@ref man-singleton-types), -`Type{Bool}`, the only instance of which is [`Bool`](@ref). Thus, this method is only invoked -when the first argument is the type value `Bool`. Notice the syntax used for the first +`Type{MyType}`, the only instance of which is `MyType`. Thus, this method is only invoked +when the first argument is the type value `MyType`. Notice the syntax used for the first argument: the argument name is omitted prior to the `::` symbol, and only the type is given. This is the syntax in Julia for a function argument whose type is specified but whose value is never used in the function body. In this example, since the type is a singleton, there -would never be any reason to use its value within the body. When invoked, the method -determines whether a numeric value is true or false as a boolean, -by comparing it to one and zero: +would never be any reason to use its value within the body. -```jldoctest -julia> convert(Bool, 1) -true - -julia> convert(Bool, 0) -false - -julia> convert(Bool, 1im) -ERROR: InexactError: convert(Bool, 0 + 1im) -Stacktrace: - [1] convert(::Type{Bool}, ::Complex{Int64}) at ./complex.jl:37 - -julia> convert(Bool, 0im) -false -``` - -The method signatures for conversion methods are often quite a bit more involved than this example, -especially for parametric types. The example above is meant to be pedagogical, and is not the -actual Julia behaviour. This is the actual implementation in Julia: +All instances of some abstract types are by default considered "sufficiently similar" +that a universal `convert` definition is provided in the standard library. +For example, this definition states that it's valid to `convert` any `Number` type to +any other by calling a 1-argument constructor: ```julia -convert(::Type{T}, z::Complex) where {T<:Real} = - (imag(z) == 0 ? convert(T, real(z)) : throw(InexactError())) +convert(::Type{T}, x::Number) where {T<:Number} = T(x) ``` -### [Case Study: Rational Conversions](@id man-rational-conversion) - -To continue our case study of Julia's [`Rational`](@ref) type, here are the conversions declared in -[`rational.jl`](https://github.com/JuliaLang/julia/blob/master/base/rational.jl), -right after the declaration of the type and its constructors: +This means that new `Number` types only need to define constructors, since this +definition will handle `convert` for them. +An identity conversion is also provided to handle the case where the argument is +already of the requested type: ```julia -convert(::Type{Rational{T}}, x::Rational) where {T<:Integer} = Rational(convert(T,x.num),convert(T,x.den)) -convert(::Type{Rational{T}}, x::Integer) where {T<:Integer} = Rational(convert(T,x), convert(T,1)) - -function convert(::Type{Rational{T}}, x::AbstractFloat, tol::Real) where T<:Integer - if isnan(x); return zero(T)//zero(T); end - if isinf(x); return sign(x)//zero(T); end - y = x - a = d = one(T) - b = c = zero(T) - while true - f = convert(T,round(y)); y -= f - a, b, c, d = f*a+c, f*b+d, a, b - if y == 0 || abs(a/b-x) <= tol - return a//b - end - y = 1/y - end -end -convert(rt::Type{Rational{T}}, x::AbstractFloat) where {T<:Integer} = convert(rt,x,eps(x)) - -convert(::Type{T}, x::Rational) where {T<:AbstractFloat} = convert(T,x.num)/convert(T,x.den) -convert(::Type{T}, x::Rational) where {T<:Integer} = div(convert(T,x.num),convert(T,x.den)) +convert(::Type{T}, x::T) where {T<:Number} = x ``` -The initial four convert methods provide conversions to rational types. The first method converts -one type of rational to another type of rational by converting the numerator and denominator to -the appropriate integer type. The second method does the same conversion for integers by taking -the denominator to be 1. The third method implements a standard algorithm for approximating a -floating-point number by a ratio of integers to within a given tolerance, and the fourth method -applies it, using machine epsilon at the given value as the threshold. In general, one should -have `a//b == convert(Rational{Int64}, a/b)`. - -The last two convert methods provide conversions from rational types to floating-point and integer -types. To convert to floating point, one simply converts both numerator and denominator to that -floating point type and then divides. To convert to integer, one can use the `div` operator for -truncated integer division (rounded towards zero). +Similar definitions exist for `AbstractString`, `AbstractArray`, and `AbstractDict`. ## Promotion @@ -327,8 +316,8 @@ of rational numbers, resulting in a rational of the promotion of their respectiv types. The third and final rule dictates that promoting a rational with a float results in the same type as promoting the numerator/denominator type with the float. -This small handful of promotion rules, together with the [conversion methods discussed above](@ref man-rational-conversion), -are sufficient to make rational numbers interoperate completely naturally with all of Julia's -other numeric types -- integers, floating-point numbers, and complex numbers. By providing appropriate -conversion methods and promotion rules in the same manner, any user-defined numeric type can interoperate -just as naturally with Julia's predefined numerics. +This small handful of promotion rules, together with the type's constructors and the default +`convert` method for numbers, are sufficient to make rational numbers interoperate completely +naturally with all of Julia's other numeric types -- integers, floating-point numbers, and complex +numbers. By providing appropriate conversion methods and promotion rules in the same manner, any +user-defined numeric type can interoperate just as naturally with Julia's predefined numerics. diff --git a/doc/src/manual/methods.md b/doc/src/manual/methods.md index 13a92b64cc21f..927282bfec675 100644 --- a/doc/src/manual/methods.md +++ b/doc/src/manual/methods.md @@ -865,7 +865,7 @@ julia> p(3) ``` This mechanism is also the key to how type constructors and closures (inner functions that refer -to their surrounding environment) work in Julia, discussed [later in the manual](@ref constructors-and-conversion). +to their surrounding environment) work in Julia. ## Empty generic functions From d55148e0d0330b059d67cbbabd08e1af9aab9c59 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 30 Aug 2017 17:14:01 -0400 Subject: [PATCH 4/5] consolidate `Associative` conversions, and allow `AbstractSet` conversions --- base/abstractdict.jl | 11 +++++++++++ base/dict.jl | 15 --------------- base/set.jl | 4 ++-- base/weakkeydict.jl | 15 --------------- stdlib/Test/src/Test.jl | 1 - 5 files changed, 13 insertions(+), 33 deletions(-) diff --git a/base/abstractdict.jl b/base/abstractdict.jl index bdcd083c2084c..d688a6b9023c4 100644 --- a/base/abstractdict.jl +++ b/base/abstractdict.jl @@ -502,6 +502,17 @@ push!(t::AbstractDict, p::Pair) = setindex!(t, p.second, p.first) push!(t::AbstractDict, p::Pair, q::Pair) = push!(push!(t, p), q) push!(t::AbstractDict, p::Pair, q::Pair, r::Pair...) = push!(push!(push!(t, p), q), r...) +# AbstractDicts are convertible +convert(::Type{T}, x::T) where {T<:AbstractDict} = x + +function convert(::Type{T}, x::AbstractDict) where T<:AbstractDict + h = T(x) + if length(h) != length(x) + error("key collision during dictionary conversion") + end + return h +end + # hashing objects by identity """ diff --git a/base/dict.jl b/base/dict.jl index 8815e926b4dea..39e4bfab1dc0f 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -190,21 +190,6 @@ end empty(a::AbstractDict, ::Type{K}, ::Type{V}) where {K, V} = Dict{K, V}() -# conversion between Dict types -function convert(::Type{Dict{K,V}},d::AbstractDict) where V where K - h = Dict{K,V}() - for (k,v) in d - ck = convert(K,k) - if !haskey(h,ck) - h[ck] = convert(V,v) - else - error("key collision during dictionary conversion") - end - end - return h -end -convert(::Type{Dict{K,V}},d::Dict{K,V}) where {K,V} = d - hashindex(key, sz) = (((hash(key)%Int) & (sz-1)) + 1)::Int @propagate_inbounds isslotempty(h::Dict, i::Int) = h.slots[i] == 0x0 diff --git a/base/set.jl b/base/set.jl index b708916058f43..34f2ae345f257 100644 --- a/base/set.jl +++ b/base/set.jl @@ -542,5 +542,5 @@ function hash(s::Set, h::UInt) hash(hv, h) end -convert(::Type{Set{T}}, s::Set{T}) where {T} = s -convert(::Type{Set{T}}, x::Set) where {T} = Set{T}(x) +convert(::Type{T}, s::T) where {T<:AbstractSet} = s +convert(::Type{T}, s::AbstractSet) where {T<:AbstractSet} = T(s) diff --git a/base/weakkeydict.jl b/base/weakkeydict.jl index ecda0680dda10..fb153d500d96e 100644 --- a/base/weakkeydict.jl +++ b/base/weakkeydict.jl @@ -70,21 +70,6 @@ end empty(d::WeakKeyDict, ::Type{K}, ::Type{V}) where {K, V} = WeakKeyDict{K, V}() -# conversion between Dict types -function convert(::Type{WeakKeyDict{K,V}},d::AbstractDict) where V where K - h = WeakKeyDict{K,V}() - for (k,v) in d - ck = convert(K,k) - if !haskey(h,ck) - h[ck] = convert(V,v) - else - error("key collision during dictionary conversion") - end - end - return h -end -convert(::Type{WeakKeyDict{K,V}},d::WeakKeyDict{K,V}) where {K,V} = d - islocked(wkh::WeakKeyDict) = islocked(wkh.lock) lock(f, wkh::WeakKeyDict) = lock(f, wkh.lock) trylock(f, wkh::WeakKeyDict) = trylock(f, wkh.lock) diff --git a/stdlib/Test/src/Test.jl b/stdlib/Test/src/Test.jl index e3383937910d5..bdac989c92133 100644 --- a/stdlib/Test/src/Test.jl +++ b/stdlib/Test/src/Test.jl @@ -1449,7 +1449,6 @@ end for (G, A) in ((GenericSet, AbstractSet), (GenericDict, AbstractDict)) @eval begin - Base.convert(::Type{$G}, s::$A) = $G(s) Base.done(s::$G, state) = done(s.s, state) Base.next(s::$G, state) = next(s.s, state) end From 31006cfec17e9d2d8b6fb5aff73f97e17907fff0 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 7 Sep 2017 18:40:53 -0400 Subject: [PATCH 5/5] deprecate convert-to-construct fallback --- NEWS.md | 4 ++ base/abstractarray.jl | 19 +++--- base/array.jl | 41 ++++++------ base/bitarray.jl | 21 ++---- base/boot.jl | 8 +++ base/deprecated.jl | 16 +++++ base/dict.jl | 2 +- base/inference.jl | 8 ++- base/libgit2/types.jl | 1 + base/linalg/bidiag.jl | 17 ++--- base/linalg/cholesky.jl | 30 ++++----- base/linalg/diagonal.jl | 10 +-- base/linalg/eigen.jl | 8 +-- base/linalg/factorization.jl | 7 +- base/linalg/givens.jl | 15 +++-- base/linalg/hessenberg.jl | 12 ++-- base/linalg/ldlt.jl | 20 +++--- base/linalg/lq.jl | 46 ++++++------- base/linalg/lu.jl | 30 ++++----- base/linalg/qr.jl | 52 +++++++-------- base/linalg/rowvector.jl | 2 +- base/linalg/schur.jl | 8 +-- base/linalg/special.jl | 38 +++++------ base/linalg/svd.jl | 8 +-- base/linalg/symmetric.jl | 18 +++--- base/linalg/triangular.jl | 24 ++++--- base/linalg/tridiag.jl | 24 +++---- base/precompile.jl | 4 -- base/range.jl | 49 +++++++------- base/replutil.jl | 12 +--- base/set.jl | 4 +- base/socket.jl | 2 +- base/sparse/sparse.jl | 2 +- base/sparse/sparsematrix.jl | 29 ++++----- base/sparse/sparsevector.jl | 38 +++++------ base/statistics.jl | 6 +- base/sysimg.jl | 4 -- base/twiceprecision.jl | 19 +++--- stdlib/Dates/src/periods.jl | 7 +- stdlib/Dates/test/periods.jl | 2 + stdlib/SharedArrays/src/SharedArrays.jl | 8 +-- stdlib/SuiteSparse/src/cholmod.jl | 86 ++++++++++++------------- test/abstractarray.jl | 14 ++-- test/arrayops.jl | 2 +- test/choosetests.jl | 16 ++--- test/dimensionful.jl | 7 +- 46 files changed, 405 insertions(+), 395 deletions(-) diff --git a/NEWS.md b/NEWS.md index c4c6ba11ee152..84bbf2a141d3a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -44,6 +44,10 @@ Language changes * The syntax for parametric methods, `function f{T}(x::T)`, has been changed to `function f(x::T) where {T}` ([#11310]). + * The fallback constructor that calls `convert` is deprecated. Instead, new types should + prefer to define constructors, and add `convert` methods that call those constructors + only as necessary ([#15120]). + * The syntax `1.+2` is deprecated, since it is ambiguous: it could mean either `1 .+ 2` (the current meaning) or `1. + 2` ([#19089]). diff --git a/base/abstractarray.jl b/base/abstractarray.jl index c998dca6cccce..00414ecacf6d7 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -11,6 +11,17 @@ Supertype for `N`-dimensional arrays (or array-like types) with elements of type """ AbstractArray +convert(::Type{T}, a::T) where {T<:AbstractArray} = a +convert(::Type{T}, a::AbstractArray) where {T<:AbstractArray} = T(a) + +if module_name(@__MODULE__) === :Base # avoid method overwrite +# catch undefined constructors before the deprecation kicks in +# TODO: remove when deprecation is removed +function (::Type{T})(arg) where {T<:AbstractArray} + throw(MethodError(T, (arg,))) +end +end + """ size(A::AbstractArray, [dim...]) @@ -854,14 +865,6 @@ isempty(a::AbstractArray) = (_length(a) == 0) # keys with an IndexStyle keys(s::IndexStyle, A::AbstractArray, B::AbstractArray...) = eachindex(s, A, B...) -## Conversions ## - -convert(::Type{AbstractArray{T,N}}, A::AbstractArray{T,N}) where {T,N } = A -convert(::Type{AbstractArray{T,N}}, A::AbstractArray{S,N}) where {T,S,N} = copyto!(similar(A,T), A) -convert(::Type{AbstractArray{T}}, A::AbstractArray{S,N}) where {T,S,N} = convert(AbstractArray{T,N}, A) - -convert(::Type{Array}, A::AbstractArray{T,N}) where {T,N} = convert(Array{T,N}, A) - """ of_indices(x, y) diff --git a/base/array.jl b/base/array.jl index 1cf9e506de7fe..7cef7f61c21ee 100644 --- a/base/array.jl +++ b/base/array.jl @@ -402,21 +402,14 @@ oneunit(x::AbstractMatrix{T}) where {T} = _one(oneunit(T), x) # arises in similar(dest, Pair{Union{},Union{}}) where dest::Dict: convert(::Type{Vector{Union{}}}, a::Vector{Union{}}) = a -convert(::Type{Vector}, x::AbstractVector{T}) where {T} = convert(Vector{T}, x) -convert(::Type{Matrix}, x::AbstractMatrix{T}) where {T} = convert(Matrix{T}, x) - -convert(::Type{Array{T}}, x::Array{T,n}) where {T,n} = x -convert(::Type{Array{T,n}}, x::Array{T,n}) where {T,n} = x - -convert(::Type{Array{T}}, x::AbstractArray{S,n}) where {T,n,S} = convert(Array{T,n}, x) -convert(::Type{Array{T,n}}, x::AbstractArray{S,n}) where {T,n,S} = copyto!(Array{T,n}(uninitialized, size(x)), x) - promote_rule(a::Type{Array{T,n}}, b::Type{Array{S,n}}) where {T,n,S} = el_same(promote_type(T,S), a, b) -# constructors should make copies +## Constructors ## if module_name(@__MODULE__) === :Base # avoid method overwrite -(::Type{T})(x::T) where {T<:Array} = copy(x) +# constructors should make copies +Array{T,N}(x::AbstractArray{S,N}) where {T,N,S} = copyto!(Array{T,N}(uninitialized, size(x)), x) +AbstractArray{T,N}(A::AbstractArray{S,N}) where {T,N,S} = copyto!(similar(A,T), A) end ## copying iterators to containers @@ -504,14 +497,26 @@ end # gets a chance to see it, so that recursive calls to the caller # don't trigger the inference limiter if isdefined(Core, :Inference) - macro default_eltype(itrt) + macro default_eltype(itr) + I = esc(itr) return quote - Core.Inference.return_type(first, Tuple{$(esc(itrt))}) + if $I isa Generator && ($I).f isa Type + ($I).f + else + Core.Inference.return_type(first, Tuple{typeof($I)}) + end end end else - macro default_eltype(itrt) - return :(Any) + macro default_eltype(itr) + I = esc(itr) + return quote + if $I isa Generator && ($I).f isa Type + ($I).f + else + Any + end + end end end @@ -520,7 +525,7 @@ _array_for(::Type{T}, itr, ::HasShape) where {T} = similar(Array{T}, axes(itr)): function collect(itr::Generator) isz = iteratorsize(itr.iter) - et = @default_eltype(typeof(itr)) + et = @default_eltype(itr) if isa(isz, SizeUnknown) return grow_to!(Vector{et}(), itr) else @@ -534,12 +539,12 @@ function collect(itr::Generator) end _collect(c, itr, ::EltypeUnknown, isz::SizeUnknown) = - grow_to!(_similar_for(c, @default_eltype(typeof(itr)), itr, isz), itr) + grow_to!(_similar_for(c, @default_eltype(itr), itr, isz), itr) function _collect(c, itr, ::EltypeUnknown, isz::Union{HasLength,HasShape}) st = start(itr) if done(itr,st) - return _similar_for(c, @default_eltype(typeof(itr)), itr, isz) + return _similar_for(c, @default_eltype(itr), itr, isz) end v1, st = next(itr, st) collect_to_with_first!(_similar_for(c, typeof(v1), itr, isz), v1, itr, st) diff --git a/base/bitarray.jl b/base/bitarray.jl index 9da097162ace0..d3f57f063d474 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -449,12 +449,10 @@ function _bitreshape(B::BitArray, dims::NTuple{N,Int}) where N return Br end -## Conversions ## +## Constructors ## -convert(::Type{Array{T}}, B::BitArray{N}) where {T,N} = convert(Array{T,N}, B) -convert(::Type{Array{T,N}}, B::BitArray{N}) where {T,N} = _convert(Array{T,N}, B) # see #15801 -function _convert(::Type{Array{T,N}}, B::BitArray{N}) where {T,N} - A = Array{T}(uninitialized, size(B)) +function Array{T,N}(B::BitArray{N}) where {T,N} + A = Array{T,N}(uninitialized, size(B)) Bc = B.chunks @inbounds for i = 1:length(A) A[i] = unsafe_bitgetindex(Bc, i) @@ -462,8 +460,8 @@ function _convert(::Type{Array{T,N}}, B::BitArray{N}) where {T,N} return A end -convert(::Type{BitArray}, A::AbstractArray{T,N}) where {T,N} = convert(BitArray{N}, A) -function convert(::Type{BitArray{N}}, A::AbstractArray{T,N}) where N where T +BitArray(A::AbstractArray{<:Any,N}) where {N} = BitArray{N}(A) +function BitArray{N}(A::AbstractArray{T,N}) where N where T B = BitArray(uninitialized, size(A)) Bc = B.chunks l = length(B) @@ -488,7 +486,7 @@ function convert(::Type{BitArray{N}}, A::AbstractArray{T,N}) where N where T return B end -function convert(::Type{BitArray{N}}, A::Array{Bool,N}) where N +function BitArray{N}(A::Array{Bool,N}) where N B = BitArray(uninitialized, size(A)) Bc = B.chunks l = length(B) @@ -497,16 +495,9 @@ function convert(::Type{BitArray{N}}, A::Array{Bool,N}) where N return B end -convert(::Type{BitArray{N}}, B::BitArray{N}) where {N} = B -convert(::Type{AbstractArray{T,N}}, B::BitArray{N}) where {T,N} = convert(Array{T,N}, B) - reinterpret(::Type{Bool}, B::BitArray, dims::NTuple{N,Int}) where {N} = reinterpret(B, dims) reinterpret(B::BitArray, dims::NTuple{N,Int}) where {N} = reshape(B, dims) -## Constructors from generic iterables ## - -BitArray(A::AbstractArray{<:Any,N}) where {N} = convert(BitArray{N}, A) - if module_name(@__MODULE__) === :Base # avoid method overwrite (::Type{T})(x::T) where {T<:BitArray} = copy(x) end diff --git a/base/boot.jl b/base/boot.jl index 3aa379d3a45ae..900a82c588229 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -386,6 +386,13 @@ Array{T}(::Uninitialized, d::NTuple{N,Int}) where {T,N} = Array{T,N}(uninitializ Array{T,1}() where {T} = Array{T,1}(uninitialized, 0) +(::Type{Array{T,N} where T})(x::AbstractArray{S,N}) where {S,N} = Array{S,N}(x) + +Array(A::AbstractArray{T,N}) where {T,N} = Array{T,N}(A) +Array{T}(A::AbstractArray{S,N}) where {T,N,S} = Array{T,N}(A) + +AbstractArray{T}(A::AbstractArray{S,N}) where {T,S,N} = AbstractArray{T,N}(A) + # primitive Symbol constructors function Symbol(s::String) return ccall(:jl_symbol_n, Ref{Symbol}, (Ptr{UInt8}, Int), @@ -675,6 +682,7 @@ UInt64(x::BuiltinInts) = toUInt64(x)::UInt64 UInt128(x::BuiltinInts) = toUInt128(x)::UInt128 Char(x::Number) = Char(UInt32(x)) +Char(x::Char) = x (::Type{T})(x::Char) where {T<:Number} = T(UInt32(x)) (::Type{T})(x::T) where {T<:Number} = x diff --git a/base/deprecated.jl b/base/deprecated.jl index cbfe708942b80..3f39f2cea5ba3 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1566,6 +1566,22 @@ export hex2num @deprecate convert(dt::Type{<:Integer}, ip::IPAddr) dt(ip) +function (::Type{T})(arg) where {T} + if applicable(convert, T, arg) + sig = which(convert, (Type{T}, typeof(arg))).sig + if sig == (Tuple{typeof(convert),Type{S},Number} where S<:Number) || + sig == (Tuple{typeof(convert),Type{S},AbstractArray} where S<:AbstractArray) + # matches a catch-all converter; will stack overflow + throw(MethodError(T, (arg,))) + end + # if `convert` call would not work, just let the method error happen + depwarn("Constructors no longer fall back to `convert`. A constructor `$T(::$(typeof(arg)))` should be defined instead.", :Type) + end + convert(T, arg)::T +end +# related items to remove in: abstractarray.jl, dates/periods.jl, inference.jl +# also remove all uses of is_default_method + # Issue #19923 @deprecate ror circshift @deprecate ror! circshift! diff --git a/base/dict.jl b/base/dict.jl index 39e4bfab1dc0f..3e5534885318a 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -159,7 +159,7 @@ dict_with_eltype(DT_apply, ::Type{Pair{K,V}}) where {K,V} = DT_apply(K, V)() dict_with_eltype(DT_apply, ::Type) = DT_apply(Any, Any)() dict_with_eltype(DT_apply::F, kv, t) where {F} = grow_to!(dict_with_eltype(DT_apply, @default_eltype(typeof(kv))), kv) function dict_with_eltype(DT_apply::F, kv::Generator, t) where F - T = @default_eltype(typeof(kv)) + T = @default_eltype(kv) if T <: Union{Pair, Tuple{Any, Any}} && _isleaftype(T) return dict_with_eltype(DT_apply, kv, T) end diff --git a/base/inference.jl b/base/inference.jl index f3925014d4808..01e02e7b94c3f 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -2086,7 +2086,13 @@ function abstract_call_method_with_const_args(@nospecialize(f), argtypes::Vector return result end +const deprecated_sym = Symbol("deprecated.jl") + function abstract_call_method(method::Method, @nospecialize(sig), sparams::SimpleVector, sv::InferenceState) + # TODO: remove with 0.7 deprecations + if method.file === deprecated_sym && method.sig == (Tuple{Type{T},Any} where T) + return Any, false + end topmost = nothing # Limit argument type tuple growth of functions: # look through the parents list to see if there's a call to the same method @@ -2181,7 +2187,7 @@ function abstract_call_method(method::Method, @nospecialize(sig), sparams::Simpl recomputed = ccall(:jl_type_intersection_with_env, Any, (Any, Any), sig, method.sig)::SimpleVector sig = recomputed[1] if !isa(unwrap_unionall(sig), DataType) # probably Union{} - return Any + return Any, false end sparams = recomputed[2]::SimpleVector end diff --git a/base/libgit2/types.jl b/base/libgit2/types.jl index 3bc83ade4a47d..30cc7fdcf068a 100644 --- a/base/libgit2/types.jl +++ b/base/libgit2/types.jl @@ -20,6 +20,7 @@ struct GitHash <: AbstractGitHash GitHash(val::NTuple{OID_RAWSZ, UInt8}) = new(val) end GitHash() = GitHash(ntuple(i->zero(UInt8), OID_RAWSZ)) +GitHash(h::GitHash) = h """ GitShortHash(hash::GitHash, len::Integer) diff --git a/base/linalg/bidiag.jl b/base/linalg/bidiag.jl index 15cb73809fb5e..7c6ad8b1bd2eb 100644 --- a/base/linalg/bidiag.jl +++ b/base/linalg/bidiag.jl @@ -93,6 +93,8 @@ function Bidiagonal(A::AbstractMatrix, uplo::Symbol) Bidiagonal(diag(A, 0), diag(A, uplo == :U ? 1 : -1), uplo) end +Bidiagonal(A::Bidiagonal) = A + function getindex(A::Bidiagonal{T}, i::Integer, j::Integer) where T if !((1 <= i <= size(A,2)) && (1 <= j <= size(A,2))) throw(BoundsError(A,(i,j))) @@ -131,7 +133,7 @@ function Base.replace_in_print_matrix(A::Bidiagonal,i::Integer,j::Integer,s::Abs end #Converting from Bidiagonal to dense Matrix -function convert(::Type{Matrix{T}}, A::Bidiagonal) where T +function Matrix{T}(A::Bidiagonal) where T n = size(A, 1) B = zeros(T, n, n) for i = 1:n - 1 @@ -145,15 +147,14 @@ function convert(::Type{Matrix{T}}, A::Bidiagonal) where T B[n,n] = A.dv[n] return B end -convert(::Type{Matrix}, A::Bidiagonal{T}) where {T} = convert(Matrix{T}, A) -convert(::Type{Array}, A::Bidiagonal) = convert(Matrix, A) +Matrix(A::Bidiagonal{T}) where {T} = Matrix{T}(A) +Array(A::Bidiagonal) = Matrix(A) promote_rule(::Type{Matrix{T}}, ::Type{<:Bidiagonal{S}}) where {T,S} = @isdefined(T) && @isdefined(S) ? Matrix{promote_type(T,S)} : Matrix promote_rule(::Type{Matrix}, ::Type{<:Bidiagonal}) = Matrix #Converting from Bidiagonal to Tridiagonal -Tridiagonal(M::Bidiagonal{T}) where {T} = convert(Tridiagonal{T}, M) -function convert(::Type{Tridiagonal{T}}, A::Bidiagonal) where T +function Tridiagonal{T}(A::Bidiagonal) where T dv = convert(AbstractVector{T}, A.dv) ev = convert(AbstractVector{T}, A.ev) z = fill!(similar(ev), zero(T)) @@ -164,12 +165,12 @@ promote_rule(::Type{<:Tridiagonal{T}}, ::Type{<:Bidiagonal{S}}) where {T,S} = promote_rule(::Type{<:Tridiagonal}, ::Type{<:Bidiagonal}) = Tridiagonal # No-op for trivial conversion Bidiagonal{T} -> Bidiagonal{T} -convert(::Type{Bidiagonal{T}}, A::Bidiagonal{T}) where {T} = A +Bidiagonal{T}(A::Bidiagonal{T}) where {T} = A # Convert Bidiagonal to Bidiagonal{T} by constructing a new instance with converted elements -convert(::Type{Bidiagonal{T}}, A::Bidiagonal) where {T} = +Bidiagonal{T}(A::Bidiagonal) where {T} = Bidiagonal(convert(AbstractVector{T}, A.dv), convert(AbstractVector{T}, A.ev), A.uplo) # When asked to convert Bidiagonal to AbstractMatrix{T}, preserve structure by converting to Bidiagonal{T} <: AbstractMatrix{T} -convert(::Type{AbstractMatrix{T}}, A::Bidiagonal) where {T} = convert(Bidiagonal{T}, A) +AbstractMatrix{T}(A::Bidiagonal) where {T} = convert(Bidiagonal{T}, A) broadcast(::typeof(big), B::Bidiagonal) = Bidiagonal(big.(B.dv), big.(B.ev), B.uplo) diff --git a/base/linalg/cholesky.jl b/base/linalg/cholesky.jl index 3a8f1705e8914..8e1d338aa9781 100644 --- a/base/linalg/cholesky.jl +++ b/base/linalg/cholesky.jl @@ -349,30 +349,30 @@ function cholfact(x::Number, uplo::Symbol=:U) end -function convert(::Type{Cholesky{T}}, C::Cholesky) where T +function Cholesky{T}(C::Cholesky) where T Cnew = convert(AbstractMatrix{T}, C.factors) Cholesky{T, typeof(Cnew)}(Cnew, C.uplo, C.info) end -convert(::Type{Factorization{T}}, C::Cholesky{T}) where {T} = C -convert(::Type{Factorization{T}}, C::Cholesky) where {T} = convert(Cholesky{T}, C) -convert(::Type{CholeskyPivoted{T}},C::CholeskyPivoted{T}) where {T} = C -convert(::Type{CholeskyPivoted{T}},C::CholeskyPivoted) where {T} = +Factorization{T}(C::Cholesky{T}) where {T} = C +Factorization{T}(C::Cholesky) where {T} = Cholesky{T}(C) +CholeskyPivoted{T}(C::CholeskyPivoted{T}) where {T} = C +CholeskyPivoted{T}(C::CholeskyPivoted) where {T} = CholeskyPivoted(AbstractMatrix{T}(C.factors),C.uplo,C.piv,C.rank,C.tol,C.info) -convert(::Type{Factorization{T}}, C::CholeskyPivoted{T}) where {T} = C -convert(::Type{Factorization{T}}, C::CholeskyPivoted) where {T} = convert(CholeskyPivoted{T}, C) +Factorization{T}(C::CholeskyPivoted{T}) where {T} = C +Factorization{T}(C::CholeskyPivoted) where {T} = CholeskyPivoted{T}(C) -convert(::Type{AbstractMatrix}, C::Cholesky) = C.uplo == 'U' ? C[:U]'C[:U] : C[:L]*C[:L]' -convert(::Type{AbstractArray}, C::Cholesky) = convert(AbstractMatrix, C) -convert(::Type{Matrix}, C::Cholesky) = convert(Array, convert(AbstractArray, C)) -convert(::Type{Array}, C::Cholesky) = convert(Matrix, C) +AbstractMatrix(C::Cholesky) = C.uplo == 'U' ? C[:U]'C[:U] : C[:L]*C[:L]' +AbstractArray(C::Cholesky) = AbstractMatrix(C) +Matrix(C::Cholesky) = Array(AbstractArray(C)) +Array(C::Cholesky) = Matrix(C) -function convert(::Type{AbstractMatrix}, F::CholeskyPivoted) +function AbstractMatrix(F::CholeskyPivoted) ip = invperm(F[:p]) (F[:L] * F[:U])[ip,ip] end -convert(::Type{AbstractArray}, F::CholeskyPivoted) = convert(AbstractMatrix, F) -convert(::Type{Matrix}, F::CholeskyPivoted) = convert(Array, convert(AbstractArray, F)) -convert(::Type{Array}, F::CholeskyPivoted) = convert(Matrix, F) +AbstractArray(F::CholeskyPivoted) = AbstractMatrix(F) +Matrix(F::CholeskyPivoted) = Array(AbstractArray(F)) +Array(F::CholeskyPivoted) = Matrix(F) copy(C::Cholesky) = Cholesky(copy(C.factors), C.uplo, C.info) copy(C::CholeskyPivoted) = CholeskyPivoted(copy(C.factors), C.uplo, C.piv, C.rank, C.tol, C.info) diff --git a/base/linalg/diagonal.jl b/base/linalg/diagonal.jl index a1190103df936..e2624f487e88b 100644 --- a/base/linalg/diagonal.jl +++ b/base/linalg/diagonal.jl @@ -49,11 +49,11 @@ Diagonal(V::AbstractVector{T}) where {T} = Diagonal{T,typeof(V)}(V) Diagonal{T}(V::AbstractVector{T}) where {T} = Diagonal{T,typeof(V)}(V) Diagonal{T}(V::AbstractVector) where {T} = Diagonal{T}(convert(AbstractVector{T}, V)) -convert(::Type{Diagonal{T}}, D::Diagonal{T}) where {T} = D -convert(::Type{Diagonal{T}}, D::Diagonal) where {T} = Diagonal{T}(convert(AbstractVector{T}, D.diag)) -convert(::Type{AbstractMatrix{T}}, D::Diagonal) where {T} = convert(Diagonal{T}, D) -convert(::Type{Matrix}, D::Diagonal) = diagm(0 => D.diag) -convert(::Type{Array}, D::Diagonal) = convert(Matrix, D) +Diagonal{T}(D::Diagonal{T}) where {T} = D +Diagonal{T}(D::Diagonal) where {T} = Diagonal{T}(convert(AbstractVector{T}, D.diag)) +AbstractMatrix{T}(D::Diagonal) where {T} = Diagonal{T}(D) +Matrix(D::Diagonal) = diagm(0 => D.diag) +Array(D::Diagonal) = Matrix(D) # For D<:Diagonal, similar(D[, neweltype]) should yield a Diagonal matrix. # On the other hand, similar(D, [neweltype,] shape...) should yield a sparse matrix. diff --git a/base/linalg/eigen.jl b/base/linalg/eigen.jl index 2c92c9fa4ba55..d30fae6e6080b 100644 --- a/base/linalg/eigen.jl +++ b/base/linalg/eigen.jl @@ -526,7 +526,7 @@ eigvecs(A::AbstractMatrix, B::AbstractMatrix) = eigvecs(eigfact(A, B)) # Conversion methods ## Can we determine the source/result is Real? This is not stored in the type Eigen -convert(::Type{AbstractMatrix}, F::Eigen) = F.vectors * Diagonal(F.values) / F.vectors -convert(::Type{AbstractArray}, F::Eigen) = convert(AbstractMatrix, F) -convert(::Type{Matrix}, F::Eigen) = convert(Array, convert(AbstractArray, F)) -convert(::Type{Array}, F::Eigen) = convert(Matrix, F) +AbstractMatrix(F::Eigen) = F.vectors * Diagonal(F.values) / F.vectors +AbstractArray(F::Eigen) = AbstractMatrix(F) +Matrix(F::Eigen) = Array(AbstractArray(F)) +Array(F::Eigen) = Matrix(F) diff --git a/base/linalg/factorization.jl b/base/linalg/factorization.jl index 1eedc04270415..3bef6499d1bb9 100644 --- a/base/linalg/factorization.jl +++ b/base/linalg/factorization.jl @@ -45,8 +45,13 @@ function det(F::Factorization) return exp(d)*s end +convert(::Type{T}, f::T) where {T<:Factorization} = f +convert(::Type{T}, f::Factorization) where {T<:Factorization} = T(f) + +convert(::Type{T}, f::Factorization) where {T<:AbstractArray} = T(f) + ### General promotion rules -convert(::Type{Factorization{T}}, F::Factorization{T}) where {T} = F +Factorization{T}(F::Factorization{T}) where {T} = F inv(F::Factorization{T}) where {T} = (n = size(F, 1); ldiv!(F, Matrix{T}(I, n, n))) Base.hash(F::Factorization, h::UInt) = mapreduce(f -> hash(getfield(F, f)), hash, h, 1:nfields(F)) diff --git a/base/linalg/givens.jl b/base/linalg/givens.jl index 539f5694351d9..daa3cebb0416d 100644 --- a/base/linalg/givens.jl +++ b/base/linalg/givens.jl @@ -37,12 +37,15 @@ mutable struct Rotation{T} <: AbstractRotation{T} rotations::Vector{Givens{T}} end -convert(::Type{Givens{T}}, G::Givens{T}) where {T} = G -convert(::Type{Givens{T}}, G::Givens) where {T} = Givens(G.i1, G.i2, convert(T, G.c), convert(T, G.s)) -convert(::Type{Rotation{T}}, R::Rotation{T}) where {T} = R -convert(::Type{Rotation{T}}, R::Rotation) where {T} = Rotation{T}([convert(Givens{T}, g) for g in R.rotations]) -convert(::Type{AbstractRotation{T}}, G::Givens) where {T} = convert(Givens{T}, G) -convert(::Type{AbstractRotation{T}}, R::Rotation) where {T} = convert(Rotation{T}, R) +convert(::Type{T}, r::T) where {T<:AbstractRotation} = r +convert(::Type{T}, r::AbstractRotation) where {T<:AbstractRotation} = T(r) + +Givens{T}(G::Givens{T}) where {T} = G +Givens{T}(G::Givens) where {T} = Givens(G.i1, G.i2, convert(T, G.c), convert(T, G.s)) +Rotation{T}(R::Rotation{T}) where {T} = R +Rotation{T}(R::Rotation) where {T} = Rotation{T}([Givens{T}(g) for g in R.rotations]) +AbstractRotation{T}(G::Givens) where {T} = Givens{T}(G) +AbstractRotation{T}(R::Rotation) where {T} = Rotation{T}(R) adjoint(G::Givens) = Givens(G.i1, G.i2, conj(G.c), -G.s) adjoint(R::Rotation{T}) where {T} = Rotation{T}(reverse!([adjoint(r) for r in R.rotations])) diff --git a/base/linalg/hessenberg.jl b/base/linalg/hessenberg.jl index 1d13fb7eb591f..6c253b3aff39d 100644 --- a/base/linalg/hessenberg.jl +++ b/base/linalg/hessenberg.jl @@ -75,12 +75,12 @@ function getindex(A::HessenbergQ, i::Integer, j::Integer) end ## reconstruct the original matrix -convert(::Type{Matrix}, A::HessenbergQ{<:BlasFloat}) = LAPACK.orghr!(1, size(A.factors, 1), copy(A.factors), A.τ) -convert(::Type{Array}, A::HessenbergQ) = convert(Matrix, A) -convert(::Type{AbstractMatrix}, F::Hessenberg) = (fq = Array(F[:Q]); (fq * F[:H]) * fq') -convert(::Type{AbstractArray}, F::Hessenberg) = convert(AbstractMatrix, F) -convert(::Type{Matrix}, F::Hessenberg) = convert(Array, convert(AbstractArray, F)) -convert(::Type{Array}, F::Hessenberg) = convert(Matrix, F) +Matrix(A::HessenbergQ{<:BlasFloat}) = LAPACK.orghr!(1, size(A.factors, 1), copy(A.factors), A.τ) +Array(A::HessenbergQ) = Matrix(A) +AbstractMatrix(F::Hessenberg) = (fq = Array(F[:Q]); (fq * F[:H]) * fq') +AbstractArray(F::Hessenberg) = AbstractMatrix(F) +Matrix(F::Hessenberg) = Array(AbstractArray(F)) +Array(F::Hessenberg) = Matrix(F) mul!(Q::HessenbergQ{T}, X::StridedVecOrMat{T}) where {T<:BlasFloat} = LAPACK.ormhr!('L', 'N', 1, size(Q.factors, 1), Q.factors, Q.τ, X) diff --git a/base/linalg/ldlt.jl b/base/linalg/ldlt.jl index d8bc1f38c979a..7db241411102f 100644 --- a/base/linalg/ldlt.jl +++ b/base/linalg/ldlt.jl @@ -7,13 +7,13 @@ end size(S::LDLt) = size(S.data) size(S::LDLt, i::Integer) = size(S.data, i) -convert(::Type{LDLt{T,S}}, F::LDLt) where {T,S} = LDLt{T,S}(convert(S, F.data)) +LDLt{T,S}(F::LDLt) where {T,S<:AbstractMatrix} = LDLt{T,S}(convert(S, F.data)) # NOTE: the annotaion <:AbstractMatrix shouldn't be necessary, it is introduced # to avoid an ambiguity warning (see issue #6383) -convert(::Type{LDLt{T}}, F::LDLt{S,U}) where {T,S,U<:AbstractMatrix} = convert(LDLt{T,U}, F) +LDLt{T}(F::LDLt{S,U}) where {T,S,U<:AbstractMatrix} = LDLt{T,U}(F) -convert(::Type{Factorization{T}}, F::LDLt{T}) where {T} = F -convert(::Type{Factorization{T}}, F::LDLt{S,U}) where {T,S,U} = convert(LDLt{T,U}, F) +Factorization{T}(F::LDLt{T}) where {T} = F +Factorization{T}(F::LDLt{S,U}) where {T,S,U} = LDLt{T,U}(F) # SymTridiagonal """ @@ -86,7 +86,7 @@ julia> S \\ b """ function ldltfact(M::SymTridiagonal{T}) where T S = typeof(zero(T)/one(T)) - return S == T ? ldltfact!(copy(M)) : ldltfact!(convert(SymTridiagonal{S}, M)) + return S == T ? ldltfact!(copy(M)) : ldltfact!(SymTridiagonal{S}(M)) end factorize(S::SymTridiagonal) = ldltfact(S) @@ -127,14 +127,14 @@ function logabsdet(F::LDLt{<:Any,<:SymTridiagonal}) end # Conversion methods -function convert(::Type{SymTridiagonal}, F::LDLt) +function SymTridiagonal(F::LDLt) e = copy(F.data.ev) d = copy(F.data.dv) e .*= d[1:end-1] d[2:end] += e .* F.data.ev SymTridiagonal(d, e) end -convert(::Type{AbstractMatrix}, F::LDLt) = convert(SymTridiagonal, F) -convert(::Type{AbstractArray}, F::LDLt) = convert(AbstractMatrix, F) -convert(::Type{Matrix}, F::LDLt) = convert(Array, convert(AbstractArray, F)) -convert(::Type{Array}, F::LDLt) = convert(Matrix, F) +AbstractMatrix(F::LDLt) = SymTridiagonal(F) +AbstractArray(F::LDLt) = AbstractMatrix(F) +Matrix(F::LDLt) = Array(AbstractArray(F)) +Array(F::LDLt) = Matrix(F) diff --git a/base/linalg/lq.jl b/base/linalg/lq.jl index d4424900dbd9a..e91f0cfea2947 100644 --- a/base/linalg/lq.jl +++ b/base/linalg/lq.jl @@ -62,13 +62,13 @@ end copy(A::LQ) = LQ(copy(A.factors), copy(A.τ)) -convert(::Type{LQ{T}},A::LQ) where {T} = LQ(convert(AbstractMatrix{T}, A.factors), convert(Vector{T}, A.τ)) -convert(::Type{Factorization{T}}, A::LQ{T}) where {T} = A -convert(::Type{Factorization{T}}, A::LQ) where {T} = convert(LQ{T}, A) -convert(::Type{AbstractMatrix}, A::LQ) = A[:L]*A[:Q] -convert(::Type{AbstractArray}, A::LQ) = convert(AbstractMatrix, A) -convert(::Type{Matrix}, A::LQ) = convert(Array, convert(AbstractArray, A)) -convert(::Type{Array}, A::LQ) = convert(Matrix, A) +LQ{T}(A::LQ) where {T} = LQ(convert(AbstractMatrix{T}, A.factors), convert(Vector{T}, A.τ)) +Factorization{T}(A::LQ{T}) where {T} = A +Factorization{T}(A::LQ) where {T} = LQ{T}(A) +AbstractMatrix(A::LQ) = A[:L]*A[:Q] +AbstractArray(A::LQ) = AbstractMatrix(A) +Matrix(A::LQ) = Array(AbstractArray(A)) +Array(A::LQ) = Matrix(A) adjoint(A::LQ{T}) where {T} = QR{T,typeof(A.factors)}(adjoint(A.factors), A.τ) @@ -95,10 +95,10 @@ function show(io::IO, C::LQ) show(io, C[:Q]) end -convert(::Type{LQPackedQ{T}}, Q::LQPackedQ) where {T} = LQPackedQ(convert(AbstractMatrix{T}, Q.factors), convert(Vector{T}, Q.τ)) -convert(::Type{AbstractMatrix{T}}, Q::LQPackedQ) where {T} = convert(LQPackedQ{T}, Q) -convert(::Type{Matrix}, A::LQPackedQ) = LAPACK.orglq!(copy(A.factors),A.τ) -convert(::Type{Array}, A::LQPackedQ) = convert(Matrix, A) +LQPackedQ{T}(Q::LQPackedQ) where {T} = LQPackedQ(convert(AbstractMatrix{T}, Q.factors), convert(Vector{T}, Q.τ)) +AbstractMatrix{T}(Q::LQPackedQ) where {T} = LQPackedQ{T}(Q) +Matrix(A::LQPackedQ) = LAPACK.orglq!(copy(A.factors),A.τ) +Array(A::LQPackedQ) = Matrix(A) size(A::LQ, dim::Integer) = size(A.factors, dim) size(A::LQ) = size(A.factors) @@ -128,15 +128,15 @@ mul!(A::QR{T}, B::LQ{T}) where {T<:BlasFloat} = mul!(zeros(eltype(A), size(A)), Matrix(A), Matrix(B)) function *(A::LQ{TA}, B::StridedVecOrMat{TB}) where {TA,TB} TAB = promote_type(TA, TB) - mul!(convert(Factorization{TAB},A), copy_oftype(B, TAB)) + mul!(Factorization{TAB}(A), copy_oftype(B, TAB)) end function *(A::LQ{TA},B::QR{TB}) where {TA,TB} TAB = promote_type(TA, TB) - mul!(convert(Factorization{TAB},A), convert(Factorization{TAB},B)) + mul!(Factorization{TAB}(A), Factorization{TAB}(B)) end function *(A::QR{TA},B::LQ{TB}) where {TA,TB} TAB = promote_type(TA, TB) - mul!(convert(Factorization{TAB},A), convert(Factorization{TAB},B)) + mul!(Factorization{TAB}(A), Factorization{TAB}(B)) end *(A::Adjoint{<:Any,<:LQ}, B::LQ) = adjoint(A.parent) * B *(A::LQ, B::Adjoint{<:Any,<:LQ}) = A * adjoint(B.parent) @@ -146,7 +146,7 @@ end mul!(A::LQPackedQ{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = LAPACK.ormlq!('L','N',A.factors,A.τ,B) function (*)(A::LQPackedQ, B::StridedVecOrMat) TAB = promote_type(eltype(A), eltype(B)) - mul!(convert(AbstractMatrix{TAB}, A), copy_oftype(B, TAB)) + mul!(AbstractMatrix{TAB}(A), copy_oftype(B, TAB)) end ### QcB @@ -158,9 +158,9 @@ function *(adjA::Adjoint{<:Any,<:LQPackedQ}, B::StridedVecOrMat) A = adjA.parent TAB = promote_type(eltype(A), eltype(B)) if size(B,1) == size(A.factors,2) - mul!(Adjoint(convert(AbstractMatrix{TAB}, A)), copy_oftype(B, TAB)) + mul!(Adjoint(AbstractMatrix{TAB}(A)), copy_oftype(B, TAB)) elseif size(B,1) == size(A.factors,1) - mul!(Adjoint(convert(AbstractMatrix{TAB}, A)), [B; zeros(TAB, size(A.factors, 2) - size(A.factors, 1), size(B, 2))]) + mul!(Adjoint(AbstractMatrix{TAB}(A)), [B; zeros(TAB, size(A.factors, 2) - size(A.factors, 1), size(B, 2))]) else throw(DimensionMismatch("first dimension of B, $(size(B,1)), must equal one of the dimensions of A, $(size(A))")) end @@ -209,13 +209,13 @@ mul!(A::StridedMatrix{T}, adjB::Adjoint{<:Any,<:LQPackedQ{T}}) where {T<:BlasCom function *(A::StridedVecOrMat, adjQ::Adjoint{<:Any,<:LQPackedQ}) Q = adjQ.parent TR = promote_type(eltype(A), eltype(Q)) - return mul!(copy_oftype(A, TR), Adjoint(convert(AbstractMatrix{TR}, Q))) + return mul!(copy_oftype(A, TR), Adjoint(AbstractMatrix{TR}(Q))) end function *(adjA::Adjoint{<:Any,<:StridedMatrix}, adjQ::Adjoint{<:Any,<:LQPackedQ}) A, Q = adjA.parent, adjQ.parent TR = promote_type(eltype(A), eltype(Q)) C = adjoint!(similar(A, TR, reverse(size(A))), A) - return mul!(C, Adjoint(convert(AbstractMatrix{TR}, Q))) + return mul!(C, Adjoint(AbstractMatrix{TR}(Q))) end # # (2) the inner dimension in the multiplication is the LQPackedQ's first dimension. @@ -240,7 +240,7 @@ function *(A::StridedVecOrMat, Q::LQPackedQ) else _rightappdimmismatch("columns") end - return mul!(C, convert(AbstractMatrix{TR}, Q)) + return mul!(C, AbstractMatrix{TR}(Q)) end function *(adjA::Adjoint{<:Any,<:StridedMatrix}, Q::LQPackedQ) A = adjA.parent @@ -253,7 +253,7 @@ function *(adjA::Adjoint{<:Any,<:StridedMatrix}, Q::LQPackedQ) else _rightappdimmismatch("rows") end - return mul!(C, convert(AbstractMatrix{TR}, Q)) + return mul!(C, AbstractMatrix{TR}(Q)) end _rightappdimmismatch(rowsorcols) = throw(DimensionMismatch(string("the number of $(rowsorcols) of the matrix on the left ", @@ -266,7 +266,7 @@ function (\)(A::LQ{TA}, b::StridedVector{Tb}) where {TA,Tb} S = promote_type(TA,Tb) m = checksquare(A) m == length(b) || throw(DimensionMismatch("left hand side has $m rows, but right hand side has length $(length(b))")) - AA = convert(Factorization{S}, A) + AA = Factorization{S}(A) x = ldiv!(AA, copy_oftype(b, S)) return x end @@ -274,7 +274,7 @@ function (\)(A::LQ{TA},B::StridedMatrix{TB}) where {TA,TB} S = promote_type(TA,TB) m = checksquare(A) m == size(B,1) || throw(DimensionMismatch("left hand side has $m rows, but right hand side has $(size(B,1)) rows")) - AA = convert(Factorization{S}, A) + AA = Factorization{S}(A) X = ldiv!(AA, copy_oftype(B, S)) return X end diff --git a/base/linalg/lu.jl b/base/linalg/lu.jl index d8ca0dae38494..838b46d1552ef 100644 --- a/base/linalg/lu.jl +++ b/base/linalg/lu.jl @@ -227,13 +227,13 @@ function lu(A::AbstractMatrix, pivot::Union{Val{false}, Val{true}} = Val(true)) F[:L], F[:U], F[:p] end -function convert(::Type{LU{T}}, F::LU) where T +function LU{T}(F::LU) where T M = convert(AbstractMatrix{T}, F.factors) LU{T,typeof(M)}(M, F.ipiv, F.info) end -convert(::Type{LU{T,S}}, F::LU) where {T,S} = LU{T,S}(convert(S, F.factors), F.ipiv, F.info) -convert(::Type{Factorization{T}}, F::LU{T}) where {T} = F -convert(::Type{Factorization{T}}, F::LU) where {T} = convert(LU{T}, F) +LU{T,S}(F::LU) where {T,S} = LU{T,S}(convert(S, F.factors), F.ipiv, F.info) +Factorization{T}(F::LU{T}) where {T} = F +Factorization{T}(F::LU) where {T} = LU{T}(F) copy(A::LU{T,S}) where {T,S} = LU{T,S}(copy(A.factors), copy(A.ipiv), A.info) @@ -593,12 +593,12 @@ end /(B::AbstractMatrix,A::LU) = transpose(Transpose(A) \ Transpose(B)) # Conversions -convert(::Type{AbstractMatrix}, F::LU) = (F[:L] * F[:U])[invperm(F[:p]),:] -convert(::Type{AbstractArray}, F::LU) = convert(AbstractMatrix, F) -convert(::Type{Matrix}, F::LU) = convert(Array, convert(AbstractArray, F)) -convert(::Type{Array}, F::LU) = convert(Matrix, F) +AbstractMatrix(F::LU) = (F[:L] * F[:U])[invperm(F[:p]),:] +AbstractArray(F::LU) = AbstractMatrix(F) +Matrix(F::LU) = Array(AbstractArray(F)) +Array(F::LU) = Matrix(F) -function convert(::Type{Tridiagonal}, F::Base.LinAlg.LU{T,Tridiagonal{T,V}}) where {T,V} +function Tridiagonal(F::Base.LinAlg.LU{T,Tridiagonal{T,V}}) where {T,V} n = size(F, 1) dl = copy(F.factors.dl) @@ -632,11 +632,7 @@ function convert(::Type{Tridiagonal}, F::Base.LinAlg.LU{T,Tridiagonal{T,V}}) whe end return Tridiagonal(dl, d, du) end -convert(::Type{AbstractMatrix}, F::LU{T,Tridiagonal{T,V}}) where {T,V} = - convert(Tridiagonal, F) -convert(::Type{AbstractArray}, F::LU{T,Tridiagonal{T,V}}) where {T,V} = - convert(AbstractMatrix, F) -convert(::Type{Matrix}, F::LU{T,Tridiagonal{T,V}}) where {T,V} = - convert(Array, convert(AbstractArray, F)) -convert(::Type{Array}, F::LU{T,Tridiagonal{T,V}}) where {T,V} = - convert(Matrix, F) +AbstractMatrix(F::LU{T,Tridiagonal{T,V}}) where {T,V} = Tridiagonal(F) +AbstractArray(F::LU{T,Tridiagonal{T,V}}) where {T,V} = AbstractMatrix(F) +Matrix(F::LU{T,Tridiagonal{T,V}}) where {T,V} = Array(AbstractArray(F)) +Array(F::LU{T,Tridiagonal{T,V}}) where {T,V} = Matrix(F) diff --git a/base/linalg/qr.jl b/base/linalg/qr.jl index 435f2a67ac12e..9c2f0c0ee76fc 100644 --- a/base/linalg/qr.jl +++ b/base/linalg/qr.jl @@ -404,23 +404,23 @@ function qr!(v::AbstractVector) end # Conversions -convert(::Type{QR{T}}, A::QR) where {T} = QR(convert(AbstractMatrix{T}, A.factors), convert(Vector{T}, A.τ)) -convert(::Type{Factorization{T}}, A::QR{T}) where {T} = A -convert(::Type{Factorization{T}}, A::QR) where {T} = convert(QR{T}, A) -convert(::Type{QRCompactWY{T}}, A::QRCompactWY) where {T} = QRCompactWY(convert(AbstractMatrix{T}, A.factors), convert(AbstractMatrix{T}, A.T)) -convert(::Type{Factorization{T}}, A::QRCompactWY{T}) where {T} = A -convert(::Type{Factorization{T}}, A::QRCompactWY) where {T} = convert(QRCompactWY{T}, A) -convert(::Type{AbstractMatrix}, F::Union{QR,QRCompactWY}) = F[:Q] * F[:R] -convert(::Type{AbstractArray}, F::Union{QR,QRCompactWY}) = convert(AbstractMatrix, F) -convert(::Type{Matrix}, F::Union{QR,QRCompactWY}) = convert(Array, convert(AbstractArray, F)) -convert(::Type{Array}, F::Union{QR,QRCompactWY}) = convert(Matrix, F) -convert(::Type{QRPivoted{T}}, A::QRPivoted) where {T} = QRPivoted(convert(AbstractMatrix{T}, A.factors), convert(Vector{T}, A.τ), A.jpvt) -convert(::Type{Factorization{T}}, A::QRPivoted{T}) where {T} = A -convert(::Type{Factorization{T}}, A::QRPivoted) where {T} = convert(QRPivoted{T}, A) -convert(::Type{AbstractMatrix}, F::QRPivoted) = (F[:Q] * F[:R])[:,invperm(F[:p])] -convert(::Type{AbstractArray}, F::QRPivoted) = convert(AbstractMatrix, F) -convert(::Type{Matrix}, F::QRPivoted) = convert(Array, convert(AbstractArray, F)) -convert(::Type{Array}, F::QRPivoted) = convert(Matrix, F) +QR{T}(A::QR) where {T} = QR(convert(AbstractMatrix{T}, A.factors), convert(Vector{T}, A.τ)) +Factorization{T}(A::QR{T}) where {T} = A +Factorization{T}(A::QR) where {T} = QR{T}(A) +QRCompactWY{T}(A::QRCompactWY) where {T} = QRCompactWY(convert(AbstractMatrix{T}, A.factors), convert(AbstractMatrix{T}, A.T)) +Factorization{T}(A::QRCompactWY{T}) where {T} = A +Factorization{T}(A::QRCompactWY) where {T} = QRCompactWY{T}(A) +AbstractMatrix(F::Union{QR,QRCompactWY}) = F[:Q] * F[:R] +AbstractArray(F::Union{QR,QRCompactWY}) = AbstractMatrix(F) +Matrix(F::Union{QR,QRCompactWY}) = Array(AbstractArray(F)) +Array(F::Union{QR,QRCompactWY}) = Matrix(F) +QRPivoted{T}(A::QRPivoted) where {T} = QRPivoted(convert(AbstractMatrix{T}, A.factors), convert(Vector{T}, A.τ), A.jpvt) +Factorization{T}(A::QRPivoted{T}) where {T} = A +Factorization{T}(A::QRPivoted) where {T} = QRPivoted{T}(A) +AbstractMatrix(F::QRPivoted) = (F[:Q] * F[:R])[:,invperm(F[:p])] +AbstractArray(F::QRPivoted) = AbstractMatrix(F) +Matrix(F::QRPivoted) = Array(AbstractArray(F)) +Array(F::QRPivoted) = Matrix(F) function show(io::IO, F::Union{QR, QRCompactWY, QRPivoted}) println(io, "$(typeof(F)) with factors Q and R:") @@ -502,14 +502,14 @@ struct QRCompactWYQ{S, M<:AbstractMatrix} <: AbstractQ{S} end QRCompactWYQ(factors::AbstractMatrix{S}, T::Matrix{S}) where {S} = QRCompactWYQ{S,typeof(factors)}(factors, T) -convert(::Type{QRPackedQ{T}}, Q::QRPackedQ) where {T} = QRPackedQ(convert(AbstractMatrix{T}, Q.factors), convert(Vector{T}, Q.τ)) -convert(::Type{AbstractMatrix{T}}, Q::QRPackedQ{T}) where {T} = Q -convert(::Type{AbstractMatrix{T}}, Q::QRPackedQ) where {T} = convert(QRPackedQ{T}, Q) -convert(::Type{QRCompactWYQ{S}}, Q::QRCompactWYQ) where {S} = QRCompactWYQ(convert(AbstractMatrix{S}, Q.factors), convert(AbstractMatrix{S}, Q.T)) -convert(::Type{AbstractMatrix{S}}, Q::QRCompactWYQ{S}) where {S} = Q -convert(::Type{AbstractMatrix{S}}, Q::QRCompactWYQ) where {S} = convert(QRCompactWYQ{S}, Q) -convert(::Type{Matrix}, A::AbstractQ{T}) where {T} = mul!(A, Matrix{T}(I, size(A.factors, 1), min(size(A.factors)...))) -convert(::Type{Array}, A::AbstractQ) = convert(Matrix, A) +QRPackedQ{T}(Q::QRPackedQ) where {T} = QRPackedQ(convert(AbstractMatrix{T}, Q.factors), convert(Vector{T}, Q.τ)) +AbstractMatrix{T}(Q::QRPackedQ{T}) where {T} = Q +AbstractMatrix{T}(Q::QRPackedQ) where {T} = QRPackedQ{T}(Q) +QRCompactWYQ{S}(Q::QRCompactWYQ) where {S} = QRCompactWYQ(convert(AbstractMatrix{S}, Q.factors), convert(AbstractMatrix{S}, Q.T)) +AbstractMatrix{S}(Q::QRCompactWYQ{S}) where {S} = Q +AbstractMatrix{S}(Q::QRCompactWYQ) where {S} = QRCompactWYQ{S}(Q) +Matrix(A::AbstractQ{T}) where {T} = mul!(A, Matrix{T}(I, size(A.factors, 1), min(size(A.factors)...))) +Array(A::AbstractQ) = Matrix(A) size(A::Union{QR,QRCompactWY,QRPivoted}, dim::Integer) = size(A.factors, dim) size(A::Union{QR,QRCompactWY,QRPivoted}) = size(A.factors) @@ -857,7 +857,7 @@ function (\)(A::Union{QR{TA},QRCompactWY{TA},QRPivoted{TA}}, B::AbstractVecOrMat m, n = size(A) m == size(B,1) || throw(DimensionMismatch("left hand side has $m rows, but right hand side has $(size(B,1)) rows")) - AA = convert(Factorization{S}, A) + AA = Factorization{S}(A) X = _zeros(S, B, n) X[1:size(B, 1), :] = B diff --git a/base/linalg/rowvector.jl b/base/linalg/rowvector.jl index 0ad9ca8a69a35..89170bc29fd72 100644 --- a/base/linalg/rowvector.jl +++ b/base/linalg/rowvector.jl @@ -84,7 +84,7 @@ const ConjRowVector{T,CV<:ConjVector} = RowVector{T,CV} error("RowVector expects 1×N size, got $n") # Conversion of underlying storage -convert(::Type{RowVector{T,V}}, rowvec::RowVector) where {T,V<:AbstractVector} = +RowVector{T,V}(rowvec::RowVector) where {T,V<:AbstractVector} = RowVector{T,V}(convert(V,rowvec.vec)) # similar tries to maintain the RowVector wrapper and the parent type diff --git a/base/linalg/schur.jl b/base/linalg/schur.jl index 73fa0c5f6cf89..6458d45592e91 100644 --- a/base/linalg/schur.jl +++ b/base/linalg/schur.jl @@ -295,10 +295,10 @@ function schur(A::StridedMatrix, B::StridedMatrix) end # Conversion -convert(::Type{AbstractMatrix}, F::Schur) = (F.Z * F.T) * F.Z' -convert(::Type{AbstractArray}, F::Schur) = convert(AbstractMatrix, F) -convert(::Type{Matrix}, F::Schur) = convert(Array, convert(AbstractArray, F)) -convert(::Type{Array}, F::Schur) = convert(Matrix, F) +AbstractMatrix(F::Schur) = (F.Z * F.T) * F.Z' +AbstractArray(F::Schur) = AbstractMatrix(F) +Matrix(F::Schur) = Array(AbstractArray(F)) +Array(F::Schur) = Matrix(F) copy(F::Schur) = Schur(copy(F.T), copy(F.Z), copy(F.values)) copy(F::GeneralizedSchur) = GeneralizedSchur(copy(F.S), copy(F.T), copy(F.alpha), copy(F.beta), copy(F.Q), copy(F.Z)) diff --git a/base/linalg/special.jl b/base/linalg/special.jl index 364518507f04f..40d13824fbcbf 100644 --- a/base/linalg/special.jl +++ b/base/linalg/special.jl @@ -6,58 +6,54 @@ # Interconversion between special matrix types # conversions from Diagonal to other special matrix types -convert(::Type{Bidiagonal}, A::Diagonal) = - Bidiagonal(A.diag, fill!(similar(A.diag, length(A.diag)-1), 0), :U) -convert(::Type{SymTridiagonal}, A::Diagonal) = - SymTridiagonal(A.diag, fill!(similar(A.diag, length(A.diag)-1), 0)) -convert(::Type{Tridiagonal}, A::Diagonal) = - Tridiagonal(fill!(similar(A.diag, length(A.diag)-1), 0), A.diag, - fill!(similar(A.diag, length(A.diag)-1), 0)) +Bidiagonal(A::Diagonal) = Bidiagonal(A.diag, fill!(similar(A.diag, length(A.diag)-1), 0), :U) +SymTridiagonal(A::Diagonal) = SymTridiagonal(A.diag, fill!(similar(A.diag, length(A.diag)-1), 0)) +Tridiagonal(A::Diagonal) = Tridiagonal(fill!(similar(A.diag, length(A.diag)-1), 0), A.diag, + fill!(similar(A.diag, length(A.diag)-1), 0)) # conversions from Bidiagonal to other special matrix types -convert(::Type{Diagonal}, A::Bidiagonal) = +Diagonal(A::Bidiagonal) = iszero(A.ev) ? Diagonal(A.dv) : throw(ArgumentError("matrix cannot be represented as Diagonal")) -convert(::Type{SymTridiagonal}, A::Bidiagonal) = +SymTridiagonal(A::Bidiagonal) = iszero(A.ev) ? SymTridiagonal(A.dv, A.ev) : throw(ArgumentError("matrix cannot be represented as SymTridiagonal")) -convert(::Type{Tridiagonal}, A::Bidiagonal) = +Tridiagonal(A::Bidiagonal) = Tridiagonal(A.uplo == 'U' ? fill!(similar(A.ev), 0) : A.ev, A.dv, A.uplo == 'U' ? A.ev : fill!(similar(A.ev), 0)) # conversions from SymTridiagonal to other special matrix types -convert(::Type{Diagonal}, A::SymTridiagonal) = +Diagonal(A::SymTridiagonal) = iszero(A.ev) ? Diagonal(A.dv) : throw(ArgumentError("matrix cannot be represented as Diagonal")) -convert(::Type{Bidiagonal}, A::SymTridiagonal) = +Bidiagonal(A::SymTridiagonal) = iszero(A.ev) ? Bidiagonal(A.dv, A.ev, :U) : throw(ArgumentError("matrix cannot be represented as Bidiagonal")) -convert(::Type{Tridiagonal}, A::SymTridiagonal) = +Tridiagonal(A::SymTridiagonal) = Tridiagonal(copy(A.ev), A.dv, A.ev) # conversions from Tridiagonal to other special matrix types -convert(::Type{Diagonal}, A::Tridiagonal) = +Diagonal(A::Tridiagonal) = iszero(A.dl) && iszero(A.du) ? Diagonal(A.d) : throw(ArgumentError("matrix cannot be represented as Diagonal")) -convert(::Type{Bidiagonal}, A::Tridiagonal) = +Bidiagonal(A::Tridiagonal) = iszero(A.dl) ? Bidiagonal(A.d, A.du, :U) : iszero(A.du) ? Bidiagonal(A.d, A.dl, :L) : throw(ArgumentError("matrix cannot be represented as Bidiagonal")) -convert(::Type{SymTridiagonal}, A::Tridiagonal) = +SymTridiagonal(A::Tridiagonal) = A.dl == A.du ? SymTridiagonal(A.d, A.dl) : throw(ArgumentError("matrix cannot be represented as SymTridiagonal")) # conversions from AbstractTriangular to special matrix types -convert(::Type{Diagonal}, A::AbstractTriangular) = +Diagonal(A::AbstractTriangular) = isdiag(A) ? Diagonal(diag(A)) : throw(ArgumentError("matrix cannot be represented as Diagonal")) -convert(::Type{Bidiagonal}, A::AbstractTriangular) = +Bidiagonal(A::AbstractTriangular) = isbanded(A, 0, 1) ? Bidiagonal(diag(A, 0), diag(A, 1), :U) : # is upper bidiagonal isbanded(A, -1, 0) ? Bidiagonal(diag(A, 0), diag(A, -1), :L) : # is lower bidiagonal throw(ArgumentError("matrix cannot be represented as Bidiagonal")) -convert(::Type{SymTridiagonal}, A::AbstractTriangular) = - convert(SymTridiagonal, convert(Tridiagonal, A)) -convert(::Type{Tridiagonal}, A::AbstractTriangular) = +SymTridiagonal(A::AbstractTriangular) = SymTridiagonal(Tridiagonal(A)) +Tridiagonal(A::AbstractTriangular) = isbanded(A, -1, 1) ? Tridiagonal(diag(A, -1), diag(A, 0), diag(A, 1)) : # is tridiagonal throw(ArgumentError("matrix cannot be represented as Tridiagonal")) diff --git a/base/linalg/svd.jl b/base/linalg/svd.jl index 1ee5eba8ad55b..a6d3bc72adb95 100644 --- a/base/linalg/svd.jl +++ b/base/linalg/svd.jl @@ -544,7 +544,7 @@ end svdvals(x::Number, y::Number) = abs(x/y) # Conversion -convert(::Type{AbstractMatrix}, F::SVD) = (F.U * Diagonal(F.S)) * F.Vt -convert(::Type{AbstractArray}, F::SVD) = convert(AbstractMatrix, F) -convert(::Type{Matrix}, F::SVD) = convert(Array, convert(AbstractArray, F)) -convert(::Type{Array}, F::SVD) = convert(Matrix, F) +AbstractMatrix(F::SVD) = (F.U * Diagonal(F.S)) * F.Vt +AbstractArray(F::SVD) = AbstractMatrix(F) +Matrix(F::SVD) = Array(AbstractArray(F)) +Array(F::SVD) = Matrix(F) diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index 1a23a84298df0..c019375b7cfcf 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -162,23 +162,23 @@ end similar(A::Union{Symmetric,Hermitian}, ::Type{T}, dims::Dims{N}) where {T,N} = similar(parent(A), T, dims) # Conversion -convert(::Type{Matrix}, A::Symmetric) = copytri!(convert(Matrix, copy(A.data)), A.uplo) -function convert(::Type{Matrix}, A::Hermitian) +Matrix(A::Symmetric) = copytri!(convert(Matrix, copy(A.data)), A.uplo) +function Matrix(A::Hermitian) B = copytri!(convert(Matrix, copy(A.data)), A.uplo, true) for i = 1:size(A, 1) B[i,i] = real(B[i,i]) end return B end -convert(::Type{Array}, A::Union{Symmetric,Hermitian}) = convert(Matrix, A) +Array(A::Union{Symmetric,Hermitian}) = convert(Matrix, A) parent(A::HermOrSym) = A.data -convert(::Type{Symmetric{T,S}},A::Symmetric{T,S}) where {T,S<:AbstractMatrix} = A -convert(::Type{Symmetric{T,S}},A::Symmetric) where {T,S<:AbstractMatrix} = Symmetric{T,S}(convert(S,A.data),A.uplo) -convert(::Type{AbstractMatrix{T}}, A::Symmetric) where {T} = Symmetric(convert(AbstractMatrix{T}, A.data), Symbol(A.uplo)) -convert(::Type{Hermitian{T,S}},A::Hermitian{T,S}) where {T,S<:AbstractMatrix} = A -convert(::Type{Hermitian{T,S}},A::Hermitian) where {T,S<:AbstractMatrix} = Hermitian{T,S}(convert(S,A.data),A.uplo) -convert(::Type{AbstractMatrix{T}}, A::Hermitian) where {T} = Hermitian(convert(AbstractMatrix{T}, A.data), Symbol(A.uplo)) +Symmetric{T,S}(A::Symmetric{T,S}) where {T,S<:AbstractMatrix} = A +Symmetric{T,S}(A::Symmetric) where {T,S<:AbstractMatrix} = Symmetric{T,S}(convert(S,A.data),A.uplo) +AbstractMatrix{T}(A::Symmetric) where {T} = Symmetric(convert(AbstractMatrix{T}, A.data), Symbol(A.uplo)) +Hermitian{T,S}(A::Hermitian{T,S}) where {T,S<:AbstractMatrix} = A +Hermitian{T,S}(A::Hermitian) where {T,S<:AbstractMatrix} = Hermitian{T,S}(convert(S,A.data),A.uplo) +AbstractMatrix{T}(A::Hermitian) where {T} = Hermitian(convert(AbstractMatrix{T}, A.data), Symbol(A.uplo)) copy(A::Symmetric{T,S}) where {T,S} = (B = copy(A.data); Symmetric{T,typeof(B)}(B,A.uplo)) copy(A::Hermitian{T,S}) where {T,S} = (B = copy(A.data); Hermitian{T,typeof(B)}(B,A.uplo)) diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index f2d0c5a40e373..7b421e10397fb 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -13,22 +13,20 @@ for t in (:LowerTriangular, :UnitLowerTriangular, :UpperTriangular, data::S end $t(A::$t) = A + $t{T}(A::$t{T}) where {T} = A function $t(A::AbstractMatrix) Base.LinAlg.checksquare(A) return $t{eltype(A), typeof(A)}(A) end - size(A::$t, d) = size(A.data, d) - size(A::$t) = size(A.data) - - convert(::Type{$t{T}}, A::$t{T}) where {T} = A - function convert(::Type{$t{T}}, A::$t) where T + function $t{T}(A::$t) where T Anew = convert(AbstractMatrix{T}, A.data) $t(Anew) end - convert(::Type{AbstractMatrix{T}}, A::$t{T}) where {T} = A - convert(::Type{AbstractMatrix{T}}, A::$t) where {T} = convert($t{T}, A) - convert(::Type{Matrix}, A::$t{T}) where {T} = convert(Matrix{T}, A) + Matrix(A::$t{T}) where {T} = Matrix{T}(A) + + size(A::$t, d) = size(A.data, d) + size(A::$t) = size(A.data) # For A<:AbstractTriangular, similar(A[, neweltype]) should yield a matrix with the same # triangular type and underlying storage type as A. The following method covers these cases. @@ -100,18 +98,18 @@ imag(A::LowerTriangular) = LowerTriangular(imag(A.data)) imag(A::UnitLowerTriangular) = LowerTriangular(tril!(imag(A.data),-1)) imag(A::UnitUpperTriangular) = UpperTriangular(triu!(imag(A.data),1)) -convert(::Type{Array}, A::AbstractTriangular) = convert(Matrix, A) +Array(A::AbstractTriangular) = Matrix(A) parent(A::AbstractTriangular) = A.data # then handle all methods that requires specific handling of upper/lower and unit diagonal -function convert(::Type{Matrix{T}}, A::LowerTriangular) where T +function Matrix{T}(A::LowerTriangular) where T B = Matrix{T}(uninitialized, size(A, 1), size(A, 1)) copyto!(B, A.data) tril!(B) B end -function convert(::Type{Matrix{T}}, A::UnitLowerTriangular) where T +function Matrix{T}(A::UnitLowerTriangular) where T B = Matrix{T}(uninitialized, size(A, 1), size(A, 1)) copyto!(B, A.data) tril!(B) @@ -120,13 +118,13 @@ function convert(::Type{Matrix{T}}, A::UnitLowerTriangular) where T end B end -function convert(::Type{Matrix{T}}, A::UpperTriangular) where T +function Matrix{T}(A::UpperTriangular) where T B = Matrix{T}(uninitialized, size(A, 1), size(A, 1)) copyto!(B, A.data) triu!(B) B end -function convert(::Type{Matrix{T}}, A::UnitUpperTriangular) where T +function Matrix{T}(A::UnitUpperTriangular) where T B = Matrix{T}(uninitialized, size(A, 1), size(A, 1)) copyto!(B, A.data) triu!(B) diff --git a/base/linalg/tridiag.jl b/base/linalg/tridiag.jl index a418a569ef9aa..f238c3918fa25 100644 --- a/base/linalg/tridiag.jl +++ b/base/linalg/tridiag.jl @@ -76,11 +76,11 @@ function SymTridiagonal(A::AbstractMatrix) end end -convert(::Type{SymTridiagonal{T}}, S::SymTridiagonal) where {T} = +SymTridiagonal{T}(S::SymTridiagonal) where {T} = SymTridiagonal(convert(AbstractVector{T}, S.dv), convert(AbstractVector{T}, S.ev)) -convert(::Type{AbstractMatrix{T}}, S::SymTridiagonal) where {T} = +AbstractMatrix{T}(S::SymTridiagonal) where {T} = SymTridiagonal(convert(AbstractVector{T}, S.dv), convert(AbstractVector{T}, S.ev)) -function convert(::Type{Matrix{T}}, M::SymTridiagonal) where T +function Matrix{T}(M::SymTridiagonal) where T n = size(M, 1) Mf = zeros(T, n, n) @inbounds begin @@ -93,8 +93,8 @@ function convert(::Type{Matrix{T}}, M::SymTridiagonal) where T end return Mf end -convert(::Type{Matrix}, M::SymTridiagonal{T}) where {T} = convert(Matrix{T}, M) -convert(::Type{Array}, M::SymTridiagonal) = convert(Matrix, M) +Matrix(M::SymTridiagonal{T}) where {T} = Matrix{T}(M) +Array(M::SymTridiagonal) = Matrix(M) size(A::SymTridiagonal) = (length(A.dv), length(A.dv)) function size(A::SymTridiagonal, d::Integer) @@ -476,7 +476,7 @@ function size(M::Tridiagonal, d::Integer) end end -function convert(::Type{Matrix{T}}, M::Tridiagonal{T}) where T +function Matrix{T}(M::Tridiagonal{T}) where T A = zeros(T, size(M)) for i = 1:length(M.d) A[i,i] = M.d[i] @@ -487,8 +487,8 @@ function convert(::Type{Matrix{T}}, M::Tridiagonal{T}) where T end A end -convert(::Type{Matrix}, M::Tridiagonal{T}) where {T} = convert(Matrix{T}, M) -convert(::Type{Array}, M::Tridiagonal) = convert(Matrix, M) +Matrix(M::Tridiagonal{T}) where {T} = Matrix{T}(M) +Array(M::Tridiagonal) = Matrix(M) # For M<:Tridiagonal, similar(M[, neweltype]) should yield a Tridiagonal matrix. # On the other hand, similar(M, [neweltype,] shape...) should yield a sparse matrix. @@ -634,11 +634,11 @@ end inv(A::Tridiagonal) = inv_usmani(A.dl, A.d, A.du) det(A::Tridiagonal) = det_usmani(A.dl, A.d, A.du) -convert(::Type{Tridiagonal{T}},M::Tridiagonal) where {T} = +Tridiagonal{T}(M::Tridiagonal) where {T} = Tridiagonal(convert(AbstractVector{T}, M.dl), convert(AbstractVector{T}, M.d), convert(AbstractVector{T}, M.du)) -convert(::Type{AbstractMatrix{T}},M::Tridiagonal) where {T} = convert(Tridiagonal{T}, M) -convert(::Type{Tridiagonal{T}}, M::SymTridiagonal{T}) where {T} = Tridiagonal(M) -function convert(::Type{SymTridiagonal{T}}, M::Tridiagonal) where T +AbstractMatrix{T}(M::Tridiagonal) where {T} = Tridiagonal{T}(M) +Tridiagonal{T}(M::SymTridiagonal{T}) where {T} = Tridiagonal(M) +function SymTridiagonal{T}(M::Tridiagonal) where T if M.dl == M.du return SymTridiagonal{T}(convert(AbstractVector{T},M.d), convert(AbstractVector{T},M.dl)) else diff --git a/base/precompile.jl b/base/precompile.jl index 72c9b57f8d220..7bde4bc345019 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -561,10 +561,6 @@ precompile(Tuple{typeof(Base.nextind), String, UInt64}) precompile(Tuple{typeof(Base.matchall), Base.Regex, String, Bool}) precompile(Tuple{typeof(Base.skip_deleted), Base.Dict{String, String}, Int64}) precompile(Tuple{typeof(Base.reverse), String}) -precompile(Tuple{typeof(Core.Inference.isbits), Tuple{Nothing, Bool}}) -precompile(Tuple{typeof(Base._convert), Type{Array{Method, 1}}, Base.BitArray{1}}) -precompile(Tuple{typeof(Base.unsafe_copyto!), Array{Method, 1}, Int64, Array{Method, 1}, Int64, Int64}) -precompile(Tuple{typeof(Base.copyto!), Array{Method, 1}, Int64, Array{Method, 1}, Int64, Int64}) precompile(Tuple{typeof(Core.Inference.length), Tuple{Core.Inference.PartialTypeVar}}) precompile(Tuple{typeof(Core.Inference.getindex), Tuple{Core.Inference.PartialTypeVar}, Int64}) precompile(Tuple{typeof(Base.show_delim_array), Base.GenericIOBuffer{Array{UInt8, 1}}, Array{Any, 1}, Char, Char, Char, Bool, Int64, Int64}) diff --git a/base/range.jl b/base/range.jl index 3615a99a2d257..39698d436ba15 100644 --- a/base/range.jl +++ b/base/range.jl @@ -811,64 +811,61 @@ el_same(::Type, a, b) = typejoin(a, b) promote_rule(a::Type{UnitRange{T1}}, b::Type{UnitRange{T2}}) where {T1,T2} = el_same(promote_type(T1,T2), a, b) -convert(::Type{UnitRange{T}}, r::UnitRange{T}) where {T<:Real} = r -convert(::Type{UnitRange{T}}, r::UnitRange) where {T<:Real} = UnitRange{T}(r.start, r.stop) +UnitRange{T}(r::UnitRange{T}) where {T<:Real} = r +UnitRange{T}(r::UnitRange) where {T<:Real} = UnitRange{T}(r.start, r.stop) promote_rule(a::Type{OneTo{T1}}, b::Type{OneTo{T2}}) where {T1,T2} = el_same(promote_type(T1,T2), a, b) -convert(::Type{OneTo{T}}, r::OneTo{T}) where {T<:Real} = r -convert(::Type{OneTo{T}}, r::OneTo) where {T<:Real} = OneTo{T}(r.stop) +OneTo{T}(r::OneTo{T}) where {T<:Integer} = r +OneTo{T}(r::OneTo) where {T<:Integer} = OneTo{T}(r.stop) promote_rule(a::Type{UnitRange{T1}}, ::Type{UR}) where {T1,UR<:AbstractUnitRange} = promote_rule(a, UnitRange{eltype(UR)}) -convert(::Type{UnitRange{T}}, r::AbstractUnitRange) where {T<:Real} = UnitRange{T}(first(r), last(r)) -convert(::Type{UnitRange}, r::AbstractUnitRange) = UnitRange(first(r), last(r)) +UnitRange{T}(r::AbstractUnitRange) where {T<:Real} = UnitRange{T}(first(r), last(r)) +UnitRange(r::AbstractUnitRange) = UnitRange(first(r), last(r)) -convert(::Type{AbstractUnitRange{T}}, r::AbstractUnitRange{T}) where {T} = r -convert(::Type{AbstractUnitRange{T}}, r::UnitRange) where {T} = convert(UnitRange{T}, r) -convert(::Type{AbstractUnitRange{T}}, r::OneTo) where {T} = convert(OneTo{T}, r) +AbstractUnitRange{T}(r::AbstractUnitRange{T}) where {T} = r +AbstractUnitRange{T}(r::UnitRange) where {T} = UnitRange{T}(r) +AbstractUnitRange{T}(r::OneTo) where {T} = OneTo{T}(r) promote_rule(::Type{StepRange{T1a,T1b}}, ::Type{StepRange{T2a,T2b}}) where {T1a,T1b,T2a,T2b} = el_same(promote_type(T1a,T2a), # el_same only operates on array element type, so just promote second type parameter StepRange{T1a, promote_type(T1b,T2b)}, StepRange{T2a, promote_type(T1b,T2b)}) -convert(::Type{StepRange{T1,T2}}, r::StepRange{T1,T2}) where {T1,T2} = r +StepRange{T1,T2}(r::StepRange{T1,T2}) where {T1,T2} = r promote_rule(a::Type{StepRange{T1a,T1b}}, ::Type{UR}) where {T1a,T1b,UR<:AbstractUnitRange} = promote_rule(a, StepRange{eltype(UR), eltype(UR)}) -convert(::Type{StepRange{T1,T2}}, r::AbstractRange) where {T1,T2} = +StepRange{T1,T2}(r::AbstractRange) where {T1,T2} = StepRange{T1,T2}(convert(T1, first(r)), convert(T2, step(r)), convert(T1, last(r))) -convert(::Type{StepRange}, r::AbstractUnitRange{T}) where {T} = +StepRange(r::AbstractUnitRange{T}) where {T} = StepRange{T,T}(first(r), step(r), last(r)) -convert(::Type{StepRange{T1,T2} where T1}, r::AbstractRange) where {T2} = - convert(StepRange{eltype(r),T2}, r) +(::Type{StepRange{T1,T2} where T1})(r::AbstractRange) where {T2} = StepRange{eltype(r),T2}(r) promote_rule(::Type{StepRangeLen{T1,R1,S1}},::Type{StepRangeLen{T2,R2,S2}}) where {T1,T2,R1,R2,S1,S2} = el_same(promote_type(T1,T2), StepRangeLen{T1,promote_type(R1,R2),promote_type(S1,S2)}, StepRangeLen{T2,promote_type(R1,R2),promote_type(S1,S2)}) -convert(::Type{StepRangeLen{T,R,S}}, r::StepRangeLen{T,R,S}) where {T,R,S} = r -convert(::Type{StepRangeLen{T,R,S}}, r::StepRangeLen) where {T,R,S} = +StepRangeLen{T,R,S}(r::StepRangeLen{T,R,S}) where {T,R,S} = r +StepRangeLen{T,R,S}(r::StepRangeLen) where {T,R,S} = StepRangeLen{T,R,S}(convert(R, r.ref), convert(S, r.step), length(r), r.offset) -convert(::Type{StepRangeLen{T}}, r::StepRangeLen) where {T} = +StepRangeLen{T}(r::StepRangeLen) where {T} = StepRangeLen(convert(T, r.ref), convert(T, r.step), length(r), r.offset) promote_rule(a::Type{StepRangeLen{T,R,S}}, ::Type{OR}) where {T,R,S,OR<:AbstractRange} = promote_rule(a, StepRangeLen{eltype(OR), eltype(OR), eltype(OR)}) -convert(::Type{StepRangeLen{T,R,S}}, r::AbstractRange) where {T,R,S} = +StepRangeLen{T,R,S}(r::AbstractRange) where {T,R,S} = StepRangeLen{T,R,S}(R(first(r)), S(step(r)), length(r)) -convert(::Type{StepRangeLen{T}}, r::AbstractRange) where {T} = +StepRangeLen{T}(r::AbstractRange) where {T} = StepRangeLen(T(first(r)), T(step(r)), length(r)) -convert(::Type{StepRangeLen}, r::AbstractRange) = convert(StepRangeLen{eltype(r)}, r) +StepRangeLen(r::AbstractRange) = StepRangeLen{eltype(r)}(r) promote_rule(a::Type{LinSpace{T1}}, b::Type{LinSpace{T2}}) where {T1,T2} = el_same(promote_type(T1,T2), a, b) -convert(::Type{LinSpace{T}}, r::LinSpace{T}) where {T} = r -convert(::Type{LinSpace{T}}, r::AbstractRange) where {T} = - LinSpace{T}(first(r), last(r), length(r)) -convert(::Type{LinSpace}, r::AbstractRange{T}) where {T} = - convert(LinSpace{T}, r) +LinSpace{T}(r::LinSpace{T}) where {T} = r +LinSpace{T}(r::AbstractRange) where {T} = LinSpace{T}(first(r), last(r), length(r)) +LinSpace(r::AbstractRange{T}) where {T} = LinSpace{T}(r) promote_rule(a::Type{LinSpace{T}}, ::Type{OR}) where {T,OR<:OrdinalRange} = promote_rule(a, LinSpace{eltype(OR)}) @@ -894,7 +891,7 @@ function vcat(rs::AbstractRange{T}...) where T return a end -convert(::Type{Array{T,1}}, r::AbstractRange{T}) where {T} = vcat(r) +Array{T,1}(r::AbstractRange{T}) where {T} = vcat(r) collect(r::AbstractRange) = vcat(r) reverse(r::OrdinalRange) = colon(last(r), -step(r), first(r)) diff --git a/base/replutil.jl b/base/replutil.jl index 6d93f4dce3761..8ad88cef24d0e 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -412,16 +412,6 @@ function showerror(io::IO, ex::MethodError) "\nYou can convert to a column vector with the vec() function.") end end - # Give a helpful error message if the user likely called a type constructor - # and sees a no method error for convert - if (f === Base.convert && !isempty(arg_types_param) && !is_arg_types && - isa(arg_types_param[1], DataType) && - arg_types_param[1].name === Type.body.name) - construct_type = arg_types_param[1].parameters[1] - println(io) - print(io, "This may have arisen from a call to the constructor $construct_type(...),", - "\nsince type constructors fall back to convert methods.") - end try show_method_candidates(io, ex, kwargs) catch ex @@ -712,7 +702,7 @@ Determines whether a method is the default method which is provided to all types Such a method is usually undesirable to be displayed to the user in the REPL. """ function is_default_method(m::Method) - return m.module == Base && m.file == Symbol("sysimg.jl") && m.sig == Tuple{Type{T},Any} where T + return m.module == Base && m.sig == Tuple{Type{T},Any} where T end @noinline function throw_eachindex_mismatch(::IndexLinear, A...) diff --git a/base/set.jl b/base/set.jl index 34f2ae345f257..8c1b03c893d7e 100644 --- a/base/set.jl +++ b/base/set.jl @@ -22,7 +22,7 @@ for sets of arbitrary objects. """ Set(itr) = Set{eltype(itr)}(itr) function Set(g::Generator) - T = @default_eltype(typeof(g)) + T = @default_eltype(g) (_isleaftype(T) || T === Union{}) || return grow_to!(Set{T}(), g) return Set{T}(g) end @@ -329,7 +329,7 @@ julia> unique(Real[1, 1.0, 2]) ``` """ function unique(itr) - T = @default_eltype(typeof(itr)) + T = @default_eltype(itr) out = Vector{T}() seen = Set{T}() i = start(itr) diff --git a/base/socket.jl b/base/socket.jl index 3d339010cc189..5e061f305aeb5 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -4,7 +4,7 @@ abstract type IPAddr end Base.isless(a::T, b::T) where {T<:IPAddr} = isless(a.host, b.host) -(dt::Type{<:Integer})(ip::IPAddr) = dt(ip.host) +(dt::Type{<:Integer})(ip::IPAddr) = dt(ip.host)::dt struct IPv4 <: IPAddr host::UInt32 diff --git a/base/sparse/sparse.jl b/base/sparse/sparse.jl index 3199fea8e3f0e..3cad4648c8c06 100644 --- a/base/sparse/sparse.jl +++ b/base/sparse/sparse.jl @@ -27,7 +27,7 @@ import Base: @get!, acos, acosd, acot, acotd, acsch, asech, asin, asind, asinh, vcat, hcat, hvcat, cat, imag, indmax, ishermitian, kron, length, log, log1p, max, min, maximum, minimum, norm, one, promote_eltype, real, reshape, rot180, rotl90, rotr90, round, scale!, setindex!, similar, size, transpose, tril, - triu, vec, permute!, map, map! + triu, vec, permute!, map, map!, Array export AbstractSparseArray, AbstractSparseMatrix, AbstractSparseVector, SparseMatrixCSC, SparseVector, blkdiag, droptol!, dropzeros!, dropzeros, diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index 1c62160478a4c..b864016b94f11 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -349,31 +349,30 @@ similar(S::SparseMatrixCSC, ::Type{TvNew}, ::Type{TiNew}, m::Integer, n::Integer _sparsesimilar(S, TvNew, TiNew, (m, n)) -# convert'ing between SparseMatrixCSC types -convert(::Type{AbstractMatrix{Tv}}, A::SparseMatrixCSC{Tv}) where {Tv} = A -convert(::Type{AbstractMatrix{Tv}}, A::SparseMatrixCSC) where {Tv} = convert(SparseMatrixCSC{Tv}, A) -convert(::Type{SparseMatrixCSC{Tv}}, S::SparseMatrixCSC{Tv}) where {Tv} = S -convert(::Type{SparseMatrixCSC{Tv}}, S::SparseMatrixCSC) where {Tv} = convert(SparseMatrixCSC{Tv,eltype(S.colptr)}, S) -convert(::Type{SparseMatrixCSC{Tv,Ti}}, S::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} = S -function convert(::Type{SparseMatrixCSC{Tv,Ti}}, S::SparseMatrixCSC) where {Tv,Ti} +# converting between SparseMatrixCSC types +AbstractMatrix{Tv}(A::SparseMatrixCSC) where {Tv} = SparseMatrixCSC{Tv}(A) +SparseMatrixCSC{Tv}(S::SparseMatrixCSC{Tv}) where {Tv} = copy(S) +SparseMatrixCSC{Tv}(S::SparseMatrixCSC) where {Tv} = SparseMatrixCSC{Tv,eltype(S.colptr)}(S) +SparseMatrixCSC{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} = copy(S) +function SparseMatrixCSC{Tv,Ti}(S::SparseMatrixCSC) where {Tv,Ti} eltypeTicolptr = convert(Vector{Ti}, S.colptr) eltypeTirowval = convert(Vector{Ti}, S.rowval) eltypeTvnzval = convert(Vector{Tv}, S.nzval) return SparseMatrixCSC(S.m, S.n, eltypeTicolptr, eltypeTirowval, eltypeTvnzval) end -# convert'ing from other matrix types to SparseMatrixCSC (also see sparse()) -convert(::Type{SparseMatrixCSC}, M::Matrix) = sparse(M) -convert(::Type{SparseMatrixCSC}, M::AbstractMatrix{Tv}) where {Tv} = convert(SparseMatrixCSC{Tv,Int}, M) -convert(::Type{SparseMatrixCSC{Tv}}, M::AbstractMatrix{Tv}) where {Tv} = convert(SparseMatrixCSC{Tv,Int}, M) -function convert(::Type{SparseMatrixCSC{Tv,Ti}}, M::AbstractMatrix) where {Tv,Ti} +# converting from other matrix types to SparseMatrixCSC (also see sparse()) +SparseMatrixCSC(M::Matrix) = sparse(M) +SparseMatrixCSC(M::AbstractMatrix{Tv}) where {Tv} = SparseMatrixCSC{Tv,Int}(M) +SparseMatrixCSC{Tv}(M::AbstractMatrix{Tv}) where {Tv} = SparseMatrixCSC{Tv,Int}(M) +function SparseMatrixCSC{Tv,Ti}(M::AbstractMatrix) where {Tv,Ti} (I, J, V) = findnz(M) eltypeTiI = convert(Vector{Ti}, I) eltypeTiJ = convert(Vector{Ti}, J) eltypeTvV = convert(Vector{Tv}, V) return sparse_IJ_sorted!(eltypeTiI, eltypeTiJ, eltypeTvV, size(M)...) end -# convert'ing from SparseMatrixCSC to other matrix types -function convert(::Type{Matrix}, S::SparseMatrixCSC{Tv}) where Tv +# converting from SparseMatrixCSC to other matrix types +function Matrix(S::SparseMatrixCSC{Tv}) where Tv # Handle cases where zero(Tv) is not defined but the array is dense. A = length(S) == nnz(S) ? Matrix{Tv}(uninitialized, S.m, S.n) : zeros(Tv, S.m, S.n) for Sj in 1:S.n @@ -385,7 +384,7 @@ function convert(::Type{Matrix}, S::SparseMatrixCSC{Tv}) where Tv end return A end -convert(::Type{Array}, S::SparseMatrixCSC) = convert(Matrix, S) +Array(S::SparseMatrixCSC) = Matrix(S) float(S::SparseMatrixCSC) = SparseMatrixCSC(S.m, S.n, copy(S.colptr), copy(S.rowval), float.(S.nzval)) complex(S::SparseMatrixCSC) = SparseMatrixCSC(S.m, S.n, copy(S.colptr), copy(S.rowval), complex(copy(S.nzval))) diff --git a/base/sparse/sparsevector.jl b/base/sparse/sparsevector.jl index b02f62724ca11..3941849f5be90 100644 --- a/base/sparse/sparsevector.jl +++ b/base/sparse/sparsevector.jl @@ -342,16 +342,14 @@ end ### Conversion # convert SparseMatrixCSC to SparseVector -function convert(::Type{SparseVector{Tv,Ti}}, s::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti<:Integer} +function SparseVector{Tv,Ti}(s::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti<:Integer} size(s, 2) == 1 || throw(ArgumentError("The input argument must have a single-column.")) SparseVector(s.m, s.rowval, s.nzval) end -convert(::Type{SparseVector{Tv}}, s::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} = - convert(SparseVector{Tv,Ti}, s) +SparseVector{Tv}(s::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} = SparseVector{Tv,Ti}(s) -convert(::Type{SparseVector}, s::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} = - convert(SparseVector{Tv,Ti}, s) +SparseVector(s::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} = SparseVector{Tv,Ti}(s) # convert Vector to SparseVector @@ -369,7 +367,7 @@ julia> sparsevec([1.0, 2.0, 0.0, 0.0, 3.0, 0.0]) [5] = 3.0 ``` """ -sparsevec(a::AbstractVector{T}) where {T} = convert(SparseVector{T, Int}, a) +sparsevec(a::AbstractVector{T}) where {T} = SparseVector{T, Int}(a) sparsevec(a::AbstractArray) = sparsevec(vec(a)) sparsevec(a::AbstractSparseArray) = vec(a) sparsevec(a::AbstractSparseVector) = vec(a) @@ -402,23 +400,21 @@ function _dense2sparsevec(s::AbstractArray{Tv}, initcap::Ti) where {Tv,Ti} SparseVector(n, nzind, nzval) end -convert(::Type{SparseVector{Tv,Ti}}, s::AbstractVector{Tv}) where {Tv,Ti} = +SparseVector{Tv,Ti}(s::AbstractVector{Tv}) where {Tv,Ti} = _dense2sparsevec(s, convert(Ti, max(8, div(length(s), 8)))) -convert(::Type{SparseVector{Tv}}, s::AbstractVector{Tv}) where {Tv} = - convert(SparseVector{Tv,Int}, s) +SparseVector{Tv}(s::AbstractVector{Tv}) where {Tv} = SparseVector{Tv,Int}(s) -convert(::Type{SparseVector}, s::AbstractVector{Tv}) where {Tv} = - convert(SparseVector{Tv,Int}, s) +SparseVector(s::AbstractVector{Tv}) where {Tv} = SparseVector{Tv,Int}(s) # convert between different types of SparseVector -convert(::Type{SparseVector{Tv}}, s::SparseVector{Tv}) where {Tv} = s -convert(::Type{SparseVector{Tv,Ti}}, s::SparseVector{Tv,Ti}) where {Tv,Ti} = s -convert(::Type{SparseVector{Tv,Ti}}, s::SparseVector) where {Tv,Ti} = +SparseVector{Tv}(s::SparseVector{Tv}) where {Tv} = s +SparseVector{Tv,Ti}(s::SparseVector{Tv,Ti}) where {Tv,Ti} = s +SparseVector{Tv,Ti}(s::SparseVector) where {Tv,Ti} = SparseVector{Tv,Ti}(s.n, convert(Vector{Ti}, s.nzind), convert(Vector{Tv}, s.nzval)) -convert(::Type{SparseVector{Tv}}, s::SparseVector{<:Any,Ti}) where {Tv,Ti} = +SparseVector{Tv}(s::SparseVector{<:Any,Ti}) where {Tv,Ti} = SparseVector{Tv,Ti}(s.n, s.nzind, convert(Vector{Tv}, s.nzval)) @@ -843,7 +839,7 @@ end ### Conversion to matrix -function convert(::Type{SparseMatrixCSC{Tv,Ti}}, x::AbstractSparseVector) where {Tv,Ti} +function SparseMatrixCSC{Tv,Ti}(x::AbstractSparseVector) where {Tv,Ti} n = length(x) xnzind = nonzeroinds(x) xnzval = nonzeros(x) @@ -856,13 +852,11 @@ function convert(::Type{SparseMatrixCSC{Tv,Ti}}, x::AbstractSparseVector) where SparseMatrixCSC(n, 1, colptr, rowval, nzval) end -convert(::Type{SparseMatrixCSC{Tv}}, x::AbstractSparseVector{<:Any,Ti}) where {Tv,Ti} = - convert(SparseMatrixCSC{Tv,Ti}, x) +SparseMatrixCSC{Tv}(x::AbstractSparseVector{<:Any,Ti}) where {Tv,Ti} = SparseMatrixCSC{Tv,Ti}(x) -convert(::Type{SparseMatrixCSC}, x::AbstractSparseVector{Tv,Ti}) where {Tv,Ti} = - convert(SparseMatrixCSC{Tv,Ti}, x) +SparseMatrixCSC(x::AbstractSparseVector{Tv,Ti}) where {Tv,Ti} = SparseMatrixCSC{Tv,Ti}(x) -function convert(::Type{Vector}, x::AbstractSparseVector{Tv}) where Tv +function Vector(x::AbstractSparseVector{Tv}) where Tv n = length(x) n == 0 && return Vector{Tv}() nzind = nonzeroinds(x) @@ -875,7 +869,7 @@ function convert(::Type{Vector}, x::AbstractSparseVector{Tv}) where Tv end return r end -convert(::Type{Array}, x::AbstractSparseVector) = convert(Vector, x) +Array(x::AbstractSparseVector) = Vector(x) ### Array manipulation diff --git a/base/statistics.jl b/base/statistics.jl index a866a5ed28315..aead894107d8b 100644 --- a/base/statistics.jl +++ b/base/statistics.jl @@ -708,14 +708,14 @@ end T = promote_type(eltype(v), typeof(v[1]*h)) if h == 0 - return T(v[i]) + return convert(T, v[i]) else a = v[i] b = v[i+1] if isfinite(a) && isfinite(b) - return T(a + h*(b-a)) + return convert(T, a + h*(b-a)) else - return T((1-h)*a + h*b) + return convert(T, (1-h)*a + h*b) end end end diff --git a/base/sysimg.jl b/base/sysimg.jl index b10f6f1ebc1b3..616b2e10f27db 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -119,10 +119,6 @@ include("refpointer.jl") include("checked.jl") using .Checked -# buggy handling of ispure in type-inference means this should be -# after re-defining the basic operations that they might try to call -(::Type{T})(arg) where {T} = convert(T, arg)::T # Hidden from the REPL. - # vararg Symbol constructor Symbol(x...) = Symbol(string(x...)) diff --git a/base/twiceprecision.jl b/base/twiceprecision.jl index 06108e505c35a..bc47ea3f2bb6d 100644 --- a/base/twiceprecision.jl +++ b/base/twiceprecision.jl @@ -240,12 +240,15 @@ promote_rule(::Type{TwicePrecision{R}}, ::Type{TwicePrecision{S}}) where {R,S} = promote_rule(::Type{TwicePrecision{R}}, ::Type{S}) where {R,S} = TwicePrecision{promote_type(R,S)} +(::Type{T})(x::TwicePrecision) where {T<:Number} = T(x.hi + x.lo)::T +TwicePrecision{T}(x::Number) where {T} = TwicePrecision{T}(T(x), zero(T)) + convert(::Type{TwicePrecision{T}}, x::TwicePrecision{T}) where {T} = x convert(::Type{TwicePrecision{T}}, x::TwicePrecision) where {T} = TwicePrecision{T}(convert(T, x.hi), convert(T, x.lo)) -convert(::Type{T}, x::TwicePrecision) where {T<:Number} = convert(T, x.hi + x.lo) -convert(::Type{TwicePrecision{T}}, x::Number) where {T} = TwicePrecision{T}(convert(T, x), zero(T)) +convert(::Type{T}, x::TwicePrecision) where {T<:Number} = T(x) +convert(::Type{TwicePrecision{T}}, x::Number) where {T} = TwicePrecision{T}(x) float(x::TwicePrecision{<:AbstractFloat}) = x float(x::TwicePrecision) = TwicePrecision(float(x.hi), float(x.lo)) @@ -476,19 +479,19 @@ end /(r::StepRangeLen{<:Real,<:TwicePrecision}, x::Real) = StepRangeLen(r.ref/x, twiceprecision(r.step/x, nbitslen(r)), length(r), r.offset) -convert(::Type{StepRangeLen{T,R,S}}, r::StepRangeLen{T,R,S}) where {T<:AbstractFloat,R<:TwicePrecision,S<:TwicePrecision} = r +StepRangeLen{T,R,S}(r::StepRangeLen{T,R,S}) where {T<:AbstractFloat,R<:TwicePrecision,S<:TwicePrecision} = r -convert(::Type{StepRangeLen{T,R,S}}, r::StepRangeLen) where {T<:AbstractFloat,R<:TwicePrecision,S<:TwicePrecision} = +StepRangeLen{T,R,S}(r::StepRangeLen) where {T<:AbstractFloat,R<:TwicePrecision,S<:TwicePrecision} = _convertSRL(StepRangeLen{T,R,S}, r) -convert(::Type{StepRangeLen{Float64}}, r::StepRangeLen) = +(::Type{StepRangeLen{Float64}})(r::StepRangeLen) = _convertSRL(StepRangeLen{Float64,TwicePrecision{Float64},TwicePrecision{Float64}}, r) -convert(::Type{StepRangeLen{T}}, r::StepRangeLen) where {T<:IEEEFloat} = +StepRangeLen{T}(r::StepRangeLen) where {T<:IEEEFloat} = _convertSRL(StepRangeLen{T,Float64,Float64}, r) -convert(::Type{StepRangeLen{Float64}}, r::AbstractRange) = +(::Type{StepRangeLen{Float64}})(r::AbstractRange) = _convertSRL(StepRangeLen{Float64,TwicePrecision{Float64},TwicePrecision{Float64}}, r) -convert(::Type{StepRangeLen{T}}, r::AbstractRange) where {T<:IEEEFloat} = +StepRangeLen{T}(r::AbstractRange) where {T<:IEEEFloat} = _convertSRL(StepRangeLen{T,Float64,Float64}, r) function _convertSRL(::Type{StepRangeLen{T,R,S}}, r::StepRangeLen{<:Integer}) where {T,R,S} diff --git a/stdlib/Dates/src/periods.jl b/stdlib/Dates/src/periods.jl index 1a74892e23a6d..37ea6504ab887 100644 --- a/stdlib/Dates/src/periods.jl +++ b/stdlib/Dates/src/periods.jl @@ -401,8 +401,13 @@ function divexact(x, y) return q end +# TODO: this is needed to prevent undefined Period constructors from +# hitting the deprecated construct-to-convert fallback. +(::Type{T})(p::Period) where {T<:Period} = convert(T, p)::T + # FixedPeriod conversions and promotion rules -const fixedperiod_conversions = [(Week, 7), (Day, 24), (Hour, 60), (Minute, 60), (Second, 1000), (Millisecond, 1000), (Microsecond, 1000), (Nanosecond, 1)] +const fixedperiod_conversions = [(:Week, 7), (:Day, 24), (:Hour, 60), (:Minute, 60), (:Second, 1000), + (:Millisecond, 1000), (:Microsecond, 1000), (:Nanosecond, 1)] for i = 1:length(fixedperiod_conversions) T, n = fixedperiod_conversions[i] N = Int64(1) diff --git a/stdlib/Dates/test/periods.jl b/stdlib/Dates/test/periods.jl index 85a3b05a6ba16..455d5a8116cd7 100644 --- a/stdlib/Dates/test/periods.jl +++ b/stdlib/Dates/test/periods.jl @@ -252,6 +252,8 @@ struct Beat <: Dates.Period value::Int64 end +Beat(p::Period) = Beat(Dates.toms(p) ÷ 86400) + @testset "comparisons with new subtypes of Period" begin # https://en.wikipedia.org/wiki/Swatch_Internet_Time Dates.value(b::Beat) = b.value diff --git a/stdlib/SharedArrays/src/SharedArrays.jl b/stdlib/SharedArrays/src/SharedArrays.jl index 5f4cb9ea23310..d7b933c723087 100644 --- a/stdlib/SharedArrays/src/SharedArrays.jl +++ b/stdlib/SharedArrays/src/SharedArrays.jl @@ -344,15 +344,15 @@ localindices(S::SharedArray) = S.pidx > 0 ? range_1dim(S, S.pidx) : 1:0 unsafe_convert(::Type{Ptr{T}}, S::SharedArray{T}) where {T} = unsafe_convert(Ptr{T}, sdata(S)) unsafe_convert(::Type{Ptr{T}}, S::SharedArray ) where {T} = unsafe_convert(Ptr{T}, sdata(S)) -function convert(::Type{SharedArray}, A::Array) +function SharedArray(A::Array) S = SharedArray{eltype(A),ndims(A)}(size(A)) copyto!(S, A) end -function convert(::Type{SharedArray{T}}, A::Array) where T +function SharedArray{T}(A::Array) where T S = SharedArray{T,ndims(A)}(size(A)) copyto!(S, A) end -function convert(::Type{SharedArray{TS,N}}, A::Array{TA,N}) where {TS,TA,N} +function SharedArray{TS,N}(A::Array{TA,N}) where {TS,TA,N} S = SharedArray{TS,ndims(A)}(size(A)) copyto!(S, A) end @@ -491,7 +491,7 @@ function show(io::IO, mime::MIME"text/plain", S::SharedArray) end end -convert(::Type{Array}, S::SharedArray) = S.s +Array(S::SharedArray) = S.s # pass through getindex and setindex! - unlike DArrays, these always work on the complete array getindex(S::SharedArray, i::Real) = getindex(S.s, i) diff --git a/stdlib/SuiteSparse/src/cholmod.jl b/stdlib/SuiteSparse/src/cholmod.jl index 2c4a7ba535ebd..22a7f88baa43d 100644 --- a/stdlib/SuiteSparse/src/cholmod.jl +++ b/stdlib/SuiteSparse/src/cholmod.jl @@ -345,6 +345,7 @@ mutable struct Factor{Tv} <: Factorization{Tv} end end Factor(p::Ptr{C_Factor{Tv}}) where {Tv<:VTypes} = Factor{Tv}(p) +Factor(x::Factor) = x # All pointer loads should be checked to make sure that SuiteSparse is not called with # a C_NULL pointer which could cause a segfault. Pointers are set to null @@ -819,7 +820,7 @@ get_perm(FC::FactorComponent) = get_perm(Factor(FC)) ######################### # Convertion/construction -function convert(::Type{Dense{T}}, A::StridedVecOrMat) where T<:VTypes +function Dense{T}(A::StridedVecOrMat) where T<:VTypes d = allocate_dense(size(A, 1), size(A, 2), stride(A, 2), T) s = unsafe_load(d.p) for i in eachindex(A) @@ -827,11 +828,11 @@ function convert(::Type{Dense{T}}, A::StridedVecOrMat) where T<:VTypes end d end -function convert(::Type{Dense}, A::StridedVecOrMat) +function Dense(A::StridedVecOrMat) T = promote_type(eltype(A), Float64) - return convert(Dense{T}, A) + return Dense{T}(A) end -convert(::Type{Dense}, A::Sparse) = sparse_to_dense(A) +Dense(A::Sparse) = sparse_to_dense(A) # This constructior assumes zero based colptr and rowval function Sparse(m::Integer, n::Integer, @@ -913,9 +914,8 @@ function Sparse(A::SparseMatrixCSC{Tv,SuiteSparse_long}, stype::Integer) where T end # convert SparseVectors into CHOLMOD Sparse types through a mx1 CSC matrix -convert(::Type{Sparse}, A::SparseVector{<:VTypes,SuiteSparse_long}) = - convert(Sparse, convert(SparseMatrixCSC, A)) -function convert(::Type{Sparse}, A::SparseMatrixCSC{<:VTypes,<:ITypes}) +Sparse(A::SparseVector{<:VTypes,SuiteSparse_long}) = Sparse(SparseMatrixCSC(A)) +function Sparse(A::SparseMatrixCSC{<:VTypes,<:ITypes}) o = Sparse(A, 0) # check if array is symmetric and change stype if it is if ishermitian(o) @@ -923,15 +923,15 @@ function convert(::Type{Sparse}, A::SparseMatrixCSC{<:VTypes,<:ITypes}) end o end -convert(::Type{Sparse}, A::SparseMatrixCSC{Complex{Float32},<:ITypes}) = - convert(Sparse, convert(SparseMatrixCSC{Complex{Float64},SuiteSparse_long}, A)) -convert(::Type{Sparse}, A::Symmetric{Float64,SparseMatrixCSC{Float64,SuiteSparse_long}}) = +Sparse(A::SparseMatrixCSC{Complex{Float32},<:ITypes}) = + Sparse(SparseMatrixCSC{Complex{Float64},SuiteSparse_long}(A)) +Sparse(A::Symmetric{Float64,SparseMatrixCSC{Float64,SuiteSparse_long}}) = Sparse(A.data, A.uplo == 'L' ? -1 : 1) # The convert method for Hermitian is very similar to the general convert method, but we need to # remove any non real elements in the diagonal because, in contrast to BLAS/LAPACK these are not # ignored by CHOLMOD. If even tiny imaginary parts are present CHOLMOD will fail with a non-positive # definite/zero pivot error. -function convert(::Type{Sparse}, AH::Hermitian{Tv,SparseMatrixCSC{Tv,SuiteSparse_long}}) where {Tv<:VTypes} +function Sparse(AH::Hermitian{Tv,SparseMatrixCSC{Tv,SuiteSparse_long}}) where {Tv<:VTypes} A = AH.data # Here we allocate a Symmetric/Hermitian CHOLMOD.Sparse matrix so we only need to copy @@ -955,23 +955,21 @@ function convert(::Type{Sparse}, AH::Hermitian{Tv,SparseMatrixCSC{Tv,SuiteSparse return o end -function convert(::Type{Sparse}, - A::Union{SparseMatrixCSC{BigFloat,Ti}, - Symmetric{BigFloat,SparseMatrixCSC{BigFloat,Ti}}, - Hermitian{Complex{BigFloat},SparseMatrixCSC{Complex{BigFloat},Ti}}}, - args...) where Ti<:ITypes - throw(MethodError(convert, (Sparse, A))) +function Sparse(A::Union{SparseMatrixCSC{BigFloat,Ti}, + Symmetric{BigFloat,SparseMatrixCSC{BigFloat,Ti}}, + Hermitian{Complex{BigFloat},SparseMatrixCSC{Complex{BigFloat},Ti}}}, + args...) where Ti<:ITypes + throw(MethodError(Sparse, (A,))) end -function convert(::Type{Sparse}, - A::Union{SparseMatrixCSC{T,Ti}, - Symmetric{T,SparseMatrixCSC{T,Ti}}, - Hermitian{T,SparseMatrixCSC{T,Ti}}}, - args...) where T where Ti<:ITypes - return Sparse(convert(AbstractMatrix{promote_type(Float64, T)}, A), args...) +function Sparse(A::Union{SparseMatrixCSC{T,Ti}, + Symmetric{T,SparseMatrixCSC{T,Ti}}, + Hermitian{T,SparseMatrixCSC{T,Ti}}}, + args...) where T where Ti<:ITypes + return Sparse(AbstractMatrix{promote_type(Float64, T)}(A), args...) end # Useful when reading in files, but not type stable -function convert(::Type{Sparse}, p::Ptr{C_SparseVoid}) +function Sparse(p::Ptr{C_SparseVoid}) if p == C_NULL throw(ArgumentError("sparse matrix construction failed for " * "unknown reasons. Please submit a bug report.")) @@ -1016,8 +1014,8 @@ function convert(::Type{Sparse}, p::Ptr{C_SparseVoid}) return Sparse(convert(Ptr{C_Sparse{Tv}}, p)) end -convert(::Type{Sparse}, A::Dense) = dense_to_sparse(A, SuiteSparse_long) -convert(::Type{Sparse}, L::Factor) = factor_to_sparse!(copy(L)) +Sparse(A::Dense) = dense_to_sparse(A, SuiteSparse_long) +Sparse(L::Factor) = factor_to_sparse!(copy(L)) function Sparse(filename::String) open(filename) do f return read_sparse(f, SuiteSparse_long) @@ -1025,7 +1023,7 @@ function Sparse(filename::String) end ## convertion back to base Julia types -function convert(::Type{Matrix{T}}, D::Dense{T}) where T +function Matrix{T}(D::Dense{T}) where T s = unsafe_load(D.p) a = Matrix{T}(uninitialized, s.nrow, s.ncol) copyto!(a, D) @@ -1053,16 +1051,16 @@ function _copy!(dest::AbstractArray, D::Dense) end dest end -convert(::Type{Matrix}, D::Dense{T}) where {T} = convert(Matrix{T}, D) -function convert(::Type{Vector{T}}, D::Dense{T}) where T +Matrix(D::Dense{T}) where {T} = Matrix{T}(D) +function Vector{T}(D::Dense{T}) where T if size(D, 2) > 1 throw(DimensionMismatch("input must be a vector but had $(size(D, 2)) columns")) end copyto!(Vector{T}(uninitialized, size(D, 1)), D) end -convert(::Type{Vector}, D::Dense{T}) where {T} = convert(Vector{T}, D) +Vector(D::Dense{T}) where {T} = Vector{T}(D) -function convert(::Type{SparseMatrixCSC{Tv,SuiteSparse_long}}, A::Sparse{Tv}) where Tv +function SparseMatrixCSC{Tv,SuiteSparse_long}(A::Sparse{Tv}) where Tv s = unsafe_load(A.p) if s.stype != 0 throw(ArgumentError("matrix has stype != 0. Convert to matrix " * @@ -1080,7 +1078,7 @@ function convert(::Type{SparseMatrixCSC{Tv,SuiteSparse_long}}, A::Sparse{Tv}) wh return B end end -function convert(::Type{Symmetric{Float64,SparseMatrixCSC{Float64,SuiteSparse_long}}}, A::Sparse{Float64}) +function (::Type{Symmetric{Float64,SparseMatrixCSC{Float64,SuiteSparse_long}}})(A::Sparse{Float64}) s = unsafe_load(A.p) if !issymmetric(A) throw(ArgumentError("matrix is not symmetric")) @@ -1097,7 +1095,7 @@ function convert(::Type{Symmetric{Float64,SparseMatrixCSC{Float64,SuiteSparse_lo return B end end -function convert(::Type{Hermitian{Tv,SparseMatrixCSC{Tv,SuiteSparse_long}}}, A::Sparse{Tv}) where Tv<:VTypes +function Hermitian{Tv,SparseMatrixCSC{Tv,SuiteSparse_long}}(A::Sparse{Tv}) where Tv<:VTypes s = unsafe_load(A.p) if !ishermitian(A) throw(ArgumentError("matrix is not Hermitian")) @@ -1117,16 +1115,16 @@ end function sparse(A::Sparse{Float64}) # Notice! Cannot be type stable because of stype s = unsafe_load(A.p) if s.stype == 0 - return convert(SparseMatrixCSC{Float64,SuiteSparse_long}, A) + return SparseMatrixCSC{Float64,SuiteSparse_long}(A) end - return convert(Symmetric{Float64,SparseMatrixCSC{Float64,SuiteSparse_long}}, A) + return Symmetric{Float64,SparseMatrixCSC{Float64,SuiteSparse_long}}(A) end function sparse(A::Sparse{Complex{Float64}}) # Notice! Cannot be type stable because of stype s = unsafe_load(A.p) if s.stype == 0 - return convert(SparseMatrixCSC{Complex{Float64},SuiteSparse_long}, A) + return SparseMatrixCSC{Complex{Float64},SuiteSparse_long}(A) end - return convert(Hermitian{Complex{Float64},SparseMatrixCSC{Complex{Float64},SuiteSparse_long}}, A) + return Hermitian{Complex{Float64},SparseMatrixCSC{Complex{Float64},SuiteSparse_long}}(A) end function sparse(F::Factor) s = unsafe_load(pointer(F)) @@ -1665,10 +1663,10 @@ end SparseVecOrMat{Tv,Ti} = Union{SparseVector{Tv,Ti}, SparseMatrixCSC{Tv,Ti}} function (\)(L::FactorComponent, b::Vector) - reshape(convert(Matrix, L\Dense(b)), length(b)) + reshape(Matrix(L\Dense(b)), length(b)) end function (\)(L::FactorComponent, B::Matrix) - convert(Matrix, L\Dense(B)) + Matrix(L\Dense(B)) end function (\)(L::FactorComponent, B::SparseVecOrMat) sparse(L\Sparse(B,0)) @@ -1682,14 +1680,14 @@ end # Likewise the two following explicit Vector and Matrix defs (rather than a single VecOrMat) (\)(L::Factor{T}, B::Vector{Complex{T}}) where {T<:Float64} = complex.(L\real(B), L\imag(B)) (\)(L::Factor{T}, B::Matrix{Complex{T}}) where {T<:Float64} = complex.(L\real(B), L\imag(B)) -(\)(L::Factor{T}, b::StridedVector) where {T<:VTypes} = Vector(L\convert(Dense{T}, b)) -(\)(L::Factor{T}, B::StridedMatrix) where {T<:VTypes} = Matrix(L\convert(Dense{T}, B)) +(\)(L::Factor{T}, b::StridedVector) where {T<:VTypes} = Vector(L\Dense{T}(b)) +(\)(L::Factor{T}, B::StridedMatrix) where {T<:VTypes} = Matrix(L\Dense{T}(B)) (\)(L::Factor, B::Sparse) = spsolve(CHOLMOD_A, L, B) # When right hand side is sparse, we have to ensure that the rhs is not marked as symmetric. (\)(L::Factor, B::SparseVecOrMat) = sparse(spsolve(CHOLMOD_A, L, Sparse(B, 0))) \(adjL::Adjoint{<:Any,<:Factor}, B::Dense) = (L = adjL.parent; solve(CHOLMOD_A, L, B)) -\(adjL::Adjoint{<:Any,<:Factor}, B::VecOrMat) = (L = adjL.parent; convert(Matrix, solve(CHOLMOD_A, L, Dense(B)))) +\(adjL::Adjoint{<:Any,<:Factor}, B::VecOrMat) = (L = adjL.parent; Matrix(solve(CHOLMOD_A, L, Dense(B)))) \(adjL::Adjoint{<:Any,<:Factor}, B::Sparse) = (L = adjL.parent; spsolve(CHOLMOD_A, L, B)) \(adjL::Adjoint{<:Any,<:Factor}, B::SparseVecOrMat) = (L = adjL.parent; \(Adjoint(L), Sparse(B))) @@ -1706,7 +1704,7 @@ function \(A::RealHermSymComplexHermF64SSL, B::StridedVecOrMat) if issuccess(F) return \(F, B) else - return \(lufact(convert(SparseMatrixCSC{eltype(A), SuiteSparse_long}, A)), B) + return \(lufact(SparseMatrixCSC{eltype(A), SuiteSparse_long}(A)), B) end end end @@ -1720,7 +1718,7 @@ function \(adjA::Adjoint{<:Any,<:RealHermSymComplexHermF64SSL}, B::StridedVecOrM if issuccess(F) return \(Adjoint(F), B) else - return \(Adjoint(lufact(convert(SparseMatrixCSC{eltype(A), SuiteSparse_long}, A))), B) + return \(Adjoint(lufact(SparseMatrixCSC{eltype(A), SuiteSparse_long}(A))), B) end end end diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 5a761c51249b2..5b1ec4bd6cf89 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -199,9 +199,9 @@ end T24Linear(::Type{T}, dims::Int...) where T = T24Linear(T, dims) T24Linear(::Type{T}, dims::NTuple{N,Int}) where {T,N} = T24Linear{T,N,dims}() -Base.convert(::Type{T24Linear }, X::AbstractArray{T,N}) where {T,N } = convert(T24Linear{T,N}, X) -Base.convert(::Type{T24Linear{T }}, X::AbstractArray{_,N}) where {T,N,_} = convert(T24Linear{T,N}, X) -Base.convert(::Type{T24Linear{T,N}}, X::AbstractArray ) where {T,N } = T24Linear{T,N,size(X)}(X...) +T24Linear( X::AbstractArray{T,N}) where {T,N } = T24Linear{T,N}(X) +T24Linear{T }(X::AbstractArray{_,N}) where {T,N,_} = T24Linear{T,N}(X) +T24Linear{T,N}(X::AbstractArray ) where {T,N } = T24Linear{T,N,size(X)}(X...) Base.size(::T24Linear{T,N,dims}) where {T,N,dims} = dims import Base: IndexLinear @@ -217,10 +217,10 @@ end TSlow(::Type{T}, dims::Int...) where {T} = TSlow(T, dims) TSlow(::Type{T}, dims::NTuple{N,Int}) where {T,N} = TSlow{T,N}(Dict{NTuple{N,Int}, T}(), dims) -Base.convert(::Type{TSlow{T,N}}, X::TSlow{T,N}) where {T,N } = X -Base.convert(::Type{TSlow }, X::AbstractArray{T,N}) where {T,N } = convert(TSlow{T,N}, X) -Base.convert(::Type{TSlow{T }}, X::AbstractArray{_,N}) where {T,N,_} = convert(TSlow{T,N}, X) -Base.convert(::Type{TSlow{T,N}}, X::AbstractArray ) where {T,N } = begin +TSlow{T,N}(X::TSlow{T,N}) where {T,N } = X +TSlow( X::AbstractArray{T,N}) where {T,N } = TSlow{T,N}(X) +TSlow{T }(X::AbstractArray{_,N}) where {T,N,_} = TSlow{T,N}(X) +TSlow{T,N}(X::AbstractArray ) where {T,N } = begin A = TSlow(T, size(X)) for I in CartesianIndices(size(X)) A[I.I...] = X[I.I...] diff --git a/test/arrayops.jl b/test/arrayops.jl index 547f7bf2f65b5..6a8f47d22712b 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -2172,7 +2172,7 @@ end Base.TypeArithmetic(::Type{F21666{T}}) where {T} = T() Base.:+(x::F, y::F) where {F <: F21666} = F(x.x + y.x) -Base.convert(::Type{Float64}, x::F21666) = Float64(x.x) +Float64(x::F21666) = Float64(x.x) @testset "Exactness of cumsum # 21666" begin # test that cumsum uses more stable algorithm # for types with unknown/rounding arithmetic diff --git a/test/choosetests.jl b/test/choosetests.jl index 7cf2f45eb7749..aea130dd8e9f0 100644 --- a/test/choosetests.jl +++ b/test/choosetests.jl @@ -136,14 +136,6 @@ function choosetests(choices = []) prepend!(tests, linalgtests) end - # do ambiguous first to avoid failing if ambiguities are introduced by other tests - if "ambiguous" in skip_tests - filter!(x -> x != "ambiguous", tests) - elseif "ambiguous" in tests - filter!(x -> x != "ambiguous", tests) - prepend!(tests, ["ambiguous"]) - end - net_required_for = ["socket", "stdlib", "libgit2"] net_on = true try @@ -169,6 +161,14 @@ function choosetests(choices = []) prepend!(tests, STDLIBS) end + # do ambiguous first to avoid failing if ambiguities are introduced by other tests + if "ambiguous" in skip_tests + filter!(x -> x != "ambiguous", tests) + elseif "ambiguous" in tests + filter!(x -> x != "ambiguous", tests) + prepend!(tests, ["ambiguous"]) + end + if startswith(string(Sys.ARCH), "arm") # Remove profile from default tests on ARM since it currently segfaults # Allow explicitly adding it for testing diff --git a/test/dimensionful.jl b/test/dimensionful.jl index bb3b5ac2043af..5c526c17e93ff 100644 --- a/test/dimensionful.jl +++ b/test/dimensionful.jl @@ -11,12 +11,9 @@ struct Furlong{p,T<:Number} <: Number Furlong{p,T}(x::Furlong{p}) where {p,T} = new(x.val) end Furlong(x::T) where {T<:Number} = Furlong{1,T}(x) -(::Type{T})(x::Furlong{p,T}) where {p,T} = x.val +(::Type{T})(x::Furlong) where {T<:Number} = T(x.val) Furlong{p}(v::Number) where {p} = Furlong{p,typeof(v)}(v) -Base.convert(::Type{Furlong{p,T}}, x::Furlong{p,S}) where {T,p,S} = Furlong{p,T}(convert(T,x.val)) -Base.convert(::Type{Furlong{0,T}}, x::Furlong{0}) where {T} = Furlong{0,T}(convert(T, x.val)) -Base.convert(::Type{T}, x::Furlong{0}) where {T<:Number} = convert(T, x.val) -Base.convert(::Type{Furlong{0,T}}, x::Number) where {T} = Furlong{0,T}(convert(T, x)) +Furlong{p,T}(x::Furlong{p,S}) where {T,p,S} = Furlong{p,T}(T(x.val)) Base.promote_type(::Type{Furlong{p,T}}, ::Type{Furlong{p,S}}) where {p,T,S} = (Base.@_pure_meta; Furlong{p,promote_type(T,S)})