diff --git a/NEWS.md b/NEWS.md index 076b00cedd43d..1aa135fec5ee6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -254,6 +254,8 @@ Deprecated or removed * Calling `write` on non-isbits arrays is deprecated in favor of explicit loops or `serialize` ([#6466]). + * The function `isleaftype` is deprecated in favor of `isconcrete` ([#20709]). + * The default `juliarc.jl` file on Windows has been removed. Now must explicitly include the full path if you need access to executables or libraries in the `JULIA_HOME` directory, e.g. `joinpath(JULIA_HOME, "7z.exe")` for `7z.exe` ([#21540]). diff --git a/base/broadcast.jl b/base/broadcast.jl index 1b847aa7ddb6d..0bddd968162e3 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -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 isconcrete(T) return broadcast_t(f, T, shape, iter, A, Bs...) end if isempty(iter) @@ -320,7 +320,7 @@ 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, + if isconcrete(S) && null_safe_op(f, maptoTuple(_unsafe_get_eltype, a...).types...) Nullable{S}(f(map(unsafe_get, a)...), nonnull) else diff --git a/base/complex.jl b/base/complex.jl index 64b80ae149076..65db3392a3dd2 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -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) diff --git a/base/deprecated.jl b/base/deprecated.jl index 2cb868c64a7b8..cacf62a9ccaec 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1595,6 +1595,8 @@ end # issue #6466 # `write` on non-isbits arrays is deprecated in io.jl. +@deprecate isleaftype isconcrete + # PR #22925 # also uncomment constructor tests in test/linalg/bidiag.jl function Bidiagonal(dv::AbstractVector{T}, ev::AbstractVector{S}, uplo::Symbol) where {T,S} diff --git a/base/dict.jl b/base/dict.jl index e0ddcaaee649e..ced9824a6daac 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -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 isconcrete(K) && isconcrete(V) print(io, typeof(t).name) else print(io, typeof(t)) @@ -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}} && isconcrete(T) return associative_with_eltype(DT_apply, kv, T) end return grow_to!(associative_with_eltype(DT_apply, T), kv) diff --git a/base/exports.jl b/base/exports.jl index 80601067a1dce..e9f514d544172 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -949,7 +949,7 @@ export fieldname, fieldnames, fieldcount, - isleaftype, + isconcrete, oftype, promote, promote_rule, diff --git a/base/float.jl b/base/float.jl index 40242fab6b112..d7a2724f2f3df 100644 --- a/base/float.jl +++ b/base/float.jl @@ -853,7 +853,7 @@ truncmask(x, mask) = x 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) diff --git a/base/inference.jl b/base/inference.jl index 27945928da9a8..9aa2c69c81e9f 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -15,7 +15,7 @@ struct InferenceParams # optimization inlining::Bool inline_cost_threshold::Int # number of CPU cycles beyond which it's not worth inlining - inline_nonleaf_penalty::Int # penalty for dynamic dispatch + inline_nonconcrete_penalty::Int # penalty for dynamic dispatch inline_tupleret_bonus::Int # extra willingness for non-isbits tuple return types # parameters limiting potentially-infinite types (configurable) @@ -30,7 +30,7 @@ struct InferenceParams function InferenceParams(world::UInt; inlining::Bool = inlining_enabled(), inline_cost_threshold::Int = 100, - inline_nonleaf_penalty::Int = 1000, + inline_nonconcrete_penalty::Int = 1000, inline_tupleret_bonus::Int = 400, max_methods::Int = 4, tupletype_len::Int = 15, @@ -38,7 +38,7 @@ struct InferenceParams tuple_splat::Int = 16, union_splitting::Int = 4, apply_union_enum::Int = 8) - return new(world, inlining, inline_cost_threshold, inline_nonleaf_penalty, + return new(world, inlining, inline_cost_threshold, inline_nonconcrete_penalty, inline_tupleret_bonus, max_methods, tupletype_len, tuple_depth, tuple_splat, union_splitting, apply_union_enum) end @@ -383,7 +383,7 @@ const _Type_name = Type.body.name isType(@nospecialize t) = isa(t, DataType) && (t::DataType).name === _Type_name # true if Type is inlineable as constant (is a singleton) -isconstType(@nospecialize t) = isType(t) && (isleaftype(t.parameters[1]) || t.parameters[1] === Union{}) +isconstType(@nospecialize t) = isType(t) && (isconcrete(t.parameters[1]) || t.parameters[1] === Union{}) iskindtype(@nospecialize t) = (t === DataType || t === UnionAll || t === Union || t === typeof(Bottom)) @@ -637,7 +637,7 @@ add_tfunc(Core.sizeof, 1, 1, isa(x, Const) && return _const_sizeof(x.val) isa(x, Conditional) && return _const_sizeof(Bool) isconstType(x) && return _const_sizeof(x.parameters[1]) - x !== DataType && isleaftype(x) && return _const_sizeof(x) + x !== DataType && isconcrete(x) && return _const_sizeof(x) return Int end, 0) old_nfields(@nospecialize x) = length((isa(x,DataType) ? x : typeof(x)).types) @@ -647,7 +647,7 @@ add_tfunc(nfields, 1, 1, isa(x,Conditional) && return Const(old_nfields(Bool)) if isType(x) # TODO: remove with deprecation in builtins.c for nfields(::Type) - isleaftype(x.parameters[1]) && return Const(old_nfields(x.parameters[1])) + isconcrete(x.parameters[1]) && return Const(old_nfields(x.parameters[1])) elseif isa(x,DataType) && !x.abstract && !(x.name === Tuple.name && isvatuple(x)) && x !== DataType return Const(length(x.types)) end @@ -681,13 +681,13 @@ function typeof_tfunc(@nospecialize(t)) return Const(Bool) elseif isType(t) tp = t.parameters[1] - if !isleaftype(tp) + if !isconcrete(tp) return DataType # typeof(Kind::Type)::DataType else return Const(typeof(tp)) # XXX: this is not necessarily true end elseif isa(t, DataType) - if isleaftype(t) || isvarargtype(t) + if isconcrete(t) || isvarargtype(t) return Const(t) elseif t === Any return DataType @@ -734,7 +734,7 @@ add_tfunc(isa, 2, 2, if isexact return Const(true) end - elseif isa(v, Const) || isa(v, Conditional) || (isleaftype(v) && !iskindtype(v)) + elseif isa(v, Const) || isa(v, Conditional) || (isconcrete(v) && !iskindtype(v)) return Const(false) elseif isexact && typeintersect(v, t) === Bottom if !iskindtype(v) #= subtyping currently intentionally answers this query incorrectly for kinds =# @@ -742,7 +742,7 @@ add_tfunc(isa, 2, 2, end end end - # TODO: handle non-leaftype(t) by testing against lower and upper bounds + # TODO: handle non-concrete t by testing against lower and upper bounds return Bool end, 0) add_tfunc(<:, 2, 2, @@ -974,7 +974,7 @@ function is_derived_type(@nospecialize(t), @nospecialize(c)) # try to find `type for p in cP is_derived_type(t, p) && return true end - if isleaftype(c) && isbits(c) + if isconcrete(c) && isbits(c) # see if it was extracted from a fieldtype # however, only look through types that can be inlined # to ensure monotonicity of derivation @@ -1128,7 +1128,7 @@ function getfield_tfunc(@nospecialize(s00), name) elseif isa(s, Const) || isType(s) if !isa(s, Const) p1 = s.parameters[1] - if !isleaftype(p1) + if !isconcrete(p1) return Any end sv = p1 @@ -1214,7 +1214,7 @@ function getfield_tfunc(@nospecialize(s00), name) if fld < 1 || fld > nf return Bottom end - if isType(s00) && isleaftype(s00.parameters[1]) + if isType(s00) && isconcrete(s00.parameters[1]) sp = s00.parameters[1] elseif isa(s00, Const) && isa(s00.val, DataType) sp = s00.val @@ -1314,7 +1314,7 @@ has_free_typevars(@nospecialize(t)) = ccall(:jl_has_free_typevars, Cint, (Any,), function apply_type_tfunc(@nospecialize(headtypetype), @nospecialize args...) if isa(headtypetype, Const) headtype = headtypetype.val - elseif isType(headtypetype) && isleaftype(headtypetype.parameters[1]) + elseif isType(headtypetype) && isconcrete(headtypetype.parameters[1]) headtype = headtypetype.parameters[1] else return Any @@ -1337,7 +1337,7 @@ function apply_type_tfunc(@nospecialize(headtypetype), @nospecialize args...) ai = args[i] if isType(ai) aty = ai.parameters[1] - isleaftype(aty) || (allconst = false) + isconcrete(aty) || (allconst = false) else aty = (ai::Const).val end @@ -1433,7 +1433,7 @@ add_tfunc(apply_type, 1, IInf, apply_type_tfunc, 10) end function invoke_tfunc(@nospecialize(f), @nospecialize(types), @nospecialize(argtype), sv::InferenceState) - if !isleaftype(Type{types}) + if !isconcrete(Type{types}) return Any end argtype = typeintersect(types,limit_tuple_type(argtype, sv.params)) @@ -1461,7 +1461,7 @@ function tuple_tfunc(@nospecialize(argtype)) for x in argtype.parameters if isType(x) && !isa(x.parameters[1], TypeVar) xparam = x.parameters[1] - if isleaftype(xparam) || xparam === Bottom + if isconcrete(xparam) || xparam === Bottom push!(p, typeof(xparam)) else push!(p, Type) @@ -1938,7 +1938,7 @@ end # do apply(af, fargs...), where af is a function value function abstract_apply(@nospecialize(aft), fargs::Vector{Any}, aargtypes::Vector{Any}, vtypes::VarTable, sv::InferenceState) if !isa(aft, Const) && !isconstType(aft) - if !(isleaftype(aft) || aft <: Type) || (aft <: Builtin) || (aft <: IntrinsicFunction) + if !(isconcrete(aft) || aft <: Type) || (aft <: Builtin) || (aft <: IntrinsicFunction) return Any end # non-constant function, but type is known @@ -1994,7 +1994,7 @@ function return_type_tfunc(@nospecialize(argtypes), vtypes::VarTable, sv::Infere if isa(tt, Const) || (isType(tt) && !has_free_typevars(tt)) aft = argtypes[2] if isa(aft, Const) || (isType(aft) && !has_free_typevars(aft)) || - (isleaftype(aft) && !(aft <: Builtin)) + (isconcrete(aft) && !(aft <: Builtin)) af_argtype = isa(tt, Const) ? tt.val : tt.parameters[1] if isa(af_argtype, DataType) && af_argtype <: Tuple argtypes_vec = Any[aft, af_argtype.parameters...] @@ -2009,7 +2009,7 @@ function return_type_tfunc(@nospecialize(argtypes), vtypes::VarTable, sv::Infere if isa(rt, Const) # output was computed to be constant return Const(typeof(rt.val)) - elseif isleaftype(rt) || rt === Bottom + elseif isconcrete(rt) || rt === Bottom # output type was known for certain return Const(rt) elseif (isa(tt, Const) || isconstType(tt)) && @@ -2309,9 +2309,9 @@ function abstract_eval_call(e::Expr, vtypes::VarTable, sv::InferenceState) if isa(ft, Const) f = ft.val else - if isType(ft) && isleaftype(ft.parameters[1]) + if isType(ft) && isconcrete(ft.parameters[1]) f = ft.parameters[1] - elseif isleaftype(ft) && isdefined(ft, :instance) + elseif isconcrete(ft) && isdefined(ft, :instance) f = ft.instance else for i = 2:(length(argtypes)-1) @@ -2320,7 +2320,7 @@ function abstract_eval_call(e::Expr, vtypes::VarTable, sv::InferenceState) end end # non-constant function, but type is known - if (isleaftype(ft) || ft <: Type) && !(ft <: Builtin) && !(ft <: IntrinsicFunction) + if (isconcrete(ft) || ft <: Type) && !(ft <: Builtin) && !(ft <: IntrinsicFunction) return abstract_call_gf_by_type(nothing, argtypes_to_type(argtypes), sv) end return Any @@ -2838,7 +2838,7 @@ function code_for_method(method::Method, @nospecialize(atypes), sparams::SimpleV if world < min_world(method) return nothing end - if isdefined(method, :generator) && !isleaftype(atypes) + if isdefined(method, :generator) && !isconcrete(atypes) # don't call staged functions on abstract types. # (see issues #8504, #10230) # we can't guarantee that their type behavior is monotonic. @@ -3852,7 +3852,7 @@ function effect_free(@nospecialize(e), src::CodeInfo, mod::Module, allow_volatil elseif is_known_call(e, getfield, src, mod) length(ea) == 3 || return false et = exprtype(e, src, mod) - if !isa(et,Const) && !(isType(et) && isleaftype(et)) + if !isa(et,Const) && !(isType(et) && isconcrete(et)) # first argument must be immutable to ensure e is affect_free a = ea[2] typ = widenconst(exprtype(a, src, mod)) @@ -4110,7 +4110,7 @@ end # inline functions whose bodies are "inline_worthy" # where the function body doesn't contain any argument more than once. -# static parameters are ok if all the static parameter values are leaf types, +# static parameters are ok if all the static parameter values are concrete types, # meaning they are fully known. # `ft` is the type of the function. `f` is the exact function if known, or else `nothing`. # `pending_stmts` is an array of statements from functions inlined so far, so @@ -4122,7 +4122,7 @@ function inlineable(@nospecialize(f), @nospecialize(ft), e::Expr, atypes::Vector if (f === typeassert || ft ⊑ typeof(typeassert)) && length(atypes)==3 # typeassert(x::S, T) => x, when S<:T a3 = atypes[3] - if (isType(a3) && isleaftype(a3) && atypes[2] ⊑ a3.parameters[1]) || + if (isType(a3) && isconcrete(a3) && atypes[2] ⊑ a3.parameters[1]) || (isa(a3,Const) && isa(a3.val,Type) && atypes[2] ⊑ a3.val) return (argexprs[2], ()) end @@ -4152,7 +4152,7 @@ function inlineable(@nospecialize(f), @nospecialize(ft), e::Expr, atypes::Vector if f === Core.invoke && length(atypes) >= 3 ft = widenconst(atypes[2]) invoke_tt = widenconst(atypes[3]) - if !isleaftype(ft) || !isleaftype(invoke_tt) || !isType(invoke_tt) + if !isconcrete(ft) || !isconcrete(invoke_tt) || !isType(invoke_tt) return NF end if !(isa(invoke_tt.parameters[1], Type) && @@ -4647,7 +4647,7 @@ end # saturating sum (inputs are nonnegative), prevents overflow with typemax(Int) below plus_saturate(x, y) = max(x, y, x+y) # known return type -isknowntype(T) = (T == Union{}) || isleaftype(T) +isknowntype(T) = (T == Union{}) || isconcrete(T) statement_cost(::Any, src::CodeInfo, mod::Module, params::InferenceParams) = 0 statement_cost(qn::QuoteNode, src::CodeInfo, mod::Module, params::InferenceParams) = @@ -4675,7 +4675,7 @@ function statement_cost(ex::Expr, src::CodeInfo, mod::Module, params::InferenceP iidx = Int(reinterpret(Int32, f::IntrinsicFunction)) + 1 if !isassigned(t_ifunc_cost, iidx) # unknown/unhandled intrinsic - return plus_saturate(argcost, params.inline_nonleaf_penalty) + return plus_saturate(argcost, params.inline_nonconcrete_penalty) end return plus_saturate(argcost, t_ifunc_cost[iidx]) end @@ -4687,10 +4687,10 @@ function statement_cost(ex::Expr, src::CodeInfo, mod::Module, params::InferenceP # we might like to penalize non-inferrability, but # tuple iteration/destructuring makes that # impossible - # return plus_saturate(argcost, isknowntype(ex.typ) ? 1 : params.inline_nonleaf_penalty) + # return plus_saturate(argcost, isknowntype(ex.typ) ? 1 : params.inline_nonconcrete_penalty) return argcost elseif f == Main.Core.arrayref - return plus_saturate(argcost, isknowntype(ex.typ) ? 4 : params.inline_nonleaf_penalty) + return plus_saturate(argcost, isknowntype(ex.typ) ? 4 : params.inline_nonconcrete_penalty) end fidx = findfirst(t_ffunc_key, f) if fidx == 0 @@ -4701,7 +4701,7 @@ function statement_cost(ex::Expr, src::CodeInfo, mod::Module, params::InferenceP return plus_saturate(argcost, t_ffunc_cost[fidx]) end end - return plus_saturate(argcost, params.inline_nonleaf_penalty) + return plus_saturate(argcost, params.inline_nonconcrete_penalty) elseif head == :foreigncall || head == :invoke # Calls whose "return type" is Union{} do not actually return: # they are errors. Since these are not part of the typical @@ -4904,7 +4904,7 @@ function inlining_pass(e::Expr, sv::InferenceState, stmts, ins) ft = Bool else f = nothing - if !( isleaftype(ft) || ft<:Type ) + if !( isconcrete(ft) || ft<:Type ) return e end end @@ -5040,7 +5040,7 @@ function inlining_pass(e::Expr, sv::InferenceState, stmts, ins) ft = Bool else f = nothing - if !( isleaftype(ft) || ft<:Type ) + if !( isconcrete(ft) || ft<:Type ) return e end end @@ -5685,7 +5685,7 @@ function is_allocation(@nospecialize(e), sv::InferenceState) return (length(e.args)-1,()) elseif e.head === :new typ = widenconst(exprtype(e, sv.src, sv.mod)) - if isa(typ, DataType) && isleaftype(typ) + if isa(typ, DataType) && isconcrete(typ) nf = length(e.args) - 1 names = fieldnames(typ) @assert(nf <= length(names)) diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl index 4ad8d2795ad6f..a7ef16dba368d 100644 --- a/base/interactiveutil.jl +++ b/base/interactiveutil.jl @@ -341,8 +341,8 @@ end Prints lowered and type-inferred ASTs for the methods matching the given generic function and type signature to `io` which defaults to `STDOUT`. The ASTs are annotated in such a way -as to cause "non-leaf" types to be emphasized (if color is available, displayed in red). -This serves as a warning of potential type instability. Not all non-leaf types are particularly +as to cause non-concrete types to be emphasized (if color is available, displayed in red). +This serves as a warning of potential type instability. Not all non-concrete types are particularly problematic for performance, so the results need to be used judiciously. See [`@code_warntype`](@ref man-code-warntype) for more information. """ @@ -531,7 +531,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) || + !isconcrete(t) && x <: t) || (isa(x,Union) && isa(t,DataType) && (type_close_enough(x.a, t) || type_close_enough(x.b, t))) end diff --git a/base/iterators.jl b/base/iterators.jl index a37960744bc4b..90cb3da5084d9 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -735,16 +735,16 @@ 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{<:Tuple}) = isconcrete(b) ? HasLength() : SizeUnknown() flatten_iteratorsize(::Union{HasShape, HasLength}, b::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) + if !isconcrete(T) throw(ArgumentError( - "Cannot compute length of a tuple-type which is not a leaf-type")) + "Cannot compute length of a tuple-type which is not concrete")) end fieldcount(T)*length(f.it) end diff --git a/base/methodshow.jl b/base/methodshow.jl index 095cb2f56b72f..d273dcb38eee8 100644 --- a/base/methodshow.jl +++ b/base/methodshow.jl @@ -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 && isconcrete(ft) f = ft.parameters[1] if isa(f, DataType) && isempty(f.parameters) print(io, f) @@ -234,7 +234,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 && isconcrete(ft) f = ft.parameters[1] if isa(f, DataType) && isempty(f.parameters) print(io, f) diff --git a/base/nullable.jl b/base/nullable.jl index 8d7d6f685825a..493c9eb98d1f2 100644 --- a/base/nullable.jl +++ b/base/nullable.jl @@ -323,7 +323,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} = isconcrete(T) ? T : Union{} """ map(f, x::Nullable) @@ -349,7 +349,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 isconcrete(S) && null_safe_op(f, T) Nullable(f(unsafe_get(x)), !isnull(x)) else if isnull(x) diff --git a/base/promotion.jl b/base/promotion.jl index 10c8b2a34170e..bf01d51d16c1d 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -319,13 +319,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 + isconcrete(S) && return isconcrete(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 + isconcrete(R) && isconcrete(S) && return isconcrete(T) ? T : Any return typejoin(R, S, T) end diff --git a/base/reflection.jl b/base/reflection.jl index 2d79fe19617d4..fd18f94d8b188 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -283,27 +283,27 @@ isbits(t::Type) = (@_pure_meta; false) isbits(x) = (@_pure_meta; isbits(typeof(x))) """ - 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. # 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 ``` """ -isleaftype(@nospecialize(t)) = (@_pure_meta; isa(t, DataType) && t.isleaftype) +isconcrete(@nospecialize(t)) = (@_pure_meta; isa(t, DataType) && t.isconcrete) """ Base.isabstract(T) @@ -767,8 +767,8 @@ function _dump_function_linfo(linfo::Core.MethodInstance, world::UInt, native::B (Ptr{Void}, Bool, Bool), llvmf, strip_ir_metadata, dump_module) 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) + # TODO: use jl_is_cacheable_sig instead of isconcrete + isconcrete(linfo.specTypes) || (str = "; WARNING: This code may not match what actually runs.\n" * str) return str end @@ -797,9 +797,9 @@ code_native(io::IO, @nospecialize(f), @nospecialize(types=Tuple), syntax::Symbol code_native(@nospecialize(f), @nospecialize(types=Tuple), syntax::Symbol=:att) = code_native(STDOUT, f, types, syntax) code_native(::IO, ::Any, ::Symbol) = error("illegal code_native call") # resolve ambiguous call -# give a decent error message if we try to instantiate a staged function on non-leaf types +# give a decent error message if we try to instantiate a staged function on non-concrete 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) && !isconcrete(types) error("cannot call @generated function `", m, "` ", "with abstract argument types: ", types) end @@ -861,7 +861,7 @@ function which(@nospecialize(f), @nospecialize(t)) throw(ArgumentError("argument is not a generic function")) end t = to_tuple_type(t) - if isleaftype(t) + if isconcrete(t) ms = methods(f, t) isempty(ms) && error("no method found for the specified argument types") length(ms)!=1 && error("no unique matching method for the specified argument types") diff --git a/base/refpointer.jl b/base/refpointer.jl index 44a625c76b6cf..d8fef59fd3227 100644 --- a/base/refpointer.jl +++ b/base/refpointer.jl @@ -55,10 +55,10 @@ 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) return convert(P, pointer_from_objref(b)) - elseif isleaftype(T) + elseif isconcrete(T) return convert(P, pointer_from_objref(b.x)) else - # If the slot is not leaf type, it could be either isbits or not. + # If the slot is not a concrete type, it could be either isbits or not. # If it is actually an isbits type and the type inference can infer that # it can rebox the `b.x` if we simply call `pointer_from_objref(b.x)` on it. # Instead, explicitly load the pointer from the `RefValue` so that the pointer diff --git a/base/replutil.jl b/base/replutil.jl index 5e4c9e7611aa4..d760c7d0a5634 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -465,7 +465,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 && isconcrete(at1) push!(funcs, (at1.parameters[1], arg_types_param[2:end])) end end diff --git a/base/set.jl b/base/set.jl index c0d18af570d61..b077f83fe07dc 100644 --- a/base/set.jl +++ b/base/set.jl @@ -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) + (isconcrete(T) || T === Union{}) || return grow_to!(Set{T}(), g) return Set{T}(g) end @@ -209,7 +209,7 @@ function unique(itr) return out end x, i = next(itr, i) - if !isleaftype(T) + if !isconcrete(T) S = typeof(x) return _unique_from(itr, S[x], Set{S}((x,)), i) end diff --git a/base/show.jl b/base/show.jl index a492846511bf0..234b5e9b0dea3 100644 --- a/base/show.jl +++ b/base/show.jl @@ -537,7 +537,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 && (!isconcrete(ty) || ty == Core.Box) emphasize(io, "::$ty") else print(io, "::$ty") @@ -1090,7 +1090,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 && isconcrete(ft) f = ft.parameters[1] print(io, f) else @@ -1813,7 +1813,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), (!isempty(X) && (e===Float64 || e===Int || e===Char) ? "" : str) + isconcrete(e), (!isempty(X) && (e===Float64 || e===Int || e===Char) ? "" : str) end function show_vector(io::IO, v, opn, cls) diff --git a/doc/images/jltypes.svg b/doc/images/jltypes.svg index dc7de531a649a..6e5f4bef22009 100644 --- a/doc/images/jltypes.svg +++ b/doc/images/jltypes.svg @@ -281,7 +281,7 @@ valid as type tags - - has uid assigned - not an abstract type - none of the direct type parametersare a TypeVar - no type parameter is a bound TypeVar*, recursively tested - if this is a Tuple type, then there is an additional restriction that all type parameters are leaf types + - has uid assigned - not an abstract type - none of the direct type parametersare a TypeVar - no type parameter is a bound TypeVar*, recursively tested - if this is a Tuple type, then there is an additional restriction that all type parameters are concrete types @@ -333,7 +333,7 @@ - is leaf type + is concrete type diff --git a/doc/src/devdocs/inference.md b/doc/src/devdocs/inference.md index 1cc4b29dab667..7be19a0757894 100644 --- a/doc/src/devdocs/inference.md +++ b/doc/src/devdocs/inference.md @@ -84,7 +84,7 @@ input and output types were inferred in advance) is assigned a fixed cost (currently 20 cycles). In contrast, a `:call` expression, for functions other than intrinsics/builtins, indicates that the call will require dynamic dispatch, in which case we assign a cost set by -`InferenceParams.inline_nonleaf_penalty` (currently set at 1000). Note +`InferenceParams.inline_nonconcrete_penalty` (currently set at 1000). Note that this is not a "first-principles" estimate of the raw cost of dynamic dispatch, but a mere heuristic indicating that dynamic dispatch is extremely expensive. diff --git a/doc/src/devdocs/object.md b/doc/src/devdocs/object.md index bfb096fbf980c..222e6cfc94d2c 100644 --- a/doc/src/devdocs/object.md +++ b/doc/src/devdocs/object.md @@ -20,7 +20,7 @@ typedef struct { } jl_typetag_t; ``` -The type of any Julia object is an instance of a leaf `jl_datatype_t` object. The `jl_typeof()` +The type of any Julia object is an instance of a concrete `jl_datatype_t` object. The `jl_typeof()` function can be used to query for it: ```c diff --git a/doc/src/devdocs/types.md b/doc/src/devdocs/types.md index 3008a5990611e..24116c44da303 100644 --- a/doc/src/devdocs/types.md +++ b/doc/src/devdocs/types.md @@ -441,8 +441,8 @@ For example, in the problem `Tuple{Int,String} <: Tuple{T,T} where T`, we derive this would be true if `T` were a supertype of `Union{Int,String}`. However, `Union{Int,String}` is an abstract type, so the relation does not hold. -This concreteness test is done by the function `is_leaf_bound`. -Note that this test is slightly different from `jl_is_leaf_type`, since it also returns +This concreteness test is done by the function `is_concrete_bound`. +Note that this test is slightly different from `jl_is_concrete_type`, since it also returns `true` for `Bottom`. Currently this function is heuristic, and does not catch all possible concrete types. The difficulty is that whether a lower bound is concrete might depend on the values diff --git a/doc/src/manual/calling-c-and-fortran-code.md b/doc/src/manual/calling-c-and-fortran-code.md index 6c0070dedfed7..0a139d3af3209 100644 --- a/doc/src/manual/calling-c-and-fortran-code.md +++ b/doc/src/manual/calling-c-and-fortran-code.md @@ -269,14 +269,14 @@ First, a review of some relevant Julia type terminology: | Syntax / Keyword | Example | Description | |:----------------------------- |:------------------------------------------- |:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `mutable struct` | `String` | "Leaf Type" :: A group of related data that includes a type-tag, is managed by the Julia GC, and is defined by object-identity. The type parameters of a leaf type must be fully defined (no `TypeVars` are allowed) in order for the instance to be constructed. | -| `abstract type` | `Any`, `AbstractArray{T, N}`, `Complex{T}` | "Super Type" :: A super-type (not a leaf-type) that cannot be instantiated, but can be used to describe a group of types. | +| `mutable struct` | `String` | "Concrete Type" :: A group of related data that includes a type-tag, is managed by the Julia GC, and is defined by object-identity. The type parameters of a concrete type must be fully defined (no `TypeVars` are allowed) in order for the instance to be constructed. | +| `abstract type` | `Any`, `AbstractArray{T, N}`, `Complex{T}` | "Super Type" :: A super-type (not a concrete type) that cannot be instantiated, but can be used to describe a group of types. | | `T{A}` | `Vector{Int}` | "Type Parameter" :: A specialization of a type (typically used for dispatch or storage optimization). | | | | "TypeVar" :: The `T` in the type parameter declaration is referred to as a TypeVar (short for type variable). | | `primitive type` | `Int`, `Float64` | "Primitive Type" :: A type with no fields, but a size. It is stored and defined by-value. | | `struct` | `Pair{Int, Int}` | "Struct" :: A type with all fields defined to be constant. It is defined by-value, and may be stored with a type-tag. | | | `Complex128` (`isbits`) | "Is-Bits" :: A `primitive type`, or a `struct` type where all fields are other `isbits` types. It is defined by-value, and is stored without a type-tag. | -| `struct ...; end` | `nothing` | "Singleton" :: a Leaf Type or Struct with no fields. | +| `struct ...; end` | `nothing` | "Singleton" :: a Concrete Type or Struct with no fields. | | `(...)` or `tuple(...)` | `(1, 2, 3)` | "Tuple" :: an immutable data-structure similar to an anonymous struct type, or a constant array. Represented as either an array or a struct. | ### Bits Types: @@ -579,7 +579,7 @@ For translating a C argument list to Julia: * argument value will be copied (passed by value) * `struct T` (including typedef to a struct) - * `T`, where `T` is a Julia leaf type + * `T`, where `T` is a Julia concrete type * argument value will be copied (passed by value) * `void*` diff --git a/doc/src/manual/performance-tips.md b/doc/src/manual/performance-tips.md index b26a874215db6..f0f5fcb356327 100644 --- a/doc/src/manual/performance-tips.md +++ b/doc/src/manual/performance-tips.md @@ -1449,7 +1449,7 @@ is difficult or impossible: for example, currently it's not possible to infer th of an anonymous function. In such cases, the tips above (e.g., adding type annotations and/or breaking up functions) are your best tools to contain the "damage" from type instability. -The following examples may help you interpret expressions marked as containing non-leaf types: +The following examples may help you interpret expressions marked as containing non-concrete types: * Function body ending in `end::Union{T1,T2})` @@ -1466,7 +1466,7 @@ The following examples may help you interpret expressions marked as containing n element accesses * `(top(getfield))(A::ArrayContainer{Float64},:data)::Array{Float64,N}` - * Interpretation: getting a field that is of non-leaf type. In this case, `ArrayContainer` had a + * Interpretation: getting a field that is of non-concrete type. In this case, `ArrayContainer` had a field `data::Array{T}`. But `Array` needs the dimension `N`, too, to be a concrete type. * Suggestion: use concrete types like `Array{T,3}` or `Array{T,N}`, where `N` is now a parameter of `ArrayContainer` diff --git a/doc/src/stdlib/base.md b/doc/src/stdlib/base.md index 63e39784a2990..fa72079d535a5 100644 --- a/doc/src/stdlib/base.md +++ b/doc/src/stdlib/base.md @@ -107,7 +107,7 @@ Base.fieldoffset Core.fieldtype Base.isimmutable Base.isbits -Base.isleaftype +Base.isconcrete Base.typejoin Base.typeintersect Base.Val diff --git a/src/array.c b/src/array.c index 3e77a0e9cbc30..11510d2d0b5ec 100644 --- a/src/array.c +++ b/src/array.c @@ -24,7 +24,7 @@ extern "C" { static inline int store_unboxed(jl_value_t *el_type) // jl_isbits { - return jl_is_leaf_type(el_type) && jl_is_immutable(el_type) && + return jl_is_concrete_type(el_type) && jl_is_immutable(el_type) && ((jl_datatype_t*)el_type)->layout && ((jl_datatype_t*)el_type)->layout->npointers == 0; } diff --git a/src/ccall.cpp b/src/ccall.cpp index 818989cefc24e..f0b6f0fe6fc8d 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -558,7 +558,7 @@ static Value *julia_to_address( // yes copy Value *nbytes; AllocaInst *ai; - if (jl_is_leaf_type(ety) || jl_is_primitivetype(ety)) { + if (jl_is_concrete_type(ety) || jl_is_primitivetype(ety)) { int nb = jl_datatype_size(ety); nbytes = ConstantInt::get(T_int32, nb); ai = emit_static_alloca(ctx, T_int8, nb); @@ -1146,8 +1146,8 @@ static jl_cgval_t mark_or_box_ccall_result(jl_codectx_t &ctx, Value *result, boo if (!static_rt) { assert(!isboxed && ctx.spvals_ptr && unionall && jl_is_datatype(rt)); Value *runtime_dt = runtime_apply_type(ctx, rt, unionall); - // TODO: is this leaf check actually necessary, or is it structurally guaranteed? - emit_leafcheck(ctx, runtime_dt, "ccall: return type must be a leaf DataType"); + // TODO: is this concrete check actually necessary, or is it structurally guaranteed? + emit_concrete_check(ctx, runtime_dt, "ccall: return type must be a concrete DataType"); #if JL_LLVM_VERSION >= 40000 const DataLayout &DL = jl_data_layout; #else @@ -1421,11 +1421,11 @@ static const std::string verify_ccall_sig(size_t nccallargs, jl_value_t *&rt, jl } if (!retboxed && static_rt) { - if (!jl_is_leaf_type(rt)) { + if (!jl_is_concrete_type(rt)) { if (jl_is_cpointer_type(rt)) return "ccall: return type Ptr should have an element type (not Ptr{_<:T})"; else if (rt != jl_bottom_type) - return "ccall: return type must be a leaf DataType"; + return "ccall: return type must be a concrete DataType"; } } @@ -1752,17 +1752,17 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) ctx.builder.SetInsertPoint(contBB); return ghostValue(jl_void_type); } - else if (is_libjulia_func(jl_is_leaf_type)) { + else if (is_libjulia_func(jl_is_concrete_type)) { assert(!isVa && !llvmcall && nargt == 1 && !addressOf.at(0)); const jl_cgval_t &arg = argv[0]; jl_value_t *ty = arg.constant; if (!ty && jl_is_type_type(arg.typ) && !jl_has_free_typevars(arg.typ)) ty = jl_tparam0(arg.typ); if (ty) { - int isleaf = jl_is_leaf_type(ty); + int isconcrete = jl_is_concrete_type(ty); JL_GC_POP(); return mark_or_box_ccall_result(ctx, - ConstantInt::get(T_int32, isleaf), + ConstantInt::get(T_int32, isconcrete), false, rt, unionall, static_rt); } } @@ -1894,7 +1894,7 @@ jl_cgval_t function_sig_t::emit_a_ccall( jl_cgval_t &arg = argv[ai]; // if we know the function sparams, try to fill those in now - // so that the julia_to_native type checks are more likely to be doable (e.g. leaf types) at compile-time + // so that the julia_to_native type checks are more likely to be doable (e.g. concrete types) at compile-time jl_value_t *jargty_in_env = jargty; if (ctx.spvals_ptr == NULL && !toboxed && unionall_env && jl_has_typevar_from_unionall(jargty, unionall_env) && jl_svec_len(ctx.linfo->sparam_vals) > 0) { diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 430a33b105e22..8ac88316a72c0 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -407,7 +407,7 @@ JL_DLLEXPORT Type *julia_type_to_llvm(jl_value_t *jt, bool *isboxed) if (isboxed) *isboxed = false; if (jt == (jl_value_t*)jl_bottom_type) return T_void; - if (jl_is_leaf_type(jt)) { + if (jl_is_concrete_type(jt)) { if ((jl_is_primitivetype(jt) || jl_isbits(jt))) { if (jl_datatype_nbits(jt) == 0) return T_void; @@ -443,7 +443,7 @@ static Type *bitstype_to_llvm(jl_value_t *bt) return Type::getIntNTy(jl_LLVMContext, nb * 8); } -// compute whether all leaf subtypes of this type have the same layout +// compute whether all concrete subtypes of this type have the same layout // (which is conservatively approximated here by asking whether the types of any of the // fields depend on any of the parameters of the containing type) static bool julia_struct_has_layout(jl_datatype_t *dt, jl_unionall_t *ua) @@ -500,7 +500,7 @@ static Type *julia_struct_to_llvm(jl_value_t *jt, jl_unionall_t *ua, bool *isbox if (jst->layout) isptr = jl_field_isptr(jst, i); else // compute what jl_compute_field_offsets would say - isptr = jl_isbits(ty) && jl_is_leaf_type(ty) && ((jl_datatype_t*)ty)->layout; + isptr = jl_isbits(ty) && jl_is_concrete_type(ty) && ((jl_datatype_t*)ty)->layout; Type *lty; if (isptr) lty = T_pjlvalue; @@ -580,9 +580,9 @@ static bool is_tupletype_homogeneous(jl_svec_t *t, bool allow_va = false) size_t i, l = jl_svec_len(t); if (l > 0) { jl_value_t *t0 = jl_svecref(t, 0); - if (!jl_is_leaf_type(t0)) { + if (!jl_is_concrete_type(t0)) { if (allow_va && jl_is_vararg_type(t0) && - jl_is_leaf_type(jl_unwrap_vararg(t0))) + jl_is_concrete_type(jl_unwrap_vararg(t0))) return true; return false; } @@ -700,7 +700,7 @@ static Value *emit_typeof(jl_codectx_t &ctx, Value *tt) // given p, a jl_value_t*, compute its type tag // The raw address is not GC-safe to load from as it may have mask bits set. // Note that this gives the optimizer license to not root this value. That - // is fine however, since leaf types are not GCed at the moment. Should + // is fine however, since concrete types are not GCed at the moment. Should // that ever change, this may have to go through a special intrinsic. Value *addr = emit_bitcast(ctx, emit_typeptr_addr(ctx, tt), T_ppjlvalue); tt = tbaa_decorate(tbaa_tag, ctx.builder.CreateLoad(addr)); @@ -712,7 +712,7 @@ static jl_cgval_t emit_typeof(jl_codectx_t &ctx, const jl_cgval_t &p) // given p, compute its type if (p.constant) return mark_julia_const(jl_typeof(p.constant)); - if (p.isboxed && !jl_is_leaf_type(p.typ)) { + if (p.isboxed && !jl_is_concrete_type(p.typ)) { return mark_julia_type(ctx, emit_typeof(ctx, p.V), true, jl_datatype_type, /*needsroot*/false); } if (p.TIndex) { @@ -822,7 +822,7 @@ static Value *emit_sizeof(jl_codectx_t &ctx, const jl_cgval_t &p) #endif return size; } - else if (jl_is_leaf_type(p.typ)) { + else if (jl_is_concrete_type(p.typ)) { return ConstantInt::get(T_int32, jl_datatype_size(p.typ)); } else { @@ -945,7 +945,7 @@ static size_t dereferenceable_size(jl_value_t *jt) { } static inline void maybe_mark_argument_dereferenceable(Argument *A, jl_value_t *jt) { - if (!jl_is_leaf_type(jt)) { + if (!jl_is_concrete_type(jt)) { return; } size_t size = dereferenceable_size(jt); @@ -968,7 +968,7 @@ static inline Instruction *maybe_mark_load_dereferenceable(Instruction *LI, bool } static inline Instruction *maybe_mark_load_dereferenceable(Instruction *LI, bool can_be_null, jl_value_t *jt) { - if (!jl_is_leaf_type(jt)) { + if (!jl_is_concrete_type(jt)) { return LI; } size_t size = dereferenceable_size(jt); @@ -1022,8 +1022,8 @@ static std::pair emit_isa(jl_codectx_t &ctx, const jl_cgval_t &x, ctx.builder.CreateCall(prepare_call(jlisa_func), { vx, vtyp }), ConstantInt::get(T_int32, 0)), false); } - // tests for isa leaftype can be handled with pointer comparisons - if (jl_is_leaf_type(type)) { + // tests for is a concrete type can be handled with pointer comparisons + if (jl_is_concrete_type(type)) { if (x.TIndex) { unsigned tindex = get_box_tindex((jl_datatype_t*)type, x.typ); if (tindex > 0) { @@ -1080,15 +1080,15 @@ static void emit_typecheck(jl_codectx_t &ctx, const jl_cgval_t &x, jl_value_t *t } } -static void emit_leafcheck(jl_codectx_t &ctx, Value *typ, const std::string &msg) +static void emit_concrete_check(jl_codectx_t &ctx, Value *typ, const std::string &msg) { assert(typ->getType() == T_prjlvalue); emit_typecheck(ctx, mark_julia_type(ctx, typ, true, jl_any_type, false), (jl_value_t*)jl_datatype_type, msg); - Value *isleaf; - isleaf = ctx.builder.CreateConstInBoundsGEP1_32(T_int8, emit_bitcast(ctx, decay_derived(typ), T_pint8), offsetof(jl_datatype_t, isleaftype)); - isleaf = ctx.builder.CreateLoad(isleaf, tbaa_const); - isleaf = ctx.builder.CreateTrunc(isleaf, T_int1); - error_unless(ctx, isleaf, msg); + Value *isconcrete; + isconcrete = ctx.builder.CreateConstInBoundsGEP1_32(T_int8, emit_bitcast(ctx, decay_derived(typ), T_pint8), offsetof(jl_datatype_t, isconcrete)); + isconcrete = ctx.builder.CreateLoad(isconcrete, tbaa_const); + isconcrete = ctx.builder.CreateTrunc(isconcrete, T_int1); + error_unless(ctx, isconcrete, msg); } #define CHECK_BOUNDS 1 @@ -1432,7 +1432,7 @@ static Value *emit_n_varargs(jl_codectx_t &ctx) static bool arraytype_constshape(jl_value_t *ty) { - return (jl_is_array_type(ty) && jl_is_leaf_type(ty) && + return (jl_is_array_type(ty) && jl_is_concrete_type(ty) && jl_is_long(jl_tparam1(ty)) && jl_unbox_long(jl_tparam1(ty)) != 1); } @@ -1979,7 +1979,7 @@ static Value *boxed(jl_codectx_t &ctx, const jl_cgval_t &vinfo, bool gcrooted) } else { assert(vinfo.V && "Missing data for unboxed value."); - assert(jl_isbits(jt) && jl_is_leaf_type(jt) && "This type shouldn't have been unboxed."); + assert(jl_isbits(jt) && jl_is_concrete_type(jt) && "This type shouldn't have been unboxed."); Type *t = julia_type_to_llvm(jt); assert(!type_is_ghost(t)); // ghost values should have been handled by vinfo.constant above! box = _boxed_special(ctx, vinfo, t); @@ -2002,7 +2002,7 @@ static void emit_unionmove(jl_codectx_t &ctx, Value *dest, const jl_cgval_t &src { if (AllocaInst *ai = dyn_cast(dest)) ctx.builder.CreateStore(UndefValue::get(ai->getAllocatedType()), ai); - if (jl_is_leaf_type(src.typ) || src.constant) { + if (jl_is_concrete_type(src.typ) || src.constant) { jl_value_t *typ = src.constant ? jl_typeof(src.constant) : src.typ; Type *store_ty = julia_type_to_llvm(typ); assert(skip || jl_isbits(typ)); @@ -2180,7 +2180,7 @@ static void emit_setfield(jl_codectx_t &ctx, static jl_cgval_t emit_new_struct(jl_codectx_t &ctx, jl_value_t *ty, size_t nargs, const jl_cgval_t *argv) { assert(jl_is_datatype(ty)); - assert(jl_is_leaf_type(ty)); + assert(jl_is_concrete_type(ty)); assert(nargs > 0); jl_datatype_t *sty = (jl_datatype_t*)ty; size_t nf = jl_datatype_nfields(sty); diff --git a/src/codegen.cpp b/src/codegen.cpp index 245b1a3f9c6be..65a2f4a56ccf2 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -373,7 +373,7 @@ extern "C" { static bool isbits_spec(jl_value_t *jt, bool allow_singleton = true) { - return jl_isbits(jt) && jl_is_leaf_type(jt) && + return jl_isbits(jt) && jl_is_concrete_type(jt) && (allow_singleton || (jl_datatype_size(jt) > 0) || (jl_datatype_nfields(jt) > 0)); } @@ -451,7 +451,7 @@ struct jl_cgval_t { // this constructor expects we had a badly or equivalently typed version // make sure we aren't discarding the actual type information if (v.TIndex) { - assert((TIndex == NULL) == jl_is_leaf_type(typ)); + assert((TIndex == NULL) == jl_is_concrete_type(typ)); } else { assert(isboxed || v.typ == typ || tindex); @@ -620,7 +620,7 @@ static inline jl_cgval_t ghostValue(jl_value_t *typ) typ = (jl_value_t*)jl_wrap_Type(jl_bottom_type); } if (jl_is_type_type(typ)) { - // replace T::Type{T} with T, by assuming that T must be a leaftype of some sort + // replace T::Type{T} with T, by assuming that T must be a concrete type of some sort jl_cgval_t constant(NULL, NULL, true, typ, NULL); constant.constant = jl_tparam0(typ); return constant; @@ -668,7 +668,7 @@ static inline jl_cgval_t mark_julia_type(jl_codectx_t &ctx, Value *v, bool isbox } if (jl_is_type_type(typ)) { jl_value_t *tp0 = jl_tparam0(typ); - if (jl_is_leaf_type(tp0) || tp0 == jl_bottom_type) { + if (jl_is_concrete_type(tp0) || tp0 == jl_bottom_type) { // replace T::Type{T} with T return ghostValue(typ); } @@ -708,16 +708,16 @@ static inline jl_cgval_t update_julia_type(jl_codectx_t &ctx, const jl_cgval_t & { if (v.typ == typ || v.typ == jl_bottom_type || v.constant || typ == (jl_value_t*)jl_any_type || jl_egal(v.typ, typ)) return v; // fast-path - if (jl_is_leaf_type(v.typ) && !jl_is_kind(v.typ)) { - if (jl_is_leaf_type(typ) && !jl_is_kind(typ) && !((jl_datatype_t*)typ)->abstract && !((jl_datatype_t*)v.typ)->abstract) { - // type mismatch: changing from one leaftype to another + if (jl_is_concrete_type(v.typ) && !jl_is_kind(v.typ)) { + if (jl_is_concrete_type(typ) && !jl_is_kind(typ) && !((jl_datatype_t*)typ)->abstract && !((jl_datatype_t*)v.typ)->abstract) { + // type mismatch: changing from one concrete type to another CreateTrap(ctx.builder); return jl_cgval_t(); } return v; // doesn't improve type info } if (v.TIndex) { - if (!jl_is_leaf_type(typ)) + if (!jl_is_concrete_type(typ)) return v; // not worth trying to improve type info if (!isbits_spec(typ)) { // discovered that this union-split type must actually be isboxed @@ -827,7 +827,7 @@ static jl_cgval_t convert_julia_type(jl_codectx_t &ctx, const jl_cgval_t &v, jl_ if (type_is_ghost(T)) return ghostValue(typ); Value *new_tindex = NULL; - if (jl_is_leaf_type(typ)) { + if (jl_is_concrete_type(typ)) { if (v.TIndex && !isbits_spec(typ)) { // discovered that this union-split type must actually be isboxed if (v.V) { @@ -839,9 +839,9 @@ static jl_cgval_t convert_julia_type(jl_codectx_t &ctx, const jl_cgval_t &v, jl_ return jl_cgval_t(); } } - if (jl_is_leaf_type(v.typ) && !jl_is_kind(v.typ) && !((jl_datatype_t*)v.typ)->abstract) { - if (jl_is_leaf_type(typ) && !jl_is_kind(typ) && !((jl_datatype_t*)typ)->abstract) { - // type mismatch: changing from one leaftype to another + if (jl_is_concrete_type(v.typ) && !jl_is_kind(v.typ) && !((jl_datatype_t*)v.typ)->abstract) { + if (jl_is_concrete_type(typ) && !jl_is_kind(typ) && !((jl_datatype_t*)typ)->abstract) { + // type mismatch: changing from one concrete type to another CreateTrap(ctx.builder); return jl_cgval_t(); } @@ -876,7 +876,7 @@ static jl_cgval_t convert_julia_type(jl_codectx_t &ctx, const jl_cgval_t &v, jl_ } else { // will actually need to box this element - // since it appeared as a leaftype in the original type + // since it appeared as a concrete type in the original type // but not in the remark type t = false; } @@ -991,8 +991,8 @@ static jl_cgval_t convert_julia_type(jl_codectx_t &ctx, const jl_cgval_t &v, jl_ } } else if (!v.isboxed && jl_is_uniontype(typ)) { - // previous value was unboxed (leaftype), statically compute union tindex - assert(jl_is_leaf_type(v.typ)); + // previous value was unboxed (concrete type), statically compute union tindex + assert(jl_is_concrete_type(v.typ)); unsigned new_idx = get_box_tindex((jl_datatype_t*)v.typ, typ); if (new_idx) { new_tindex = ConstantInt::get(T_int8, new_idx); @@ -2003,7 +2003,7 @@ static Value *emit_local_root(jl_codectx_t &ctx, jl_varinfo_t *vi) static void jl_add_method_root(jl_codectx_t &ctx, jl_value_t *val) { - if (jl_is_leaf_type(val) || jl_is_bool(val) || jl_is_symbol(val) || + if (jl_is_concrete_type(val) || jl_is_bool(val) || jl_is_symbol(val) || val == (jl_value_t*)jl_any_type || val == (jl_value_t*)jl_bottom_type) return; JL_GC_PUSH1(&val); @@ -2047,7 +2047,7 @@ static jl_cgval_t emit_getfield(jl_codectx_t &ctx, const jl_cgval_t &strct, jl_s return emit_globalref(ctx, (jl_module_t*)strct.constant, name); jl_datatype_t *sty = (jl_datatype_t*)strct.typ; - if (jl_is_type_type((jl_value_t*)sty) && jl_is_leaf_type(jl_tparam0(sty))) + if (jl_is_type_type((jl_value_t*)sty) && jl_is_concrete_type(jl_tparam0(sty))) sty = (jl_datatype_t*)jl_typeof(jl_tparam0(sty)); sty = (jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)sty); if (jl_is_structtype(sty) && sty != jl_module_type && sty->layout) { @@ -2065,7 +2065,7 @@ static jl_cgval_t emit_getfield(jl_codectx_t &ctx, const jl_cgval_t &strct, jl_s mark_julia_const((jl_value_t*)name) }; Value *result = emit_jlcall(ctx, jlgetfield_func, maybe_decay_untracked(V_null), myargs_array, 2); - bool needsgcroot = true; // !arg1.isimmutable || !jl_is_leaf_type(arg1.typ) || !is_datatype_all_pointers((jl_datatype_t*)arg1.typ); // TODO: probably want this as a llvm pass + bool needsgcroot = true; // !arg1.isimmutable || !jl_is_concrete_type(arg1.typ) || !is_datatype_all_pointers((jl_datatype_t*)arg1.typ); // TODO: probably want this as a llvm pass return mark_julia_type(ctx, result, true, jl_any_type, needsgcroot); } @@ -2146,8 +2146,8 @@ static Value *emit_f_is(jl_codectx_t &ctx, const jl_cgval_t &arg1, const jl_cgva // need to use typeseq for datatypes istypes = true; } - if (!istypes && jl_is_leaf_type(rt1) && jl_is_leaf_type(rt2) && rt1 != rt2) - // disjoint concrete leaf types are never equal (quick test) + if (!istypes && jl_is_concrete_type(rt1) && jl_is_concrete_type(rt2) && rt1 != rt2) + // disjoint concrete types are never equal (quick test) return ConstantInt::get(T_int1, 0); if (arg1.isghost || arg2.isghost) { @@ -2197,8 +2197,8 @@ static Value *emit_f_is(jl_codectx_t &ctx, const jl_cgval_t &arg1, const jl_cgva ptr_comparable = 1; if (istypes) // need to use typeseq for datatypes ptr_comparable = 0; - if ((jl_is_type_type(rt1) && jl_is_leaf_type(jl_tparam0(rt1))) || - (jl_is_type_type(rt2) && jl_is_leaf_type(jl_tparam0(rt2)))) // can compare leaf types by pointer + if ((jl_is_type_type(rt1) && jl_is_concrete_type(jl_tparam0(rt1))) || + (jl_is_type_type(rt2) && jl_is_concrete_type(jl_tparam0(rt2)))) // can compare concrete types by pointer ptr_comparable = 1; if ((rt1 == (jl_value_t*)jl_string_type && rt2 == (jl_value_t*)jl_string_type) || (rt1 == (jl_value_t*)jl_simplevector_type && rt2 == (jl_value_t*)jl_simplevector_type)) @@ -2311,7 +2311,7 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, *ret = ghostValue(jl_emptytuple_type); return true; } - if (jl_is_tuple_type(rt) && jl_is_leaf_type(rt) && nargs == jl_datatype_nfields(rt)) { + if (jl_is_tuple_type(rt) && jl_is_concrete_type(rt) && nargs == jl_datatype_nfields(rt)) { *ret = emit_new_struct(ctx, rt, nargs + 1, argv); return true; } @@ -2531,7 +2531,7 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, if (jl_is_tuple_type(utt) && is_tupletype_homogeneous(utt->types, true)) { // For tuples, we can emit code even if we don't know the exact // type (e.g. because we don't know the length). This is possible - // as long as we know that all elements are of the same (leaf) type. + // as long as we know that all elements are of the same (concrete) type. if (obj.ispointer()) { // Determine which was the type that was homogenous jl_value_t *jt = jl_tparam0(utt); @@ -2596,12 +2596,12 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, } if (jl_is_type_type(obj.typ)) { jl_value_t *tp0 = jl_tparam0(obj.typ); - if (jl_is_leaf_type(tp0)) { + if (jl_is_concrete_type(tp0)) { *ret = mark_julia_type(ctx, ConstantInt::get(T_size, jl_datatype_nfields(tp0)), false, jl_long_type); return true; } } - else if (jl_is_leaf_type(obj.typ) || obj.constant) { + else if (jl_is_concrete_type(obj.typ) || obj.constant) { Value *sz; if (obj.constant) { if (jl_typeof(obj.constant) == (jl_value_t*)jl_datatype_type) @@ -2624,7 +2624,7 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, else if (f == jl_builtin_fieldtype && nargs == 2) { const jl_cgval_t &typ = argv[1]; const jl_cgval_t &fld = argv[2]; - if ((jl_is_type_type(typ.typ) && jl_is_leaf_type(jl_tparam0(typ.typ))) || + if ((jl_is_type_type(typ.typ) && jl_is_concrete_type(jl_tparam0(typ.typ))) || (typ.constant && jl_is_datatype(typ.constant)) || typ.typ == (jl_value_t*)jl_datatype_type) { if (fld.typ == (jl_value_t*)jl_long_type) { @@ -2685,7 +2685,7 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, // exclude DataType, since each DataType has its own size, not sizeof(DataType). // this is issue #8798 sty != jl_datatype_type) { - if (jl_is_leaf_type((jl_value_t*)sty) || + if (jl_is_concrete_type((jl_value_t*)sty) || (jl_field_names(sty) == jl_emptysvec && jl_datatype_size(sty) > 0)) { *ret = mark_julia_type(ctx, ConstantInt::get(T_size, jl_datatype_size(sty)), false, jl_long_type); return true; @@ -2709,8 +2709,8 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, const jl_cgval_t &obj = argv[1]; const jl_cgval_t &fld = argv[2]; jl_datatype_t *stt = (jl_datatype_t*)obj.typ; - if (!jl_is_leaf_type((jl_value_t*)stt) || jl_is_array_type(stt) || - stt == jl_module_type) { // TODO: use ->layout here instead of leaf_type + if (!jl_is_concrete_type((jl_value_t*)stt) || jl_is_array_type(stt) || + stt == jl_module_type) { // TODO: use ->layout here instead of concrete_type return false; } assert(jl_is_datatype(stt)); @@ -3512,7 +3512,7 @@ static void emit_assignment(jl_codectx_t &ctx, jl_value_t *l, jl_value_t *r) if (tbaa != tbaa_stack) tbaa = NULL; if (vi.pTIndex == NULL) { - assert(jl_is_leaf_type(vi.value.typ)); + assert(jl_is_concrete_type(vi.value.typ)); Value *copy_bytes = ConstantInt::get(T_int32, jl_datatype_size(vi.value.typ)); ctx.builder.CreateMemCpy(vi.value.V, data_pointer(ctx, rval_info, T_pint8), @@ -3785,7 +3785,7 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr) jl_value_t *ty = argv[0].typ; if (jl_is_type_type(ty) && jl_is_datatype(jl_tparam0(ty)) && - jl_is_leaf_type(jl_tparam0(ty))) { + jl_is_concrete_type(jl_tparam0(ty))) { assert(nargs <= jl_datatype_nfields(jl_tparam0(ty)) + 1); return emit_new_struct(ctx, jl_tparam0(ty), nargs, argv); } @@ -4369,7 +4369,7 @@ static Function *jl_cfunction_object(jl_function_t *ff, jl_value_t *declrt, jl_t jl_error("cfunction: return type Ref should have an element type, not Ref{T}"); if (declrt == (jl_value_t*)jl_any_type) jl_error("cfunction: return type Ref{Any} is invalid. Use Any or Ptr{Any} instead."); - if (!jl_is_leaf_type(declrt)) + if (!jl_is_concrete_type(declrt)) jl_svecset(cfunc_sig, nargs + 1, declrt); // Ref{Abstract} is the same calling convention as Abstract crt = (jl_value_t*)jl_any_type; } @@ -4386,7 +4386,7 @@ static Function *jl_cfunction_object(jl_function_t *ff, jl_value_t *declrt, jl_t ati = jl_tparam0(ati); if (jl_is_typevar(ati)) jl_error("cfunction: argument type Ref should have an element type, not Ref{T}"); - if (ati != (jl_value_t*)jl_any_type && !jl_is_leaf_type(ati)) + if (ati != (jl_value_t*)jl_any_type && !jl_is_concrete_type(ati)) jl_svecset(cfunc_sig, i + 1, ati); // Ref{Abstract} is the same calling convention as Abstract } if (jl_is_pointer(ati) && jl_is_typevar(jl_tparam0(ati))) @@ -5586,7 +5586,7 @@ static std::unique_ptr emit_function( if (sret) { if (retvalinfo.ispointer()) { if (returninfo.cc == jl_returninfo_t::SRet) { - assert(jl_is_leaf_type(jlrettype)); + assert(jl_is_concrete_type(jlrettype)); Value *copy_bytes = ConstantInt::get(T_int32, jl_datatype_size(jlrettype)); ctx.builder.CreateMemCpy(sret, data_pointer(ctx, retvalinfo, T_pint8), diff --git a/src/common_symbols2.inc b/src/common_symbols2.inc index 4554dfef79b5b..805d6b95f34df 100644 --- a/src/common_symbols2.inc +++ b/src/common_symbols2.inc @@ -160,7 +160,7 @@ jl_symbol("min"), jl_symbol("last"), jl_symbol("_length"), jl_symbol(">="), -jl_symbol("isleaftype"), +jl_symbol("isconcrete"), jl_symbol("UInt32"), jl_symbol("Generator"), jl_symbol("TypeVar"), diff --git a/src/datatype.c b/src/datatype.c index e97a26ad53bf1..1322578844f4b 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -79,7 +79,7 @@ jl_datatype_t *jl_new_uninitialized_datatype(void) jl_datatype_t *t = (jl_datatype_t*)jl_gc_alloc(ptls, sizeof(jl_datatype_t), jl_datatype_type); t->depth = 0; t->hasfreetypevars = 0; - t->isleaftype = 1; + t->isconcrete = 1; t->layout = NULL; return t; } @@ -271,7 +271,7 @@ void jl_compute_field_offsets(jl_datatype_t *st) } return; } - if (!jl_is_leaf_type((jl_value_t*)st)) { + if (!jl_is_concrete_type((jl_value_t*)st)) { // compute layout whenever field types have no free variables for (size_t i = 0; i < nfields; i++) { if (jl_has_free_typevars(jl_field_type(st, i))) @@ -294,7 +294,7 @@ void jl_compute_field_offsets(jl_datatype_t *st) for (size_t i = 0; i < nfields; i++) { jl_value_t *ty = jl_field_type(st, i); size_t fsz, al; - if (jl_isbits(ty) && jl_is_leaf_type(ty) && ((jl_datatype_t*)ty)->layout) { + if (jl_isbits(ty) && jl_is_concrete_type(ty) && ((jl_datatype_t*)ty)->layout) { fsz = jl_datatype_size(ty); // Should never happen if (__unlikely(fsz > max_size)) @@ -777,7 +777,7 @@ JL_DLLEXPORT size_t jl_get_field_offset(jl_datatype_t *ty, int field) JL_DLLEXPORT size_t jl_get_alignment(jl_datatype_t *ty) { if (ty->layout == NULL) - jl_error("non-leaf type doesn't have an alignment"); + jl_error("non-concrete type doesn't have an alignment"); return jl_datatype_align(ty); } diff --git a/src/dump.c b/src/dump.c index 4383079e2f20e..9dae4d8762625 100644 --- a/src/dump.c +++ b/src/dump.c @@ -327,7 +327,7 @@ static void jl_serialize_datatype(jl_serializer_state *s, jl_datatype_t *dt) int has_instance = (dt->instance != NULL); int has_layout = (dt->layout != NULL); write_uint8(s->s, dt->abstract | (dt->mutabl<<1) | (has_layout<<2) | (has_instance<<3) | - (dt->hasfreetypevars<<4) | (dt->isleaftype<<5)); + (dt->hasfreetypevars<<4) | (dt->isconcrete<<5)); write_int32(s->s, dt->depth); if (!dt->abstract) { write_uint16(s->s, dt->ninitialized); @@ -1136,7 +1136,7 @@ static jl_value_t *jl_deserialize_datatype(jl_serializer_state *s, int pos, jl_v int has_layout = (flags>>2)&1; int has_instance = (flags>>3)&1; dt->hasfreetypevars = (flags>>4)&1; - dt->isleaftype = (flags>>5)&1; + dt->isconcrete = (flags>>5)&1; dt->depth = depth; dt->types = NULL; dt->parameters = NULL; diff --git a/src/gf.c b/src/gf.c index 3cdbb33b4c18b..03252c1822276 100644 --- a/src/gf.c +++ b/src/gf.c @@ -537,13 +537,13 @@ static jl_tupletype_t *join_tsig(jl_tupletype_t *tt, jl_tupletype_t *sig) // if the declared type was not Any or Union{Type, ...}, // then the match must been with UnionAll or DataType // and the result of matching the type signature - // needs to be corrected to the leaf type 'kind' + // needs to be corrected to the concrete type 'kind' jl_value_t *kind = jl_typeof(jl_tparam0(elt)); if (jl_subtype(kind, decl_i)) { if (!jl_subtype((jl_value_t*)jl_type_type, decl_i)) { // UnionAlls are problematic because they can be alternate // representations of any type. If we matched this method because - // it matched the leaf type UnionAll, then don't cache something + // it matched the concrete type UnionAll, then don't cache something // different since that doesn't necessarily actually apply. // // similarly, if we matched Type{T<:Any}::DataType, @@ -725,7 +725,7 @@ JL_DLLEXPORT int jl_is_cacheable_sig( // if the declared type was not Any or Union{Type, ...}, // then the match must been with TypeConstructor or DataType // and the result of matching the type signature - // needs to be corrected to the leaf type 'kind' + // needs to be corrected to the concrete type 'kind' jl_value_t *kind = jl_typeof(jl_tparam0(elt)); if (kind != (jl_value_t*)jl_tvar_type && jl_subtype(kind, decl_i)) { if (!jl_subtype((jl_value_t*)jl_type_type, decl_i)) @@ -814,7 +814,7 @@ JL_DLLEXPORT int jl_is_cacheable_sig( return 0; continue; } - else if (!jl_is_leaf_type(elt)) { + else if (!jl_is_concrete_type(elt)) { return 0; } } @@ -868,7 +868,7 @@ static jl_method_instance_t *cache_method(jl_methtable_t *mt, union jl_typemap_t // then specialize as (Any...) // // note: this also protects the work join_tsig did to correct `types` for the - // leaftype signatures TypeConstructor and DataType + // concrete type signatures TypeConstructor and DataType // (assuming those made an unlikely appearance in Varargs position) size_t j = i; int all_are_subtypes = 1; @@ -1507,7 +1507,7 @@ jl_tupletype_t *arg_type_tuple(jl_value_t **args, size_t nargs) else types[i] = jl_typeof(ai); } - // if `ai` has free type vars this will not be a leaf type. + // if `ai` has free type vars this will not be a concrete type. // TODO: it would be really nice to only dispatch and cache those as // `jl_typeof(ai)`, but that will require some redesign of the caching // logic. @@ -1549,7 +1549,7 @@ jl_method_instance_t *jl_method_lookup_by_type(jl_methtable_t *mt, jl_tupletype_ JL_UNLOCK(&mt->writelock); return linfo; } - if (jl_is_leaf_type((jl_value_t*)types)) + if (jl_is_concrete_type((jl_value_t*)types)) cache = 1; jl_method_instance_t *sf = jl_mt_assoc_by_type(mt, types, cache, inexact, allow_exec, world); if (cache) { @@ -1675,7 +1675,7 @@ jl_llvm_functions_t jl_compile_for_dispatch(jl_method_instance_t **pli, size_t w jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types, size_t world) { JL_TIMING(METHOD_LOOKUP_COMPILE); - if (!jl_is_leaf_type((jl_value_t*)types) || jl_has_free_typevars((jl_value_t*)types)) + if (!jl_is_concrete_type((jl_value_t*)types) || jl_has_free_typevars((jl_value_t*)types)) return NULL; jl_value_t *args = jl_unwrap_unionall((jl_value_t*)types); @@ -1837,7 +1837,7 @@ STATIC_INLINE jl_method_instance_t *jl_lookup_generic_(jl_value_t **args, uint32 /* search order: - check associative hash based on callsite address for leafsig match + check associative hash based on callsite address for concrete sig match look at concrete signatures if there is an exact match, return it otherwise look for a matching generic signature @@ -1872,8 +1872,8 @@ STATIC_INLINE jl_method_instance_t *jl_lookup_generic_(jl_value_t **args, uint32 jl_value_t *F = args[0]; mt = jl_gf_mtable(F); entry = jl_typemap_assoc_exact(mt->cache, args, nargs, jl_cachearg_offset(mt), world); - if (entry && entry->isleafsig && entry->simplesig == (void*)jl_nothing && entry->guardsigs == jl_emptysvec) { - // put the entry into the cache if it's valid for a leaftype lookup, + if (entry && entry->isconcretesig && entry->simplesig == (void*)jl_nothing && entry->guardsigs == jl_emptysvec) { + // put the entry into the cache if it's valid for a concrete type lookup, // using pick_which to slightly randomize where it ends up call_cache[cache_idx[++pick_which[cache_idx[0]] & 3]] = entry; } @@ -2043,7 +2043,7 @@ JL_DLLEXPORT jl_value_t *jl_get_invoke_lambda(jl_methtable_t *mt, jl_tupletype_t *tt, size_t world) { - if (!jl_is_leaf_type((jl_value_t*)tt) || tupletype_has_datatype(tt, NULL)) + if (!jl_is_concrete_type((jl_value_t*)tt) || tupletype_has_datatype(tt, NULL)) return jl_nothing; jl_method_t *method = entry->func.method; @@ -2252,9 +2252,9 @@ static int ml_matches_visitor(jl_typemap_entry_t *ml, struct typemap_intersectio // the "limited" mode used by type inference. for (i = 0; i < len; i++) { jl_value_t *prior_ti = jl_svecref(jl_array_ptr_ref(closure->t, i), 0); - // TODO: should be possible to remove the `jl_is_leaf_type` check, + // TODO: should be possible to remove the `jl_is_concrete_type` check, // but we still need it in case an intersection was approximate. - if (jl_is_leaf_type(prior_ti) && jl_subtype(closure->match.ti, prior_ti)) { + if (jl_is_concrete_type(prior_ti) && jl_subtype(closure->match.ti, prior_ti)) { skip = 1; break; } @@ -2273,7 +2273,7 @@ static int ml_matches_visitor(jl_typemap_entry_t *ml, struct typemap_intersectio // if the queried type is a subtype, but not all tvars matched, then // this method is excluded by the static-parameters-must-have-values rule if (!matched_all_tvars((jl_value_t*)ml->sig, jl_svec_data(env), jl_svec_len(env))) - return_this_match = !jl_is_leaf_type(closure->match.type); + return_this_match = !jl_is_concrete_type(closure->match.type); else done = 1; // stop; signature fully covers queried type } diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index 5b7397ddc80d0..b35186138eac4 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -452,7 +452,7 @@ static jl_cgval_t generic_bitcast(jl_codectx_t &ctx, const jl_cgval_t *argv) vx = emit_bitcast(ctx, vx, llvmt); } - if (jl_is_leaf_type(bt)) { + if (jl_is_concrete_type(bt)) { return mark_julia_type(ctx, vx, false, bt); } else { @@ -583,7 +583,7 @@ static jl_cgval_t emit_pointerref(jl_codectx_t &ctx, jl_cgval_t *argv) true, ety); } - if (!jl_is_structtype(ety) || jl_is_array_type(ety) || !jl_is_leaf_type(ety)) { + if (!jl_is_structtype(ety) || jl_is_array_type(ety) || !jl_is_concrete_type(ety)) { emit_error(ctx, "pointerref: invalid pointer type"); return jl_cgval_t(); } @@ -642,7 +642,7 @@ static jl_cgval_t emit_pointerset(jl_codectx_t &ctx, jl_cgval_t *argv) Value *thePtr; if (!jl_isbits(ety) && ety != (jl_value_t*)jl_any_type) { - if (!jl_is_structtype(ety) || jl_is_array_type(ety) || !jl_is_leaf_type(ety)) { + if (!jl_is_structtype(ety) || jl_is_array_type(ety) || !jl_is_concrete_type(ety)) { emit_error(ctx, "pointerset: invalid pointer type"); return jl_cgval_t(); } diff --git a/src/jltypes.c b/src/jltypes.c index d50ad990ae9d8..4b043f8da6bd6 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -267,18 +267,18 @@ JL_DLLEXPORT int jl_has_typevar_from_unionall(jl_value_t *t, jl_unionall_t *ua) } -JL_DLLEXPORT int (jl_is_leaf_type)(jl_value_t *v) +JL_DLLEXPORT int (jl_is_concrete_type)(jl_value_t *v) { if (jl_is_datatype(v)) { - int isleaf = ((jl_datatype_t*)v)->isleaftype; + int isconcrete = ((jl_datatype_t*)v)->isconcrete; #ifdef NDEBUG - return isleaf; + return isconcrete; #else if (((jl_datatype_t*)v)->abstract) { int x = 0; if (jl_is_type_type(v)) x = !jl_has_free_typevars(jl_tparam0(v)); - assert(x == isleaf); + assert(x == isconcrete); return x; } jl_svec_t *t = ((jl_datatype_t*)v)->parameters; @@ -286,8 +286,8 @@ JL_DLLEXPORT int (jl_is_leaf_type)(jl_value_t *v) if (((jl_datatype_t*)v)->name == jl_tuple_typename) { for(int i=0; i < l; i++) { jl_value_t *p = jl_svecref(t,i); - if (!jl_is_leaf_type(p) && p != jl_bottom_type) { - assert(!isleaf); + if (!jl_is_concrete_type(p) && p != jl_bottom_type) { + assert(!isconcrete); return 0; } } @@ -295,12 +295,12 @@ JL_DLLEXPORT int (jl_is_leaf_type)(jl_value_t *v) else { for(int i=0; i < l; i++) { if (jl_has_free_typevars(jl_svecref(t, i))) { - assert(!isleaf); + assert(!isconcrete); return 0; } } } - assert(isleaf); + assert(isconcrete); return 1; #endif } @@ -767,7 +767,7 @@ static int is_cacheable(jl_datatype_t *type) if (jl_is_abstracttype(type)) return !jl_has_free_typevars((jl_value_t*)type); // ... or concrete types - return jl_is_leaf_type((jl_value_t*)type); + return jl_is_concrete_type((jl_value_t*)type); } static void cache_insert_type(jl_value_t *type, ssize_t insert_at, int ordered) @@ -1019,7 +1019,7 @@ void jl_precompute_memoized_dt(jl_datatype_t *dt) { int istuple = dt->name == jl_tuple_typename; size_t i, l = jl_nparams(dt); - dt->isleaftype = !dt->abstract || (jl_type_type != NULL && dt->name == jl_type_typename); + dt->isconcrete = !dt->abstract || (jl_type_type != NULL && dt->name == jl_type_typename); for (i = 0; i < l; i++) { jl_value_t *p = jl_tparam(dt, i); size_t d = jl_type_depth(p) + 1; @@ -1027,8 +1027,8 @@ void jl_precompute_memoized_dt(jl_datatype_t *dt) dt->depth = d; if (!dt->hasfreetypevars) dt->hasfreetypevars = jl_has_free_typevars(p); - if (dt->isleaftype) - dt->isleaftype = (istuple ? (jl_is_leaf_type(p) || p == jl_bottom_type) : + if (dt->isconcrete) + dt->isconcrete = (istuple ? (jl_is_concrete_type(p) || p == jl_bottom_type) : !dt->hasfreetypevars); } } @@ -1121,7 +1121,7 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value jl_value_t *pi = iparams[i]; if (pi == jl_bottom_type) continue; - if (jl_is_leaf_type(pi)) { + if (jl_is_concrete_type(pi)) { assert(jl_is_datatype(pi)); if (!((jl_datatype_t*)pi)->abstract) continue; @@ -1317,7 +1317,7 @@ static jl_tupletype_t *jl_apply_tuple_type_v_(jl_value_t **p, size_t np, jl_svec { int cacheable = 1; for(size_t i=0; i < np; i++) { - if (!jl_is_leaf_type(p[i])) + if (!jl_is_concrete_type(p[i])) cacheable = 0; } jl_datatype_t *ndt = (jl_datatype_t*)inst_datatype(jl_anytuple_type, params, p, np, @@ -1406,7 +1406,7 @@ static jl_value_t *inst_tuple_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_ iparams[i] = pi; if (ip_heap) jl_gc_wb(ip_heap, pi); - if (cacheable && !jl_is_leaf_type(pi)) + if (cacheable && !jl_is_concrete_type(pi)) cacheable = 0; } jl_value_t *result = inst_datatype((jl_datatype_t*)tt, ip_heap, iparams, ntp, cacheable, stack); @@ -1683,7 +1683,7 @@ void jl_init_types(void) "llvm::DIType", "depth", "hasfreetypevars", - "isleaftype"); + "isconcrete"); jl_datatype_type->types = jl_svec(16, jl_typename_type, jl_datatype_type, @@ -1816,7 +1816,7 @@ void jl_init_types(void) jl_anytuple_type->layout = NULL; jl_anytuple_type->instance = NULL; jl_anytuple_type->hasfreetypevars = 0; - jl_anytuple_type->isleaftype = 0; + jl_anytuple_type->isconcrete = 0; jl_tvar_t *tttvar = tvar("T"); ((jl_datatype_t*)jl_type_type)->parameters = jl_svec(1, tttvar); @@ -1896,7 +1896,7 @@ void jl_init_types(void) "min_world", "max_world", "func", - "isleafsig", + "isconcretesig", "issimplesig", "va"), jl_svec(10, diff --git a/src/julia.h b/src/julia.h index c1225481aa0ca..7112c5b3e17cf 100644 --- a/src/julia.h +++ b/src/julia.h @@ -181,7 +181,7 @@ struct _jl_method_instance_t; // typedef TypeMap Union{TypeMapLevel, TypeMapEntry, Void} // it forms a roughly tree-shaped structure, consisting of nodes of TypeMapLevels // which split the tree when possible, for example based on the key into the tuple type at `offs` -// when key is a leaftype, (but only when the tree has enough entries for this to be +// when key is a concrete type (but only when the tree has enough entries for this to be // more efficient than storing them sorted linearly) // otherwise the leaf entries are stored sorted, linearly union jl_typemap_t { @@ -385,7 +385,7 @@ typedef struct _jl_datatype_t { void *ditype; // llvm::MDNode* to be used as llvm::DIType(ditype) int32_t depth; int8_t hasfreetypevars; - int8_t isleaftype; + int8_t isconcrete; } jl_datatype_t; typedef struct { @@ -432,8 +432,8 @@ typedef struct _jl_typemap_entry_t { jl_method_t *method; } func; // memoized properties of sig: - int8_t isleafsig; // isleaftype(sig) & !any(isType, sig) : unsorted and very fast - int8_t issimplesig; // all(isleaftype | isAny | isType | isVararg, sig) : sorted and fast + int8_t isconcretesig; // isconcrete(sig) & !any(isType, sig) : unsorted and very fast + int8_t issimplesig; // all(isconcrete | isAny | isType | isVararg, sig) : sorted and fast int8_t va; // isVararg(sig) } jl_typemap_entry_t; @@ -981,7 +981,7 @@ JL_DLLEXPORT int jl_egal(jl_value_t *a, jl_value_t *b); JL_DLLEXPORT uintptr_t jl_object_id(jl_value_t *v); // type predicates and basic operations -JL_DLLEXPORT int jl_is_leaf_type(jl_value_t *v); +JL_DLLEXPORT int jl_is_concrete_type(jl_value_t *v); JL_DLLEXPORT int jl_has_free_typevars(jl_value_t *v); JL_DLLEXPORT int jl_has_typevar(jl_value_t *t, jl_tvar_t *v); JL_DLLEXPORT int jl_has_typevar_from_unionall(jl_value_t *t, jl_unionall_t *ua); @@ -1000,11 +1000,11 @@ jl_value_t *jl_unwrap_unionall(jl_value_t *v); jl_value_t *jl_rewrap_unionall(jl_value_t *t, jl_value_t *u); #if defined(NDEBUG) && defined(JL_NDEBUG) -STATIC_INLINE int jl_is_leaf_type_(jl_value_t *v) +STATIC_INLINE int jl_is_concrete_type_(jl_value_t *v) { - return jl_is_datatype(v) && ((jl_datatype_t*)v)->isleaftype; + return jl_is_datatype(v) && ((jl_datatype_t*)v)->isconcrete; } -#define jl_is_leaf_type(v) jl_is_leaf_type_(v) +#define jl_is_concrete_type(v) jl_is_concrete_type_(v) #endif // type constructors diff --git a/src/method.c b/src/method.c index db2d44e8369fc..55600c3474246 100644 --- a/src/method.c +++ b/src/method.c @@ -703,7 +703,7 @@ JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, if (ftype == NULL || !(jl_is_type_type((jl_value_t*)ftype) || (jl_is_datatype(ftype) && - (!ftype->abstract || jl_is_leaf_type((jl_value_t*)ftype)) && + (!ftype->abstract || jl_is_concrete_type((jl_value_t*)ftype)) && ftype->name->mt != NULL))) jl_error("cannot add methods to an abstract type"); mt = ftype->name->mt; diff --git a/src/precompile.c b/src/precompile.c index 9843b3bedbdbe..56b900b69b442 100644 --- a/src/precompile.c +++ b/src/precompile.c @@ -115,9 +115,9 @@ static int any_bottom_field(jl_value_t *typ) // and expanding the Union may give a leaf function static void _compile_all_tvar_union(jl_value_t *methsig) { - if (!jl_is_unionall(methsig) && jl_is_leaf_type(methsig)) { + if (!jl_is_unionall(methsig) && jl_is_concrete_type(methsig)) { // usually can create a specialized version of the function, - // if the signature is already a leaftype + // if the signature is already a concrete type if (jl_compile_hint((jl_tupletype_t*)methsig)) return; } @@ -148,7 +148,7 @@ static void _compile_all_tvar_union(jl_value_t *methsig) } if (any_bottom_field(sig)) goto getnext; // signature wouldn't be callable / is invalid -- skip it - if (jl_is_leaf_type(sig)) { + if (jl_is_concrete_type(sig)) { if (jl_compile_hint((jl_tupletype_t*)sig)) goto getnext; // success } @@ -165,7 +165,7 @@ static void _compile_all_tvar_union(jl_value_t *methsig) } else { jl_value_t *ty = jl_nth_union_component(tv->ub, j); - if (!jl_is_leaf_type(ty)) + if (!jl_is_concrete_type(ty)) ty = (jl_value_t*)jl_new_typevar(tv->name, tv->lb, ty); env[2 * i + 1] = ty; idx[i] = j + 1; @@ -196,8 +196,8 @@ static void _compile_all_union(jl_value_t *sig) ++count_unions; else if (ty == jl_bottom_type) return; // why does this method exist? - else if (!jl_is_leaf_type(ty) && !jl_has_free_typevars(ty)) - return; // no amount of union splitting will make this a leaftype signature + else if (!jl_is_concrete_type(ty) && !jl_has_free_typevars(ty)) + return; // no amount of union splitting will make this a concrete type signature } if (count_unions == 0 || count_unions >= 6) { @@ -276,7 +276,7 @@ static void _compile_all_deq(jl_array_t *found) //if (linfo->jlcall_api == 2) // continue; - // first try to create leaf signatures from the signature declaration and compile those + // first try to create concrete signatures from the signature declaration and compile those _compile_all_union((jl_value_t*)ml->sig); // then also compile the generic fallback jl_compile_linfo(&linfo, (jl_code_info_t*)src, jl_world_counter, &jl_default_cgparams); diff --git a/src/runtime_intrinsics.c b/src/runtime_intrinsics.c index a768b9dec3501..d4a68fbf5dcac 100644 --- a/src/runtime_intrinsics.c +++ b/src/runtime_intrinsics.c @@ -18,8 +18,8 @@ const unsigned int host_char_bit = 8; JL_DLLEXPORT jl_value_t *jl_bitcast(jl_value_t *ty, jl_value_t *v) { JL_TYPECHK(bitcast, datatype, ty); - if (!jl_is_leaf_type(ty) || !jl_is_primitivetype(ty)) - jl_error("bitcast: target type not a leaf primitive type"); + if (!jl_is_concrete_type(ty) || !jl_is_primitivetype(ty)) + jl_error("bitcast: target type not a concrete primitive type"); if (!jl_is_primitivetype(jl_typeof(v))) jl_error("bitcast: value not a primitive type"); if (jl_datatype_size(jl_typeof(v)) != jl_datatype_size(ty)) @@ -83,8 +83,8 @@ JL_DLLEXPORT jl_value_t *jl_cglobal(jl_value_t *v, jl_value_t *ty) v == (jl_value_t*)jl_void_type ? (jl_value_t*)jl_voidpointer_type : // a common case (jl_value_t*)jl_apply_type1((jl_value_t*)jl_pointer_type, ty); - if (!jl_is_leaf_type(rt)) - jl_error("cglobal: type argument not a leaftype"); + if (!jl_is_concrete_type(rt)) + jl_error("cglobal: type argument not a concrete type"); if (jl_is_tuple(v) && jl_nfields(v) == 1) v = jl_fieldref(v, 0); diff --git a/src/subtype.c b/src/subtype.c index a379b374c64c3..9865864114dc7 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -206,9 +206,9 @@ static int obviously_unequal(jl_value_t *a, jl_value_t *b) { if (a == b) return 0; - if (jl_is_leaf_type(a) && !((jl_datatype_t*)a)->abstract) + if (jl_is_concrete_type(a) && !((jl_datatype_t*)a)->abstract) return 1; - if (jl_is_leaf_type(b) && !((jl_datatype_t*)b)->abstract) + if (jl_is_concrete_type(b) && !((jl_datatype_t*)b)->abstract) return 1; if (jl_is_unionall(a)) a = jl_unwrap_unionall(a); if (jl_is_unionall(b)) b = jl_unwrap_unionall(b); @@ -250,8 +250,8 @@ static int obviously_disjoint(jl_value_t *a, jl_value_t *b, int specificity) { if (a == b || a == (jl_value_t*)jl_any_type || b == (jl_value_t*)jl_any_type) return 0; - if (jl_is_leaf_type(a) && !((jl_datatype_t*)a)->abstract && - jl_is_leaf_type(b) && !((jl_datatype_t*)b)->abstract && + if (jl_is_concrete_type(a) && !((jl_datatype_t*)a)->abstract && + jl_is_concrete_type(b) && !((jl_datatype_t*)b)->abstract && // TODO: remove these 2 lines if and when Tuple{Union{}} === Union{} (((jl_datatype_t*)a)->name != jl_tuple_typename || ((jl_datatype_t*)b)->name != jl_tuple_typename)) @@ -502,11 +502,11 @@ static int var_gt(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int param) // check that a type is concrete. this is used to check concrete typevars; // issubtype is false if the lower bound of a concrete type var is not concrete. -static int is_leaf_bound(jl_value_t *v) +static int is_concrete_bound(jl_value_t *v) { if (v == jl_bottom_type) return 1; if (jl_is_datatype(v)) { - if (((jl_datatype_t*)v)->isleaftype) return 1; + if (((jl_datatype_t*)v)->isconcrete) return 1; if (((jl_datatype_t*)v)->abstract) { if (jl_is_type_type(v)) return 1;//!jl_has_free_typevars(jl_tparam0(v)); @@ -516,7 +516,7 @@ static int is_leaf_bound(jl_value_t *v) size_t l = jl_svec_len(t); if (((jl_datatype_t*)v)->name == jl_tuple_typename) { for(int i=0; i < l; i++) { - if (!is_leaf_bound(jl_svecref(t,i))) + if (!is_concrete_bound(jl_svecref(t,i))) return 0; } } @@ -525,11 +525,11 @@ static int is_leaf_bound(jl_value_t *v) return !jl_is_type(v) && !jl_is_typevar(v); } -static int is_leaf_typevar(jl_value_t *v) +static int is_concrete_typevar(jl_value_t *v) { if (jl_is_typevar(v)) - return is_leaf_typevar(((jl_tvar_t*)v)->lb); - return is_leaf_bound(v); + return is_concrete_typevar(((jl_tvar_t*)v)->lb); + return is_concrete_bound(v); } static jl_value_t *widen_Type(jl_value_t *t) @@ -576,7 +576,7 @@ static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8 if (e->envidx < e->envsz) { jl_value_t *val; if (!vb.occurs_inv && vb.lb != jl_bottom_type) - val = is_leaf_bound(vb.lb) ? vb.lb : (jl_value_t*)jl_new_typevar(u->var->name, jl_bottom_type, vb.lb); + val = is_concrete_bound(vb.lb) ? vb.lb : (jl_value_t*)jl_new_typevar(u->var->name, jl_bottom_type, vb.lb); else if (vb.lb == vb.ub) val = vb.lb; else if (vb.lb != jl_bottom_type) @@ -605,7 +605,7 @@ static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8 // !( Tuple{Int, String} <: Tuple{T, T} where T) // Then check concreteness by checking that the lower bound is not an abstract type. if (ans && (vb.concrete || (!vb.occurs_inv && vb.occurs_cov > 1)) && - is_leaf_typevar((jl_value_t*)u->var)) { + is_concrete_typevar((jl_value_t*)u->var)) { if (jl_is_typevar(vb.lb)) { // TODO test case that demonstrates the need for this? /* @@ -617,7 +617,7 @@ static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8 ans = (v == vb.concretevar); */ } - else if (!is_leaf_bound(vb.lb)) { + else if (!is_concrete_bound(vb.lb)) { ans = 0; } if (ans) { @@ -754,7 +754,7 @@ static int subtype_tuple(jl_datatype_t *xd, jl_datatype_t *yd, jl_stenv_t *e, in } if (xi == lastx && ((yi == lasty && !jl_has_free_typevars(xi) && !jl_has_free_typevars(yi)) || - (yi == lasty && !vx && vy && jl_is_leaf_type(xi)))) { + (yi == lasty && !vx && vy && jl_is_concrete_type(xi)))) { // fast path for repeated elements } else if (e->Runions.depth == 0 && e->Lunions.depth == 0 && !jl_has_free_typevars(xi) && !jl_has_free_typevars(yi)) { @@ -873,7 +873,7 @@ static int subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param) // TODO this is not strictly correct, but we don't yet have any other way for // e.g. the argument `Int` to match a `::DataType` slot. Most correct would be: // Int isa DataType, Int isa Type{Int}, Type{Int} more specific than DataType, - // !(Type{Int} <: DataType), !isleaftype(Type{Int}), because non-DataTypes can + // !(Type{Int} <: DataType), !isconcrete(Type{Int}), because non-DataTypes can // be type-equal to `Int`. return jl_typeof(tp0) == (jl_value_t*)yd; } @@ -1114,7 +1114,7 @@ JL_DLLEXPORT int jl_isa(jl_value_t *x, jl_value_t *t) if (t == (jl_value_t*)jl_type_type) return 1; if (!jl_has_free_typevars(x)) { - if (jl_is_leaf_type(t)) { + if (jl_is_concrete_type(t)) { if (jl_is_type_type(t)) return jl_types_equal(x, jl_tparam0(t)); return 0; @@ -1146,7 +1146,7 @@ JL_DLLEXPORT int jl_isa(jl_value_t *x, jl_value_t *t) return 0; } } - if (jl_is_leaf_type(t)) + if (jl_is_concrete_type(t)) return 0; return jl_subtype(jl_typeof(x), t); } @@ -1375,7 +1375,7 @@ static jl_value_t *finish_unionall(jl_value_t *res, jl_varbinding_t *vb, jl_sten // given x<:T<:x, substitute x for T varval = vb->ub; } - else if (!var_occurs_inside(res, vb->var, 0, 1) && is_leaf_bound(vb->ub)) { + else if (!var_occurs_inside(res, vb->var, 0, 1) && is_concrete_bound(vb->ub)) { // replace T<:x with x in covariant position when possible varval = vb->ub; } @@ -1475,7 +1475,7 @@ static jl_value_t *finish_unionall(jl_value_t *res, jl_varbinding_t *vb, jl_sten if (vb->right && e->envidx < e->envsz) { jl_value_t *oldval = e->envout[e->envidx]; - if (!varval || (!is_leaf_bound(varval) && !vb->occurs_inv)) + if (!varval || (!is_concrete_bound(varval) && !vb->occurs_inv)) e->envout[e->envidx] = (jl_value_t*)vb->var; else if (!(oldval && jl_is_typevar(oldval) && jl_is_long(varval))) e->envout[e->envidx] = varval; @@ -1511,7 +1511,7 @@ static jl_value_t *intersect_unionall_(jl_value_t *t, jl_unionall_t *u, jl_stenv else { res = intersect(u->body, t, e, param); } - vb->concrete |= (!vb->occurs_inv && vb->occurs_cov > 1 && is_leaf_typevar((jl_value_t*)u->var)); + vb->concrete |= (!vb->occurs_inv && vb->occurs_cov > 1 && is_concrete_typevar((jl_value_t*)u->var)); // handle the "diagonal dispatch" rule, which says that a type var occurring more // than once, and only in covariant position, is constrained to concrete types. E.g. @@ -1521,7 +1521,7 @@ static jl_value_t *intersect_unionall_(jl_value_t *t, jl_unionall_t *u, jl_stenv if (res != jl_bottom_type && vb->concrete) { if (jl_is_typevar(vb->lb)) { } - else if (!is_leaf_bound(vb->lb)) { + else if (!is_concrete_bound(vb->lb)) { res = jl_bottom_type; } } @@ -1971,11 +1971,11 @@ static jl_value_t *intersect(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int pa if (ii == jl_bottom_type) return jl_bottom_type; if (jl_is_typevar(xp1)) { jl_varbinding_t *xb = lookup(e, (jl_tvar_t*)xp1); - if (xb && is_leaf_typevar((jl_value_t*)xb->var)) xb->concrete = 1; + if (xb && is_concrete_typevar((jl_value_t*)xb->var)) xb->concrete = 1; } if (jl_is_typevar(yp1)) { jl_varbinding_t *yb = lookup(e, (jl_tvar_t*)yp1); - if (yb && is_leaf_typevar((jl_value_t*)yb->var)) yb->concrete = 1; + if (yb && is_concrete_typevar((jl_value_t*)yb->var)) yb->concrete = 1; } JL_GC_PUSH2(&ii, &i2); // Vararg{T,N} <: Vararg{T2,N2}; equate N and N2 @@ -2122,7 +2122,7 @@ jl_value_t *jl_type_intersection_env_s(jl_value_t *a, jl_value_t *b, jl_svec_t * *ans = b; } else { - int lta = jl_is_leaf_type(a), ltb = jl_is_leaf_type(b); + int lta = jl_is_concrete_type(a), ltb = jl_is_concrete_type(b); if (lta && ltb) goto bot; jl_stenv_t e; diff --git a/src/typemap.c b/src/typemap.c index 9d612538390d4..ad2a64b3dd9f3 100644 --- a/src/typemap.c +++ b/src/typemap.c @@ -32,7 +32,7 @@ static int sig_match_by_type_leaf(jl_value_t **types, jl_tupletype_t *sig, size_ for(i=0; i < n; i++) { jl_value_t *decl = jl_field_type(sig, i); jl_value_t *a = types[i]; - if (jl_is_type_type(a)) // decl is not Type, because it wouldn't be leafsig + if (jl_is_type_type(a)) // decl is not Type, because it wouldn't be concrete sig a = jl_typeof(jl_tparam0(a)); if (!jl_types_equal(a, decl)) return 0; @@ -334,7 +334,7 @@ static union jl_typemap_t *mtcache_hash_bp(struct jl_ordereddict_t *pa, jl_value if (jl_is_datatype(ty)) { uintptr_t uid = ((jl_datatype_t*)ty)->uid; if (!uid || jl_is_kind(ty) || jl_has_free_typevars(ty)) - // be careful not to put non-leaf types or DataType/UnionAll in the cache here, + // be careful not to put non-concrete types or DataType/UnionAll in the cache here, // since they should have a lower priority and need to go into the sorted list return NULL; if (pa->values == (void*)jl_nothing) { @@ -417,7 +417,7 @@ int jl_typemap_visitor(union jl_typemap_t cache, jl_typemap_visitor_fptr fptr, v } } -// predicate to fast-test if this type is a leaf type that can exist in the cache +// predicate to fast-test if this type is a concrete type that can exist in the cache // and does not need a more expensive linear scan to find all intersections int is_cache_leaf(jl_value_t *ty) { @@ -442,10 +442,10 @@ static int jl_typemap_intersection_array_visitor(struct jl_ordereddict_t *a, jl_ if (tparam) t = jl_tparam0(t); } - // `t` is a leaftype, so intersection test becomes subtype + // `t` is a concrete type, so intersection test becomes subtype if (ty == (jl_value_t*)jl_any_type || // easy case: Any always matches (tparam - ? (jl_typeof(t) == ty || jl_isa(t, ty)) // (Type{t} <: ty), where is_leaf_type(t) => isa(t, ty) + ? (jl_typeof(t) == ty || jl_isa(t, ty)) // (Type{t} <: ty), where isconcrete(t) => isa(t, ty) : (t == ty || jl_subtype(t, ty)))) { if (!jl_typemap_intersection_visitor(ml, offs + 1, closure)) return 0; @@ -513,7 +513,7 @@ int jl_typemap_intersection_visitor(union jl_typemap_t map, int offs, jl_value_t *typetype = jl_is_type_type(ty) ? jl_tparam0(ty) : NULL; if (typetype && !jl_has_free_typevars(typetype)) { if (is_cache_leaf(typetype)) { - // direct lookup of leaf types + // direct lookup of concrete types union jl_typemap_t ml = mtcache_hash_lookup(&cache->targ, typetype, 1, offs); if (ml.unknown != jl_nothing) { if (!jl_typemap_intersection_visitor(ml, offs+1, closure)) return 0; @@ -529,7 +529,7 @@ int jl_typemap_intersection_visitor(union jl_typemap_t map, int offs, } if (cache->arg1.values != (void*)jl_nothing) { if (is_cache_leaf(ty)) { - // direct lookup of leaf types + // direct lookup of concrete types union jl_typemap_t ml = mtcache_hash_lookup(&cache->arg1, ty, 0, offs); if (ml.unknown != jl_nothing) { if (!jl_typemap_intersection_visitor(ml, offs+1, closure)) return 0; @@ -583,7 +583,7 @@ static jl_typemap_entry_t *jl_typemap_assoc_by_type_(jl_typemap_entry_t *ml, jl_ if (ismatch == 0) ; // nothing - else if (ml->isleafsig && !typesisva) + else if (ml->isconcretesig && !typesisva) ismatch = sig_match_by_type_leaf(jl_svec_data(types->parameters), ml->sig, lensig); else if (ml->issimplesig && !typesisva) @@ -759,7 +759,7 @@ jl_typemap_entry_t *jl_typemap_assoc_by_type(union jl_typemap_t ml_or_cache, jl_ jl_typemap_entry_t *jl_typemap_entry_assoc_exact(jl_typemap_entry_t *ml, jl_value_t **args, size_t n, size_t world) { // some manually-unrolled common special cases - while (ml->simplesig == (void*)jl_nothing && ml->guardsigs == jl_emptysvec && ml->isleafsig) { + while (ml->simplesig == (void*)jl_nothing && ml->guardsigs == jl_emptysvec && ml->isconcretesig) { // use a tight loop for a long as possible if (world >= ml->min_world && world <= ml->max_world) { if (n == jl_field_count(ml->sig) && jl_typeof(args[0]) == jl_tparam(ml->sig, 0)) { @@ -802,7 +802,7 @@ jl_typemap_entry_t *jl_typemap_entry_assoc_exact(jl_typemap_entry_t *ml, jl_valu } } - if (ml->isleafsig) { + if (ml->isconcretesig) { if (!sig_match_leaf(args, jl_svec_data(ml->sig->parameters), n)) continue; } @@ -913,7 +913,7 @@ static jl_typemap_level_t *jl_method_convert_list_to_cache(jl_typemap_entry_t *m static void jl_typemap_list_insert_(jl_typemap_entry_t **pml, jl_value_t *parent, jl_typemap_entry_t *newrec, const struct jl_typemap_info *tparams) { - if (*pml == (void*)jl_nothing || newrec->isleafsig || (tparams && tparams->unsorted)) { + if (*pml == (void*)jl_nothing || newrec->isconcretesig || (tparams && tparams->unsorted)) { newrec->next = *pml; jl_gc_wb(newrec, newrec->next); *pml = newrec; @@ -1036,28 +1036,28 @@ jl_typemap_entry_t *jl_typemap_insert(union jl_typemap_t *cache, jl_value_t *par // compute the complexity of this type signature newrec->va = jl_is_va_tuple((jl_datatype_t*)ttype); newrec->issimplesig = !jl_is_unionall(type); // a TypeVar environment needs a complex matching test - newrec->isleafsig = newrec->issimplesig && !newrec->va; // entirely leaf types don't need to be sorted + newrec->isconcretesig = newrec->issimplesig && !newrec->va; // entirely concrete types don't need to be sorted JL_GC_PUSH1(&newrec); assert(jl_is_tuple_type(ttype)); size_t i, l; for (i = 0, l = jl_field_count(ttype); i < l && newrec->issimplesig; i++) { jl_value_t *decl = jl_field_type(ttype, i); if (decl == (jl_value_t*)jl_datatype_type) - newrec->isleafsig = 0; // Type{} may have a higher priority than DataType + newrec->isconcretesig = 0; // Type{} may have a higher priority than DataType else if (decl == (jl_value_t*)jl_unionall_type) - newrec->isleafsig = 0; // Type{} may have a higher priority than UnionAll + newrec->isconcretesig = 0; // Type{} may have a higher priority than UnionAll else if (decl == (jl_value_t*)jl_uniontype_type) - newrec->isleafsig = 0; // Type{} may have a higher priority than Union + newrec->isconcretesig = 0; // Type{} may have a higher priority than Union else if (jl_is_type_type(decl)) - newrec->isleafsig = 0; // Type{} may need special processing to compute the match + newrec->isconcretesig = 0; // Type{} may need special processing to compute the match else if (jl_is_vararg_type(decl)) - newrec->isleafsig = 0; // makes iteration easier when the endpoints are the same + newrec->isconcretesig = 0; // makes iteration easier when the endpoints are the same else if (decl == (jl_value_t*)jl_any_type) - newrec->isleafsig = 0; // Any needs to go in the general cache - else if (!jl_is_leaf_type(decl)) // anything else can go through the general subtyping test - newrec->isleafsig = newrec->issimplesig = 0; + newrec->isconcretesig = 0; // Any needs to go in the general cache + else if (!jl_is_concrete_type(decl)) // anything else can go through the general subtyping test + newrec->isconcretesig = newrec->issimplesig = 0; } - // TODO: assert that guardsigs == jl_emptysvec && simplesig == jl_nothing if isleafsig and optimize with that knowledge? + // TODO: assert that guardsigs == jl_emptysvec && simplesig == jl_nothing if isconcretesig and optimize with that knowledge? jl_typemap_insert_generic(cache, parent, newrec, NULL, offs, tparams); JL_GC_POP(); return newrec; @@ -1085,7 +1085,7 @@ static void jl_typemap_list_insert_sorted(jl_typemap_entry_t **pml, jl_value_t * l = *pml; jl_value_t *pa = parent; while (l != (void*)jl_nothing) { - if (!l->isleafsig) { // quickly ignore all of the leafsig entries (these were handled by caller) + if (!l->isconcretesig) { // quickly ignore all of the concrete sig entries (these were handled by caller) if (jl_type_morespecific((jl_value_t*)newrec->sig, (jl_value_t*)l->sig)) { if (l->simplesig == (void*)jl_nothing || newrec->simplesig != (void*)jl_nothing || !jl_types_equal((jl_value_t*)l->sig, (jl_value_t*)newrec->sig)) { diff --git a/test/arrayops.jl b/test/arrayops.jl index ceee283cf2fe3..f03d310a9504a 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -1893,7 +1893,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 isconcrete(Base.return_types(f, ())[1]) end end diff --git a/test/core.jl b/test/core.jl index 23362653ca884..59fdf1ad2f481 100644 --- a/test/core.jl +++ b/test/core.jl @@ -184,7 +184,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 isconcrete(elT2.body.types[1]) end # issue #3890 @@ -4235,7 +4235,7 @@ let a = Val{Val{TypeVar(:_, Int)}}, @test !isdefined(a, :instance) @test isdefined(b, :instance) - @test isleaftype(b) + @test isconcrete(b) end # A return type widened to Type{Union{T,Void}} should not confuse diff --git a/test/inference.jl b/test/inference.jl index 19b446af34335..0328190bd69b9 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -194,8 +194,8 @@ end end let ast12474 = code_typed(f12474, Tuple{Float64}) - @test isleaftype(ast12474[1][2]) - @test all(isleaftype, ast12474[1][1].slottypes) + @test isconcrete(ast12474[1][2]) + @test all(isconcrete, ast12474[1][1].slottypes) end @@ -227,7 +227,7 @@ bar7810() = [Foo7810([(a,b) for a in 1:2]) for b in 3:4] # issue #11366 f11366(x::Type{Ref{T}}) where {T} = Ref{x} -@test !isleaftype(Base.return_types(f11366, (Any,))[1]) +@test !isconcrete(Base.return_types(f11366, (Any,))[1]) let f(T) = Type{T} @@ -444,10 +444,10 @@ function is_typed_expr(e::Expr) return false end test_inferred_static(@nospecialize(other)) = true -test_inferred_static(slot::TypedSlot) = @test isleaftype(slot.typ) +test_inferred_static(slot::TypedSlot) = @test isconcrete(slot.typ) function test_inferred_static(expr::Expr) if is_typed_expr(expr) - @test isleaftype(expr.typ) + @test isconcrete(expr.typ) end for a in expr.args test_inferred_static(a) @@ -455,10 +455,10 @@ function test_inferred_static(expr::Expr) end function test_inferred_static(arrow::Pair) code, rt = arrow - @test isleaftype(rt) + @test isconcrete(rt) @test code.inferred - @test all(x->isleaftype(x), code.slottypes) - @test all(x->isleaftype(x), code.ssavaluetypes) + @test all(x->isconcrete(x), code.slottypes) + @test all(x->isconcrete(x), code.ssavaluetypes) for e in code.code test_inferred_static(e) end diff --git a/test/reflection.jl b/test/reflection.jl index 8d4f0ef9f49d8..dc8f3d4dd2cb5 100644 --- a/test/reflection.jl +++ b/test/reflection.jl @@ -29,7 +29,7 @@ end function test_code_reflections(tester, freflect) test_code_reflection(freflect, ismatch, Tuple{Regex, AbstractString}, tester) # abstract type - test_code_reflection(freflect, +, Tuple{Int, Int}, tester) # leaftype signature + test_code_reflection(freflect, +, Tuple{Int, Int}, tester) # concrete type signature test_code_reflection(freflect, +, Tuple{Array{Float32}, Array{Float32}}, tester) # incomplete types test_code_reflection(freflect, Module, Tuple{}, tester) # Module() constructor (transforms to call) @@ -133,11 +133,11 @@ end @test isbits(Tuple{Vararg{Any, 0}}) # issue #16670 -@test isleaftype(Tuple{Int, Vararg{Int, 2}}) -@test !isleaftype(Tuple{Integer, Vararg{Int, 2}}) -@test !isleaftype(Tuple{Int, Vararg{Int}}) -@test isleaftype(Type{Tuple{Integer, Vararg{Int}}}) -@test isleaftype(Type{Vector}) +@test isconcrete(Tuple{Int, Vararg{Int, 2}}) +@test !isconcrete(Tuple{Integer, Vararg{Int, 2}}) +@test !isconcrete(Tuple{Int, Vararg{Int}}) +@test isconcrete(Type{Tuple{Integer, Vararg{Int}}}) +@test isconcrete(Type{Vector}) # issue #10165 i10165(::Type) = 0