Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

replace export of isleaftype with a more simply-defined isconcrete #23666

Merged
merged 1 commit into from
Sep 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,11 @@ Deprecated or removed
been deprecated due to inconsistency with linear algebra. Use `.+` and `.-` for these operations
instead.

* `isleaftype` is deprecated in favor of a simpler predicate `isconcrete`. Concrete types are
those that might equal `typeof(x)` for some `x`; `isleaftype` includes some types for which
this is not true. If you are certain you need the old behavior, it is temporarily available
as `Base._isleaftype` ([#17086]).

Command-line option changes
---------------------------

Expand Down
6 changes: 3 additions & 3 deletions base/broadcast.jl
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ _nullable_eltype(f, A, As...) =
T = _broadcast_eltype(f, A, Bs...)
shape = broadcast_indices(A, Bs...)
iter = CartesianRange(shape)
if isleaftype(T)
if Base._isleaftype(T)
return broadcast_t(f, T, shape, iter, A, Bs...)
end
if isempty(iter)
Expand All @@ -320,8 +320,8 @@ end
@inline function broadcast_c(f, ::Type{Nullable}, a...)
nonnull = all(hasvalue, a)
S = _nullable_eltype(f, a...)
if isleaftype(S) && null_safe_op(f, maptoTuple(_unsafe_get_eltype,
a...).types...)
if Base._isleaftype(S) && null_safe_op(f, maptoTuple(_unsafe_get_eltype,
a...).types...)
Nullable{S}(f(map(unsafe_get, a)...), nonnull)
else
if nonnull
Expand Down
2 changes: 1 addition & 1 deletion base/complex.jl
Original file line number Diff line number Diff line change
Expand Up @@ -958,7 +958,7 @@ big(z::Complex{T}) where {T<:Real} = Complex{big(T)}(z)
complex(A::AbstractArray{<:Complex}) = A

function complex(A::AbstractArray{T}) where T
if !isleaftype(T)
if !isconcrete(T)
error("`complex` not defined on abstractly-typed arrays; please convert to a more specific type")
end
convert(AbstractArray{typeof(complex(zero(T)))}, A)
Expand Down
3 changes: 3 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1766,6 +1766,9 @@ import .Iterators.enumerate
# issue #5794
@deprecate map(f, d::T) where {T<:Associative} T( f(p) for p in pairs(d) )

# issue #17086
@deprecate isleaftype isconcrete

# PR #22932
@deprecate +(a::Number, b::AbstractArray) broadcast(+, a, b)
@deprecate +(a::AbstractArray, b::Number) broadcast(+, a, b)
Expand Down
4 changes: 2 additions & 2 deletions base/dict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function show(io::IO, t::Associative{K,V}) where V where K
if isempty(t)
print(io, typeof(t), "()")
else
if isleaftype(K) && isleaftype(V)
if _isleaftype(K) && _isleaftype(V)
print(io, typeof(t).name)
else
print(io, typeof(t))
Expand Down Expand Up @@ -161,7 +161,7 @@ associative_with_eltype(DT_apply, ::Type) = DT_apply(Any, Any)()
associative_with_eltype(DT_apply::F, kv, t) where {F} = grow_to!(associative_with_eltype(DT_apply, _default_eltype(typeof(kv))), kv)
function associative_with_eltype(DT_apply::F, kv::Generator, t) where F
T = _default_eltype(typeof(kv))
if T <: Union{Pair, Tuple{Any, Any}} && isleaftype(T)
if T <: Union{Pair, Tuple{Any, Any}} && _isleaftype(T)
return associative_with_eltype(DT_apply, kv, T)
end
return grow_to!(associative_with_eltype(DT_apply, T), kv)
Expand Down
2 changes: 1 addition & 1 deletion base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -931,7 +931,7 @@ export
fieldname,
fieldnames,
fieldcount,
isleaftype,
isconcrete,
oftype,
promote,
promote_rule,
Expand Down
2 changes: 1 addition & 1 deletion base/float.jl
Original file line number Diff line number Diff line change
Expand Up @@ -877,7 +877,7 @@ Base.iszero(x::Float16) = reinterpret(UInt16, x) & ~sign_mask(Float16) == 0x0000
float(A::AbstractArray{<:AbstractFloat}) = A

function float(A::AbstractArray{T}) where T
if !isleaftype(T)
if !isconcrete(T)
error("`float` not defined on abstractly-typed arrays; please convert to a more specific type")
end
convert(AbstractArray{typeof(float(zero(T)))}, A)
Expand Down
2 changes: 2 additions & 0 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ const NF = NotFound()
const LineNum = Int
const VarTable = Array{Any,1}

const isleaftype = _isleaftype

# The type of a variable load is either a value or an UndefVarError
mutable struct VarState
typ
Expand Down
2 changes: 1 addition & 1 deletion base/interactiveutil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ Evaluates the arguments to the function or macro call, determines their types, a
function type_close_enough(@nospecialize(x), @nospecialize(t))
x == t && return true
return (isa(x,DataType) && isa(t,DataType) && x.name === t.name &&
!isleaftype(t) && x <: t) ||
!_isleaftype(t) && x <: t) ||
(isa(x,Union) && isa(t,DataType) && (type_close_enough(x.a, t) || type_close_enough(x.b, t)))
end

Expand Down
11 changes: 4 additions & 7 deletions base/iterators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -733,17 +733,14 @@ iteratoreltype(::Type{Flatten{I}}) where {I} = _flatteneltype(I, iteratoreltype(
_flatteneltype(I, ::HasEltype) = iteratoreltype(eltype(I))
_flatteneltype(I, et) = EltypeUnknown()

flatten_iteratorsize(::Union{HasShape, HasLength}, b::Type{<:Tuple}) = isleaftype(b) ? HasLength() : SizeUnknown()
flatten_iteratorsize(::Union{HasShape, HasLength}, b::Type{<:Number}) = HasLength()
flatten_iteratorsize(::Union{HasShape, HasLength}, ::Type{<:NTuple{N,Any}}) where {N} = HasLength()
flatten_iteratorsize(::Union{HasShape, HasLength}, ::Type{<:Tuple}) = SizeUnknown()
flatten_iteratorsize(::Union{HasShape, HasLength}, ::Type{<:Number}) = HasLength()
flatten_iteratorsize(a, b) = SizeUnknown()

iteratorsize(::Type{Flatten{I}}) where {I} = flatten_iteratorsize(iteratorsize(I), eltype(I))

function flatten_length(f, ::Type{T}) where {T<:Tuple}
if !isleaftype(T)
throw(ArgumentError(
"Cannot compute length of a tuple-type which is not a leaf-type"))
end
function flatten_length(f, T::Type{<:NTuple{N,Any}}) where {N}
fieldcount(T)*length(f.it)
end
flatten_length(f, ::Type{<:Number}) = length(f.it)
Expand Down
4 changes: 2 additions & 2 deletions base/methodshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ function show(io::IO, m::Method; kwtype::Nullable{DataType}=Nullable{DataType}()
# TODO: more accurate test? (tn.name === "#" name)
ft0 === typeof(getfield(ft.name.module, ft.name.mt.name))
print(io, ft.name.mt.name)
elseif isa(ft, DataType) && ft.name === Type.body.name && isleaftype(ft)
elseif isa(ft, DataType) && ft.name === Type.body.name
f = ft.parameters[1]
if isa(f, DataType) && isempty(f.parameters)
print(io, f)
Expand Down Expand Up @@ -235,7 +235,7 @@ function show(io::IO, ::MIME"text/html", m::Method; kwtype::Nullable{DataType}=N
isdefined(ft.name.module, ft.name.mt.name) &&
ft0 === typeof(getfield(ft.name.module, ft.name.mt.name))
print(io, ft.name.mt.name)
elseif isa(ft, DataType) && ft.name === Type.body.name && isleaftype(ft)
elseif isa(ft, DataType) && ft.name === Type.body.name
f = ft.parameters[1]
if isa(f, DataType) && isempty(f.parameters)
print(io, f)
Expand Down
4 changes: 2 additions & 2 deletions base/nullable.jl
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ end
"""
Return the given type if it is concrete, and `Union{}` otherwise.
"""
nullable_returntype(::Type{T}) where {T} = isleaftype(T) ? T : Union{}
nullable_returntype(::Type{T}) where {T} = _isleaftype(T) ? T : Union{}

"""
map(f, x::Nullable)
Expand All @@ -365,7 +365,7 @@ Nullable{Bool}()
"""
function map(f, x::Nullable{T}) where T
S = promote_op(f, T)
if isleaftype(S) && null_safe_op(f, T)
if _isleaftype(S) && null_safe_op(f, T)
Nullable(f(unsafe_get(x)), !isnull(x))
else
if isnull(x)
Expand Down
4 changes: 2 additions & 2 deletions base/promotion.jl
Original file line number Diff line number Diff line change
Expand Up @@ -346,13 +346,13 @@ promote_op(::Any...) = (@_inline_meta; Any)
function promote_op(f, ::Type{S}) where S
@_inline_meta
T = _return_type(f, Tuple{_default_type(S)})
isleaftype(S) && return isleaftype(T) ? T : Any
_isleaftype(S) && return _isleaftype(T) ? T : Any
return typejoin(S, T)
end
function promote_op(f, ::Type{R}, ::Type{S}) where {R,S}
@_inline_meta
T = _return_type(f, Tuple{_default_type(R), _default_type(S)})
isleaftype(R) && isleaftype(S) && return isleaftype(T) ? T : Any
_isleaftype(R) && _isleaftype(S) && return _isleaftype(T) ? T : Any
return typejoin(R, S, T)
end

Expand Down
33 changes: 23 additions & 10 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -287,28 +287,41 @@ isbits(t::DataType) = (@_pure_meta; !t.mutable & (t.layout != C_NULL) && datatyp
isbits(t::Type) = (@_pure_meta; false)
isbits(x) = (@_pure_meta; isbits(typeof(x)))

_isleaftype(@nospecialize(t)) = (@_pure_meta; isa(t, DataType) && t.isleaftype)

"""
isleaftype(T)
isconcrete(T)

Determine whether `T`'s only subtypes are itself and `Union{}`. This means `T` is
a concrete type that can have instances.
Determine whether `T` is a concrete type, meaning it can have direct instances
(values `x` such that `typeof(x) === T`).

# Examples
```jldoctest
julia> isleaftype(Complex)
julia> isconcrete(Complex)
false

julia> isleaftype(Complex{Float32})
julia> isconcrete(Complex{Float32})
true

julia> isleaftype(Vector{Complex})
julia> isconcrete(Vector{Complex})
true

julia> isleaftype(Vector{Complex{Float32}})
julia> isconcrete(Vector{Complex{Float32}})
true

julia> isconcrete(Union{})
false

julia> isconcrete(Union{Int,String})
false
```
"""
isleaftype(@nospecialize(t)) = (@_pure_meta; isa(t, DataType) && t.isleaftype)
function isconcrete(@nospecialize(t))
@_pure_meta
return (isa(t, DataType) && !t.abstract &&
!t.hasfreetypevars &&
(t.name !== Tuple.name || all(isconcrete, t.parameters)))
end

"""
Base.isabstract(T)
Expand Down Expand Up @@ -791,7 +804,7 @@ function _dump_function_linfo(linfo::Core.MethodInstance, world::UInt, native::B
end

# TODO: use jl_is_cacheable_sig instead of isleaftype
isleaftype(linfo.specTypes) || (str = "; WARNING: This code may not match what actually runs.\n" * str)
_isleaftype(linfo.specTypes) || (str = "; WARNING: This code may not match what actually runs.\n" * str)
return str
end

Expand Down Expand Up @@ -822,7 +835,7 @@ code_native(::IO, ::Any, ::Symbol) = error("illegal code_native call") # resolve

# give a decent error message if we try to instantiate a staged function on non-leaf types
function func_for_method_checked(m::Method, @nospecialize types)
if isdefined(m,:generator) && !isdefined(m,:source) && !isleaftype(types)
if isdefined(m,:generator) && !isdefined(m,:source) && !_isleaftype(types)
error("cannot call @generated function `", m, "` ",
"with abstract argument types: ", types)
end
Expand Down
2 changes: 1 addition & 1 deletion base/refpointer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ convert(::Type{Ref{T}}, x) where {T} = RefValue{T}(x)
function unsafe_convert(P::Type{Ptr{T}}, b::RefValue{T}) where T
if isbits(T) || isbitsunion(T)
return convert(P, pointer_from_objref(b))
elseif isleaftype(T)
elseif _isleaftype(T)
return convert(P, pointer_from_objref(b.x))
else
# If the slot is not leaf type, it could be either isbits or not.
Expand Down
2 changes: 1 addition & 1 deletion base/replutil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ function show_method_candidates(io::IO, ex::MethodError, kwargs::Vector=Any[])
# pool MethodErrors for these two functions.
if f === convert && !isempty(arg_types_param)
at1 = arg_types_param[1]
if isa(at1,DataType) && (at1::DataType).name === Type.body.name && isleaftype(at1)
if isa(at1,DataType) && (at1::DataType).name === Type.body.name && !Core.Inference.has_free_typevars(at1)
push!(funcs, (at1.parameters[1], arg_types_param[2:end]))
end
end
Expand Down
4 changes: 2 additions & 2 deletions base/set.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ for sets of arbitrary objects.
Set(itr) = Set{eltype(itr)}(itr)
function Set(g::Generator)
T = _default_eltype(typeof(g))
(isleaftype(T) || T === Union{}) || return grow_to!(Set{T}(), g)
(_isleaftype(T) || T === Union{}) || return grow_to!(Set{T}(), g)
return Set{T}(g)
end

Expand Down Expand Up @@ -266,7 +266,7 @@ function unique(itr)
return out
end
x, i = next(itr, i)
if !isleaftype(T) && iteratoreltype(itr) == EltypeUnknown()
if !_isleaftype(T) && iteratoreltype(itr) == EltypeUnknown()
S = typeof(x)
return _unique_from(itr, S[x], Set{S}((x,)), i)
end
Expand Down
8 changes: 4 additions & 4 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ function show_type_name(io::IO, tn::TypeName)
globname_str = string(globname)
if ('#' ∉ globname_str && '@' ∉ globname_str && isdefined(tn, :module) &&
isbindingresolved(tn.module, globname) && isdefined(tn.module, globname) &&
isa(getfield(tn.module, globname), tn.wrapper) && isleaftype(tn.wrapper))
isa(getfield(tn.module, globname), tn.wrapper) && _isleaftype(tn.wrapper))
globfunc = true
end
end
Expand Down Expand Up @@ -617,7 +617,7 @@ function show_expr_type(io::IO, @nospecialize(ty), emph::Bool)
elseif ty === Core.IntrinsicFunction
print(io, "::I")
else
if emph && (!isleaftype(ty) || ty == Core.Box)
if emph && (!_isleaftype(ty) || ty == Core.Box)
emphasize(io, "::$ty")
else
print(io, "::$ty")
Expand Down Expand Up @@ -1171,7 +1171,7 @@ function show_tuple_as_call(io::IO, name::Symbol, sig::Type)
isdefined(uw.name.module, uw.name.mt.name) &&
ft == typeof(getfield(uw.name.module, uw.name.mt.name))
print(io, uw.name.mt.name)
elseif isa(ft, DataType) && ft.name === Type.body.name && isleaftype(ft)
elseif isa(ft, DataType) && ft.name === Type.body.name && !Core.Inference.has_free_typevars(ft)
f = ft.parameters[1]
print(io, f)
else
Expand Down Expand Up @@ -1913,7 +1913,7 @@ function array_eltype_show_how(X)
str = string(e)
end
# Types hard-coded here are those which are created by default for a given syntax
(isleaftype(e),
(_isleaftype(e),
(!isempty(X) && (e===Float64 || e===Int || e===Char || e===String) ? "" : str))
end

Expand Down
2 changes: 1 addition & 1 deletion doc/src/stdlib/base.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ Base.fieldoffset
Core.fieldtype
Base.isimmutable
Base.isbits
Base.isleaftype
Base.isconcrete
Base.typejoin
Base.typeintersect
Base.instances
Expand Down
2 changes: 1 addition & 1 deletion test/arrayops.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1916,7 +1916,7 @@ let A = zeros(Int, 2, 2), B = zeros(Float64, 2, 2)
for f in [f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16,
f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28, f29, f30,
f31, f32, f33, f34, f35, f36, f37, f38, f39, f40, f41, f42]
@test isleaftype(Base.return_types(f, ())[1])
@test Base._isleaftype(Base.return_types(f, ())[1])
end
end

Expand Down
4 changes: 2 additions & 2 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ let elT = T22624.body.body.body.types[1].parameters[1]
elT2 = elT.body.types[1].parameters[1]
@test elT2 == T22624{Int64, Int64, C} where C
@test elT2.body.types[1].parameters[1] === elT2
@test isleaftype(elT2.body.types[1])
@test Base._isleaftype(elT2.body.types[1])
end

# issue #3890
Expand Down Expand Up @@ -4284,7 +4284,7 @@ let a = Val{Val{TypeVar(:_, Int)}},

@test !isdefined(a, :instance)
@test isdefined(b, :instance)
@test isleaftype(b)
@test Base._isleaftype(b)
end

# A return type widened to Type{Union{T,Void}} should not confuse
Expand Down
1 change: 1 addition & 0 deletions test/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ function find_tvar10930(arg)
end
@test find_tvar10930(Vararg{Int}) === 1

const isleaftype = Base._isleaftype
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't this be written as using Base: _isleaftype? That's a little clearer, IMO.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No; this file has a lot of uses of the function and I wanted to avoid the churn of changing all of them.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, thanks for the explanation


# issue #12474
@generated function f12474(::Any)
Expand Down
Loading