Skip to content

Commit 66cde46

Browse files
committed
deprecate convert-to-construct fallback
1 parent 0568b2f commit 66cde46

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+388
-397
lines changed

NEWS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ Language changes
1717
* The syntax for parametric methods, `function f{T}(x::T)`, has been
1818
changed to `function f(x::T) where {T}` ([#11310]).
1919

20+
* The fallback constructor that calls `convert` is deprecated. Instead, new types should
21+
prefer to define constructors, and add `convert` methods that call those constructors
22+
only as necessary ([#15120]).
23+
2024
* The syntax `1.+2` is deprecated, since it is ambiguous: it could mean either
2125
`1 .+ 2` (the current meaning) or `1. + 2` ([#19089]).
2226

base/abstractarray.jl

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@ Supertype for `N`-dimensional arrays (or array-like types) with elements of type
1111
"""
1212
AbstractArray
1313

14+
convert(::Type{T}, a::T) where {T<:AbstractArray} = a
15+
convert(::Type{T}, a::AbstractArray) where {T<:AbstractArray} = T(a)
16+
17+
if module_name(@__MODULE__) === :Base # avoid method overwrite
18+
# catch undefined constructors before the deprecation kicks in
19+
# TODO: remove when deprecation is removed
20+
function (::Type{T})(arg) where {T<:AbstractArray}
21+
throw(MethodError(T, (arg,)))
22+
end
23+
end
24+
1425
"""
1526
size(A::AbstractArray, [dim...])
1627
@@ -839,14 +850,6 @@ isempty(a::AbstractArray) = (_length(a) == 0)
839850
# keys with an IndexStyle
840851
keys(s::IndexStyle, A::AbstractArray, B::AbstractArray...) = eachindex(s, A, B...)
841852

842-
## Conversions ##
843-
844-
convert(::Type{AbstractArray{T,N}}, A::AbstractArray{T,N}) where {T,N } = A
845-
convert(::Type{AbstractArray{T,N}}, A::AbstractArray{S,N}) where {T,S,N} = copy!(similar(A,T), A)
846-
convert(::Type{AbstractArray{T}}, A::AbstractArray{S,N}) where {T,S,N} = convert(AbstractArray{T,N}, A)
847-
848-
convert(::Type{Array}, A::AbstractArray{T,N}) where {T,N} = convert(Array{T,N}, A)
849-
850853
"""
851854
of_indices(x, y)
852855

base/array.jl

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -549,23 +549,14 @@ end
549549
one(x::AbstractMatrix{T}) where {T} = _one(one(T), x)
550550
oneunit(x::AbstractMatrix{T}) where {T} = _one(oneunit(T), x)
551551

552-
## Conversions ##
553-
554-
convert(::Type{Vector}, x::AbstractVector{T}) where {T} = convert(Vector{T}, x)
555-
convert(::Type{Matrix}, x::AbstractMatrix{T}) where {T} = convert(Matrix{T}, x)
556-
557-
convert(::Type{Array{T}}, x::Array{T,n}) where {T,n} = x
558-
convert(::Type{Array{T,n}}, x::Array{T,n}) where {T,n} = x
559-
560-
convert(::Type{Array{T}}, x::AbstractArray{S,n}) where {T,n,S} = convert(Array{T,n}, x)
561-
convert(::Type{Array{T,n}}, x::AbstractArray{S,n}) where {T,n,S} = copy!(Array{T,n}(size(x)), x)
562-
563552
promote_rule(a::Type{Array{T,n}}, b::Type{Array{S,n}}) where {T,n,S} = el_same(promote_type(T,S), a, b)
564553

565-
# constructors should make copies
554+
## Constructors ##
566555

567556
if module_name(@__MODULE__) === :Base # avoid method overwrite
568-
(::Type{T})(x::T) where {T<:Array} = copy(x)
557+
# constructors should make copies
558+
Array{T,N}(x::AbstractArray{S,N}) where {T,N,S} = copy!(Array{T,N}(size(x)), x)
559+
AbstractArray{T,N}(A::AbstractArray{S,N}) where {T,N,S} = copy!(similar(A,T), A)
569560
end
570561

571562
## copying iterators to containers

base/bitarray.jl

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -497,21 +497,19 @@ function _bitreshape(B::BitArray, dims::NTuple{N,Int}) where N
497497
return Br
498498
end
499499

500-
## Conversions ##
500+
## Constructors ##
501501

502-
convert(::Type{Array{T}}, B::BitArray{N}) where {T,N} = convert(Array{T,N}, B)
503-
convert(::Type{Array{T,N}}, B::BitArray{N}) where {T,N} = _convert(Array{T,N}, B) # see #15801
504-
function _convert(::Type{Array{T,N}}, B::BitArray{N}) where {T,N}
505-
A = Array{T}(size(B))
502+
function Array{T,N}(B::BitArray{N}) where {T,N}
503+
A = Array{T,N}(size(B))
506504
Bc = B.chunks
507505
@inbounds for i = 1:length(A)
508506
A[i] = unsafe_bitgetindex(Bc, i)
509507
end
510508
return A
511509
end
512510

513-
convert(::Type{BitArray}, A::AbstractArray{T,N}) where {T,N} = convert(BitArray{N}, A)
514-
function convert(::Type{BitArray{N}}, A::AbstractArray{T,N}) where N where T
511+
BitArray(A::AbstractArray{<:Any,N}) where {N} = BitArray{N}(A)
512+
function BitArray{N}(A::AbstractArray{T,N}) where N where T
515513
B = BitArray(size(A))
516514
Bc = B.chunks
517515
l = length(B)
@@ -536,7 +534,7 @@ function convert(::Type{BitArray{N}}, A::AbstractArray{T,N}) where N where T
536534
return B
537535
end
538536

539-
function convert(::Type{BitArray{N}}, A::Array{Bool,N}) where N
537+
function BitArray{N}(A::Array{Bool,N}) where N
540538
B = BitArray(size(A))
541539
Bc = B.chunks
542540
l = length(B)
@@ -545,16 +543,9 @@ function convert(::Type{BitArray{N}}, A::Array{Bool,N}) where N
545543
return B
546544
end
547545

548-
convert(::Type{BitArray{N}}, B::BitArray{N}) where {N} = B
549-
convert(::Type{AbstractArray{T,N}}, B::BitArray{N}) where {T,N} = convert(Array{T,N}, B)
550-
551546
reinterpret(::Type{Bool}, B::BitArray, dims::NTuple{N,Int}) where {N} = reinterpret(B, dims)
552547
reinterpret(B::BitArray, dims::NTuple{N,Int}) where {N} = reshape(B, dims)
553548

554-
## Constructors from generic iterables ##
555-
556-
BitArray(A::AbstractArray{<:Any,N}) where {N} = convert(BitArray{N}, A)
557-
558549
if module_name(@__MODULE__) === :Base # avoid method overwrite
559550
(::Type{T})(x::T) where {T<:BitArray} = copy(x)
560551
end

base/boot.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,13 @@ Array{T}(m::Int, n::Int, o::Int) where {T} = Array{T,3}(m, n, o)
382382

383383
Array{T,1}() where {T} = Array{T,1}(0)
384384

385+
(::Type{Array{T,N} where T})(x::AbstractArray{S,N}) where {S,N} = Array{S,N}(x)
386+
387+
Array(A::AbstractArray{T,N}) where {T,N} = Array{T,N}(A)
388+
Array{T}(A::AbstractArray{S,N}) where {T,N,S} = Array{T,N}(A)
389+
390+
AbstractArray{T}(A::AbstractArray{S,N}) where {T,S,N} = AbstractArray{T,N}(A)
391+
385392
# primitive Symbol constructors
386393
function Symbol(s::String)
387394
return ccall(:jl_symbol_n, Ref{Symbol}, (Ptr{UInt8}, Int),
@@ -602,6 +609,7 @@ UInt128(x::BuiltinInts) = toUInt128(x)::UInt128
602609
UInt32(x::Char) = bitcast(UInt32, x)
603610
Char(x::UInt32) = bitcast(Char, x)
604611
Char(x::Number) = Char(UInt32(x))
612+
Char(x::Char) = x
605613
(::Type{T})(x::Char) where {T<:Number} = T(UInt32(x))
606614

607615
(::Type{T})(x::T) where {T<:Number} = x

base/dates/periods.jl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,8 +401,13 @@ function divexact(x, y)
401401
return q
402402
end
403403

404+
# TODO: this is needed to prevent undefined Period constructors from
405+
# hitting the deprecated construct-to-convert fallback.
406+
(::Type{T})(p::Period) where {T<:Period} = convert(T, p)::T
407+
404408
# FixedPeriod conversions and promotion rules
405-
const fixedperiod_conversions = [(Week, 7), (Day, 24), (Hour, 60), (Minute, 60), (Second, 1000), (Millisecond, 1000), (Microsecond, 1000), (Nanosecond, 1)]
409+
const fixedperiod_conversions = [(:Week, 7), (:Day, 24), (:Hour, 60), (:Minute, 60), (:Second, 1000),
410+
(:Millisecond, 1000), (:Microsecond, 1000), (:Nanosecond, 1)]
406411
for i = 1:length(fixedperiod_conversions)
407412
T, n = fixedperiod_conversions[i]
408413
N = Int64(1)

base/deprecated.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1697,6 +1697,21 @@ export hex2num
16971697

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

1700+
function (::Type{T})(arg) where {T}
1701+
if applicable(convert, T, arg)
1702+
sig = which(convert, (Type{T}, typeof(arg))).sig
1703+
if sig == (Tuple{typeof(convert),Type{S},Number} where S<:Number) ||
1704+
sig == (Tuple{typeof(convert),Type{S},AbstractArray} where S<:AbstractArray)
1705+
# matches a catch-all converter; will stack overflow
1706+
throw(MethodError(T, (arg,)))
1707+
end
1708+
# if `convert` call would not work, just let the method error happen
1709+
depwarn("Constructors no longer fall back to `convert`. A constructor `$T(::$(typeof(arg)))` should be defined instead.", :Type)
1710+
end
1711+
convert(T, arg)::T
1712+
end
1713+
# related items to remove in: abstractarray.jl, dates/periods.jl
1714+
17001715
# Issue #19923
17011716
@deprecate ror circshift
17021717
@deprecate ror! circshift!

base/libgit2/types.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ struct GitHash <: AbstractGitHash
2020
GitHash(val::NTuple{OID_RAWSZ, UInt8}) = new(val)
2121
end
2222
GitHash() = GitHash(ntuple(i->zero(UInt8), OID_RAWSZ))
23+
GitHash(h::GitHash) = h
2324

2425
"""
2526
GitShortHash(hash::GitHash, len::Integer)

base/linalg/bidiag.jl

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ function Bidiagonal(A::AbstractMatrix, uplo::Symbol)
9393
Bidiagonal(diag(A, 0), diag(A, uplo == :U ? 1 : -1), uplo)
9494
end
9595

96+
Bidiagonal(A::Bidiagonal) = A
97+
9698
function getindex(A::Bidiagonal{T}, i::Integer, j::Integer) where T
9799
if !((1 <= i <= size(A,2)) && (1 <= j <= size(A,2)))
98100
throw(BoundsError(A,(i,j)))
@@ -131,7 +133,7 @@ function Base.replace_in_print_matrix(A::Bidiagonal,i::Integer,j::Integer,s::Abs
131133
end
132134

133135
#Converting from Bidiagonal to dense Matrix
134-
function convert(::Type{Matrix{T}}, A::Bidiagonal) where T
136+
function Matrix{T}(A::Bidiagonal) where T
135137
n = size(A, 1)
136138
B = zeros(T, n, n)
137139
for i = 1:n - 1
@@ -145,14 +147,14 @@ function convert(::Type{Matrix{T}}, A::Bidiagonal) where T
145147
B[n,n] = A.dv[n]
146148
return B
147149
end
148-
convert(::Type{Matrix}, A::Bidiagonal{T}) where {T} = convert(Matrix{T}, A)
149-
convert(::Type{Array}, A::Bidiagonal) = convert(Matrix, A)
150-
full(A::Bidiagonal) = convert(Array, A)
150+
Matrix(A::Bidiagonal{T}) where {T} = Matrix{T}(A)
151+
Array(A::Bidiagonal) = Matrix(A)
152+
full(A::Bidiagonal) = Array(A)
151153
promote_rule(::Type{Matrix{T}}, ::Type{<:Bidiagonal{S}}) where {T,S} = Matrix{promote_type(T,S)}
152154

153155
#Converting from Bidiagonal to Tridiagonal
154-
Tridiagonal(M::Bidiagonal{T}) where {T} = convert(Tridiagonal{T}, M)
155-
function convert(::Type{Tridiagonal{T}}, A::Bidiagonal) where T
156+
Tridiagonal(M::Bidiagonal{T}) where {T} = Tridiagonal{T}(M)
157+
function Tridiagonal{T}(A::Bidiagonal) where T
156158
dv = convert(AbstractVector{T}, A.dv)
157159
ev = convert(AbstractVector{T}, A.ev)
158160
z = fill!(similar(ev), zero(T))
@@ -161,12 +163,12 @@ end
161163
promote_rule(::Type{<:Tridiagonal{T}}, ::Type{<:Bidiagonal{S}}) where {T,S} = Tridiagonal{promote_type(T,S)}
162164

163165
# No-op for trivial conversion Bidiagonal{T} -> Bidiagonal{T}
164-
convert(::Type{Bidiagonal{T}}, A::Bidiagonal{T}) where {T} = A
166+
Bidiagonal{T}(A::Bidiagonal{T}) where {T} = A
165167
# Convert Bidiagonal to Bidiagonal{T} by constructing a new instance with converted elements
166-
convert(::Type{Bidiagonal{T}}, A::Bidiagonal) where {T} =
168+
Bidiagonal{T}(A::Bidiagonal) where {T} =
167169
Bidiagonal(convert(AbstractVector{T}, A.dv), convert(AbstractVector{T}, A.ev), A.uplo)
168170
# When asked to convert Bidiagonal to AbstractMatrix{T}, preserve structure by converting to Bidiagonal{T} <: AbstractMatrix{T}
169-
convert(::Type{AbstractMatrix{T}}, A::Bidiagonal) where {T} = convert(Bidiagonal{T}, A)
171+
AbstractMatrix{T}(A::Bidiagonal) where {T} = convert(Bidiagonal{T}, A)
170172

171173
broadcast(::typeof(big), B::Bidiagonal) = Bidiagonal(big.(B.dv), big.(B.ev), B.uplo)
172174

base/linalg/cholesky.jl

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -347,32 +347,32 @@ function cholfact(x::Number, uplo::Symbol=:U)
347347
end
348348

349349

350-
function convert(::Type{Cholesky{T}}, C::Cholesky) where T
350+
function Cholesky{T}(C::Cholesky) where T
351351
Cnew = convert(AbstractMatrix{T}, C.factors)
352352
Cholesky{T, typeof(Cnew)}(Cnew, C.uplo, C.info)
353353
end
354-
convert(::Type{Factorization{T}}, C::Cholesky{T}) where {T} = C
355-
convert(::Type{Factorization{T}}, C::Cholesky) where {T} = convert(Cholesky{T}, C)
356-
convert(::Type{CholeskyPivoted{T}},C::CholeskyPivoted{T}) where {T} = C
357-
convert(::Type{CholeskyPivoted{T}},C::CholeskyPivoted) where {T} =
354+
Factorization{T}(C::Cholesky{T}) where {T} = C
355+
Factorization{T}(C::Cholesky) where {T} = Cholesky{T}(C)
356+
CholeskyPivoted{T}(C::CholeskyPivoted{T}) where {T} = C
357+
CholeskyPivoted{T}(C::CholeskyPivoted) where {T} =
358358
CholeskyPivoted(AbstractMatrix{T}(C.factors),C.uplo,C.piv,C.rank,C.tol,C.info)
359-
convert(::Type{Factorization{T}}, C::CholeskyPivoted{T}) where {T} = C
360-
convert(::Type{Factorization{T}}, C::CholeskyPivoted) where {T} = convert(CholeskyPivoted{T}, C)
359+
Factorization{T}(C::CholeskyPivoted{T}) where {T} = C
360+
Factorization{T}(C::CholeskyPivoted) where {T} = CholeskyPivoted{T}(C)
361361

362-
convert(::Type{AbstractMatrix}, C::Cholesky) = C.uplo == 'U' ? C[:U]'C[:U] : C[:L]*C[:L]'
363-
convert(::Type{AbstractArray}, C::Cholesky) = convert(AbstractMatrix, C)
364-
convert(::Type{Matrix}, C::Cholesky) = convert(Array, convert(AbstractArray, C))
365-
convert(::Type{Array}, C::Cholesky) = convert(Matrix, C)
366-
full(C::Cholesky) = convert(AbstractArray, C)
362+
AbstractMatrix(C::Cholesky) = C.uplo == 'U' ? C[:U]'C[:U] : C[:L]*C[:L]'
363+
AbstractArray(C::Cholesky) = AbstractMatrix(C)
364+
Matrix(C::Cholesky) = Array(AbstractArray(C))
365+
Array(C::Cholesky) = Matrix(C)
366+
full(C::Cholesky) = AbstractArray(C)
367367

368-
function convert(::Type{AbstractMatrix}, F::CholeskyPivoted)
368+
function AbstractMatrix(F::CholeskyPivoted)
369369
ip = invperm(F[:p])
370370
(F[:L] * F[:U])[ip,ip]
371371
end
372-
convert(::Type{AbstractArray}, F::CholeskyPivoted) = convert(AbstractMatrix, F)
373-
convert(::Type{Matrix}, F::CholeskyPivoted) = convert(Array, convert(AbstractArray, F))
374-
convert(::Type{Array}, F::CholeskyPivoted) = convert(Matrix, F)
375-
full(F::CholeskyPivoted) = convert(AbstractArray, F)
372+
AbstractArray(F::CholeskyPivoted) = AbstractMatrix(F)
373+
Matrix(F::CholeskyPivoted) = Array(AbstractArray(F))
374+
Array(F::CholeskyPivoted) = Matrix(F)
375+
full(F::CholeskyPivoted) = AbstractArray(F)
376376

377377
copy(C::Cholesky) = Cholesky(copy(C.factors), C.uplo, C.info)
378378
copy(C::CholeskyPivoted) = CholeskyPivoted(copy(C.factors), C.uplo, C.piv, C.rank, C.tol, C.info)

0 commit comments

Comments
 (0)