Skip to content

Commit

Permalink
deprecate convert-to-construct fallback
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Sep 7, 2017
1 parent 6b7c895 commit 0c8b5e7
Show file tree
Hide file tree
Showing 34 changed files with 341 additions and 370 deletions.
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,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]).

Expand Down
11 changes: 3 additions & 8 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ 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)

"""
size(A::AbstractArray, [dim...])
Expand Down Expand Up @@ -839,14 +842,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} = copy!(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)
Expand Down
17 changes: 5 additions & 12 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -549,22 +549,15 @@ end
one(x::AbstractMatrix{T}) where {T} = _one(one(T), x)
oneunit(x::AbstractMatrix{T}) where {T} = _one(oneunit(T), x)

## Conversions ##

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} = copy!(Array{T,n}(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
Array{T,N}(x::AbstractArray{S,N}) where {T,N,S} = copy!(Array{T,N}(size(x)), x)
AbstractArray{T,N}(A::AbstractArray{S,N}) where {T,N,S} = copy!(similar(A,T), A)

# constructors should make copies
(::Type{T})(x::T) where {T<:Array} = copy(x)
end

Expand Down
23 changes: 8 additions & 15 deletions base/bitarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -497,21 +497,21 @@ 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}(size(B))
#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 Array{T,N}(B::BitArray{N}) where {T,N}
A = Array{T,N}(size(B))
Bc = B.chunks
@inbounds for i = 1:length(A)
A[i] = unsafe_bitgetindex(Bc, i)
end
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(size(A))
Bc = B.chunks
l = length(B)
Expand All @@ -536,7 +536,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(size(A))
Bc = B.chunks
l = length(B)
Expand All @@ -545,16 +545,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
Expand Down
7 changes: 7 additions & 0 deletions base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,13 @@ Array{T}(m::Int, n::Int, o::Int) where {T} = Array{T,3}(m, n, o)

Array{T,1}() where {T} = Array{T,1}(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),
Expand Down
15 changes: 9 additions & 6 deletions base/dates/periods.jl
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,9 @@ function divexact(x, y)
return q
end

convert(::Type{T}, p::T) where {T<:Period} = p
convert(::Type{T}, p::Period) where {T<:Period} = T(p)

# FixedPeriod conversions and promotion rules
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)
Expand All @@ -413,15 +416,15 @@ for i = 1:length(fixedperiod_conversions)
N *= nc
vmax = typemax(Int64) ÷ N
vmin = typemin(Int64) ÷ N
@eval function Base.convert(::Type{$T}, x::$Tc)
$vmin value(x) $vmax || throw(InexactError(:convert, $T, x))
@eval function $T(x::$Tc)
$vmin value(x) $vmax || throw(InexactError(($T).name.name, x))
return $T(value(x) * $N)
end
end
N = n
for j = (i + 1):length(fixedperiod_conversions) # more-precise periods
Tc, nc = fixedperiod_conversions[j]
@eval Base.convert(::Type{$T}, x::$Tc) = $T(divexact(value(x), $N))
@eval $T(x::$Tc) = $T(divexact(value(x), $N))
@eval Base.promote_rule(::Type{$T}, ::Type{$Tc}) = $Tc
N *= nc
end
Expand All @@ -430,12 +433,12 @@ end
# other periods with fixed conversions but which aren't fixed time periods
const OtherPeriod = Union{Month, Year}
let vmax = typemax(Int64) ÷ 12, vmin = typemin(Int64) ÷ 12
@eval function Base.convert(::Type{Month}, x::Year)
$vmin value(x) $vmax || throw(InexactError(:convert, Month, x))
@eval function Month(x::Year)
$vmin value(x) $vmax || throw(InexactError(:Month, x))
Month(value(x) * 12)
end
end
Base.convert(::Type{Year}, x::Month) = Year(divexact(value(x), 12))
Year(x::Month) = Year(divexact(value(x), 12))
Base.promote_rule(::Type{Year}, ::Type{Month}) = Month

# disallow comparing fixed to other periods
Expand Down
5 changes: 5 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1751,6 +1751,11 @@ import .Iterators.enumerate
@deprecate enumerate(i::IndexLinear, A::AbstractArray) pairs(i, A)
@deprecate enumerate(i::IndexCartesian, A::AbstractArray) pairs(i, A)

function (::Type{T})(arg) where {T}
depwarn("Constructors no longer fall back to `convert`. A constructor for `$T` should be defined instead.", :Type)
convert(T, arg)::T
end

# END 0.7 deprecations

# BEGIN 1.0 deprecations
Expand Down
18 changes: 9 additions & 9 deletions base/linalg/bidiag.jl
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,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
Expand All @@ -145,14 +145,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)
full(A::Bidiagonal) = convert(Array, A)
Matrix(A::Bidiagonal{T}) where {T} = Matrix{T}(A)
Array(A::Bidiagonal) = Matrix(A)
full(A::Bidiagonal) = Array(A)
promote_rule(::Type{Matrix{T}}, ::Type{<:Bidiagonal{S}}) where {T,S} = Matrix{promote_type(T,S)}

#Converting from Bidiagonal to Tridiagonal
Tridiagonal(M::Bidiagonal{T}) where {T} = convert(Tridiagonal{T}, M)
function convert(::Type{Tridiagonal{T}}, A::Bidiagonal) where T
Tridiagonal(M::Bidiagonal{T}) where {T} = Tridiagonal{T}(M)
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))
Expand All @@ -161,12 +161,12 @@ end
promote_rule(::Type{<:Tridiagonal{T}}, ::Type{<:Bidiagonal{S}}) where {T,S} = Tridiagonal{promote_type(T,S)}

# 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)

Expand Down
34 changes: 17 additions & 17 deletions base/linalg/cholesky.jl
Original file line number Diff line number Diff line change
Expand Up @@ -345,32 +345,32 @@ 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)
full(C::Cholesky) = convert(AbstractArray, 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)
full(C::Cholesky) = AbstractArray(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)
full(F::CholeskyPivoted) = convert(AbstractArray, F)
AbstractArray(F::CholeskyPivoted) = AbstractMatrix(F)
Matrix(F::CholeskyPivoted) = Array(AbstractArray(F))
Array(F::CholeskyPivoted) = Matrix(F)
full(F::CholeskyPivoted) = AbstractArray(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)
Expand Down
12 changes: 6 additions & 6 deletions base/linalg/diagonal.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@ 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(D.diag)
convert(::Type{Array}, D::Diagonal) = convert(Matrix, D)
full(D::Diagonal) = convert(Array, 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(D.diag)
Array(D::Diagonal) = Matrix(D)
full(D::Diagonal) = Array(D)

function similar(D::Diagonal, ::Type{T}) where T
return Diagonal{T}(similar(D.diag, T))
Expand Down
10 changes: 5 additions & 5 deletions base/linalg/eigen.jl
Original file line number Diff line number Diff line change
Expand Up @@ -433,8 +433,8 @@ 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)
full(F::Eigen) = convert(AbstractArray, 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)
full(F::Eigen) = AbstractArray(F)
5 changes: 4 additions & 1 deletion base/linalg/factorization.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,11 @@ 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)

### 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} = A_ldiv_B!(F, eye(T, size(F,1)))

Base.hash(F::Factorization, h::UInt) = mapreduce(f -> hash(getfield(F, f)), hash, h, 1:nfields(F))
Expand Down
12 changes: 6 additions & 6 deletions base/linalg/givens.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ 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)
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]))
Expand Down
16 changes: 8 additions & 8 deletions base/linalg/hessenberg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,14 @@ 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)
full(A::HessenbergQ) = convert(Array, 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)
full(F::Hessenberg) = convert(AbstractArray, F)
Matrix(A::HessenbergQ{<:BlasFloat}) = LAPACK.orghr!(1, size(A.factors, 1), copy(A.factors), A.τ)
Array(A::HessenbergQ) = Matrix(A)
full(A::HessenbergQ) = Array(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)
full(F::Hessenberg) = AbstractArray(F)

A_mul_B!(Q::HessenbergQ{T}, X::StridedVecOrMat{T}) where {T<:BlasFloat} =
LAPACK.ormhr!('L', 'N', 1, size(Q.factors, 1), Q.factors, Q.τ, X)
Expand Down
Loading

0 comments on commit 0c8b5e7

Please sign in to comment.