Skip to content

Commit 4705ba9

Browse files
authored
Merge pull request #23273 from JuliaLang/jb/ctors
deprecate fallback constructor
2 parents 5fcd0d9 + 31006cf commit 4705ba9

Some content is hidden

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

83 files changed

+876
-790
lines changed

NEWS.md

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

47+
* The fallback constructor that calls `convert` is deprecated. Instead, new types should
48+
prefer to define constructors, and add `convert` methods that call those constructors
49+
only as necessary ([#15120]).
50+
4751
* The syntax `1.+2` is deprecated, since it is ambiguous: it could mean either
4852
`1 .+ 2` (the current meaning) or `1. + 2` ([#19089]).
4953

base/Enums.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ function basetype end
99

1010
abstract type Enum{T<:Integer} end
1111

12-
Base.convert(::Type{Integer}, x::Enum{T}) where {T<:Integer} = bitcast(T, x)
13-
Base.convert(::Type{T}, x::Enum{T2}) where {T<:Integer,T2<:Integer} = convert(T, bitcast(T2, x))
12+
(::Type{T})(x::Enum{T2}) where {T<:Integer,T2<:Integer} = T(bitcast(T2, x))::T
13+
Base.cconvert(::Type{T}, x::Enum{T2}) where {T<:Integer,T2<:Integer} = T(x)
1414
Base.write(io::IO, x::Enum{T}) where {T<:Integer} = write(io, T(x))
1515
Base.read(io::IO, ::Type{T}) where {T<:Enum} = T(read(io, Enums.basetype(T)))
1616

@@ -106,7 +106,7 @@ macro enum(T, syms...)
106106
blk = quote
107107
# enum definition
108108
Base.@__doc__(primitive type $(esc(typename)) <: Enum{$(basetype)} $(sizeof(basetype) * 8) end)
109-
function Base.convert(::Type{$(esc(typename))}, x::Integer)
109+
function $(esc(typename))(x::Integer)
110110
$(membershiptest(:x, values)) || enum_argument_error($(Expr(:quote, typename)), x)
111111
return bitcast($(esc(typename)), convert($(basetype), x))
112112
end

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
@@ -854,14 +865,6 @@ isempty(a::AbstractArray) = (_length(a) == 0)
854865
# keys with an IndexStyle
855866
keys(s::IndexStyle, A::AbstractArray, B::AbstractArray...) = eachindex(s, A, B...)
856867

857-
## Conversions ##
858-
859-
convert(::Type{AbstractArray{T,N}}, A::AbstractArray{T,N}) where {T,N } = A
860-
convert(::Type{AbstractArray{T,N}}, A::AbstractArray{S,N}) where {T,S,N} = copyto!(similar(A,T), A)
861-
convert(::Type{AbstractArray{T}}, A::AbstractArray{S,N}) where {T,S,N} = convert(AbstractArray{T,N}, A)
862-
863-
convert(::Type{Array}, A::AbstractArray{T,N}) where {T,N} = convert(Array{T,N}, A)
864-
865868
"""
866869
of_indices(x, y)
867870

base/abstractdict.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,17 @@ push!(t::AbstractDict, p::Pair) = setindex!(t, p.second, p.first)
502502
push!(t::AbstractDict, p::Pair, q::Pair) = push!(push!(t, p), q)
503503
push!(t::AbstractDict, p::Pair, q::Pair, r::Pair...) = push!(push!(push!(t, p), q), r...)
504504

505+
# AbstractDicts are convertible
506+
convert(::Type{T}, x::T) where {T<:AbstractDict} = x
507+
508+
function convert(::Type{T}, x::AbstractDict) where T<:AbstractDict
509+
h = T(x)
510+
if length(h) != length(x)
511+
error("key collision during dictionary conversion")
512+
end
513+
return h
514+
end
515+
505516
# hashing objects by identity
506517

507518
"""

base/array.jl

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ function ones end
381381

382382
for (fname, felt) in ((:zeros, :zero), (:ones, :one))
383383
@eval begin
384-
$fname(::Type{T}, dims::NTuple{N, Any}) where {T, N} = fill!(Array{T,N}(uninitialized, Dims(dims)), $felt(T))
384+
$fname(::Type{T}, dims::NTuple{N, Any}) where {T, N} = fill!(Array{T,N}(uninitialized, convert(Dims, dims)::Dims), $felt(T))
385385
$fname(dims::Tuple) = ($fname)(Float64, dims)
386386
$fname(::Type{T}, dims...) where {T} = $fname(T, dims)
387387
$fname(dims...) = $fname(dims)
@@ -402,21 +402,14 @@ oneunit(x::AbstractMatrix{T}) where {T} = _one(oneunit(T), x)
402402
# arises in similar(dest, Pair{Union{},Union{}}) where dest::Dict:
403403
convert(::Type{Vector{Union{}}}, a::Vector{Union{}}) = a
404404

405-
convert(::Type{Vector}, x::AbstractVector{T}) where {T} = convert(Vector{T}, x)
406-
convert(::Type{Matrix}, x::AbstractMatrix{T}) where {T} = convert(Matrix{T}, x)
407-
408-
convert(::Type{Array{T}}, x::Array{T,n}) where {T,n} = x
409-
convert(::Type{Array{T,n}}, x::Array{T,n}) where {T,n} = x
410-
411-
convert(::Type{Array{T}}, x::AbstractArray{S,n}) where {T,n,S} = convert(Array{T,n}, x)
412-
convert(::Type{Array{T,n}}, x::AbstractArray{S,n}) where {T,n,S} = copyto!(Array{T,n}(uninitialized, size(x)), x)
413-
414405
promote_rule(a::Type{Array{T,n}}, b::Type{Array{S,n}}) where {T,n,S} = el_same(promote_type(T,S), a, b)
415406

416-
# constructors should make copies
407+
## Constructors ##
417408

418409
if module_name(@__MODULE__) === :Base # avoid method overwrite
419-
(::Type{T})(x::T) where {T<:Array} = copy(x)
410+
# constructors should make copies
411+
Array{T,N}(x::AbstractArray{S,N}) where {T,N,S} = copyto!(Array{T,N}(uninitialized, size(x)), x)
412+
AbstractArray{T,N}(A::AbstractArray{S,N}) where {T,N,S} = copyto!(similar(A,T), A)
420413
end
421414

422415
## copying iterators to containers
@@ -504,14 +497,26 @@ end
504497
# gets a chance to see it, so that recursive calls to the caller
505498
# don't trigger the inference limiter
506499
if isdefined(Core, :Inference)
507-
macro default_eltype(itrt)
500+
macro default_eltype(itr)
501+
I = esc(itr)
508502
return quote
509-
Core.Inference.return_type(first, Tuple{$(esc(itrt))})
503+
if $I isa Generator && ($I).f isa Type
504+
($I).f
505+
else
506+
Core.Inference.return_type(first, Tuple{typeof($I)})
507+
end
510508
end
511509
end
512510
else
513-
macro default_eltype(itrt)
514-
return :(Any)
511+
macro default_eltype(itr)
512+
I = esc(itr)
513+
return quote
514+
if $I isa Generator && ($I).f isa Type
515+
($I).f
516+
else
517+
Any
518+
end
519+
end
515520
end
516521
end
517522

@@ -520,7 +525,7 @@ _array_for(::Type{T}, itr, ::HasShape) where {T} = similar(Array{T}, axes(itr)):
520525

521526
function collect(itr::Generator)
522527
isz = iteratorsize(itr.iter)
523-
et = @default_eltype(typeof(itr))
528+
et = @default_eltype(itr)
524529
if isa(isz, SizeUnknown)
525530
return grow_to!(Vector{et}(), itr)
526531
else
@@ -534,12 +539,12 @@ function collect(itr::Generator)
534539
end
535540

536541
_collect(c, itr, ::EltypeUnknown, isz::SizeUnknown) =
537-
grow_to!(_similar_for(c, @default_eltype(typeof(itr)), itr, isz), itr)
542+
grow_to!(_similar_for(c, @default_eltype(itr), itr, isz), itr)
538543

539544
function _collect(c, itr, ::EltypeUnknown, isz::Union{HasLength,HasShape})
540545
st = start(itr)
541546
if done(itr,st)
542-
return _similar_for(c, @default_eltype(typeof(itr)), itr, isz)
547+
return _similar_for(c, @default_eltype(itr), itr, isz)
543548
end
544549
v1, st = next(itr, st)
545550
collect_to_with_first!(_similar_for(c, typeof(v1), itr, isz), v1, itr, st)

base/asyncmap.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ end
248248
function asyncmap(f, s::AbstractString; kwargs...)
249249
s2 = Vector{Char}(uninitialized, length(s))
250250
asyncmap!(f, s2, s; kwargs...)
251-
return convert(String, s2)
251+
return String(s2)
252252
end
253253

254254
# map on a single BitArray returns a BitArray if the mapping function is boolean.

base/bitarray.jl

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

452-
## Conversions ##
452+
## Constructors ##
453453

454-
convert(::Type{Array{T}}, B::BitArray{N}) where {T,N} = convert(Array{T,N}, B)
455-
convert(::Type{Array{T,N}}, B::BitArray{N}) where {T,N} = _convert(Array{T,N}, B) # see #15801
456-
function _convert(::Type{Array{T,N}}, B::BitArray{N}) where {T,N}
457-
A = Array{T}(uninitialized, size(B))
454+
function Array{T,N}(B::BitArray{N}) where {T,N}
455+
A = Array{T,N}(uninitialized, size(B))
458456
Bc = B.chunks
459457
@inbounds for i = 1:length(A)
460458
A[i] = unsafe_bitgetindex(Bc, i)
461459
end
462460
return A
463461
end
464462

465-
convert(::Type{BitArray}, A::AbstractArray{T,N}) where {T,N} = convert(BitArray{N}, A)
466-
function convert(::Type{BitArray{N}}, A::AbstractArray{T,N}) where N where T
463+
BitArray(A::AbstractArray{<:Any,N}) where {N} = BitArray{N}(A)
464+
function BitArray{N}(A::AbstractArray{T,N}) where N where T
467465
B = BitArray(uninitialized, size(A))
468466
Bc = B.chunks
469467
l = length(B)
@@ -488,7 +486,7 @@ function convert(::Type{BitArray{N}}, A::AbstractArray{T,N}) where N where T
488486
return B
489487
end
490488

491-
function convert(::Type{BitArray{N}}, A::Array{Bool,N}) where N
489+
function BitArray{N}(A::Array{Bool,N}) where N
492490
B = BitArray(uninitialized, size(A))
493491
Bc = B.chunks
494492
l = length(B)
@@ -497,16 +495,9 @@ function convert(::Type{BitArray{N}}, A::Array{Bool,N}) where N
497495
return B
498496
end
499497

500-
convert(::Type{BitArray{N}}, B::BitArray{N}) where {N} = B
501-
convert(::Type{AbstractArray{T,N}}, B::BitArray{N}) where {T,N} = convert(Array{T,N}, B)
502-
503498
reinterpret(::Type{Bool}, B::BitArray, dims::NTuple{N,Int}) where {N} = reinterpret(B, dims)
504499
reinterpret(B::BitArray, dims::NTuple{N,Int}) where {N} = reshape(B, dims)
505500

506-
## Constructors from generic iterables ##
507-
508-
BitArray(A::AbstractArray{<:Any,N}) where {N} = convert(BitArray{N}, A)
509-
510501
if module_name(@__MODULE__) === :Base # avoid method overwrite
511502
(::Type{T})(x::T) where {T<:BitArray} = copy(x)
512503
end

base/bool.jl

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
# This file is a part of Julia. License is MIT: https://julialang.org/license
22

3-
## boolean conversions ##
4-
5-
convert(::Type{Bool}, x::Bool) = x
6-
convert(::Type{Bool}, x::Float16) = x==0 ? false : x==1 ? true : throw(InexactError(:convert, Bool, x))
7-
convert(::Type{Bool}, x::Real) = x==0 ? false : x==1 ? true : throw(InexactError(:convert, Bool, x))
8-
93
# promote Bool to any other numeric type
104
promote_rule(::Type{Bool}, ::Type{T}) where {T<:Number} = T
115

0 commit comments

Comments
 (0)