Skip to content

Commit

Permalink
Merge pull request #23273 from JuliaLang/jb/ctors
Browse files Browse the repository at this point in the history
deprecate fallback constructor
  • Loading branch information
JeffBezanson authored Dec 21, 2017
2 parents 5fcd0d9 + 31006cf commit 4705ba9
Show file tree
Hide file tree
Showing 83 changed files with 876 additions and 790 deletions.
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]).

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

Expand Down Expand Up @@ -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
Expand Down
19 changes: 11 additions & 8 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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...])
Expand Down Expand Up @@ -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)
Expand Down
11 changes: 11 additions & 0 deletions base/abstractdict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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

"""
Expand Down
43 changes: 24 additions & 19 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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

Expand All @@ -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
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion base/asyncmap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
21 changes: 6 additions & 15 deletions base/bitarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -449,21 +449,19 @@ 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)
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(uninitialized, size(A))
Bc = B.chunks
l = length(B)
Expand All @@ -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)
Expand All @@ -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
Expand Down
6 changes: 0 additions & 6 deletions base/bool.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

## boolean conversions ##

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

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

Expand Down
Loading

0 comments on commit 4705ba9

Please sign in to comment.