@@ -851,10 +851,45 @@ end
851851"""
852852 isdispatchtuple(T)
853853
854- Determine whether type `T` is a tuple of concrete types,
855- meaning it could appear as a type signature in dispatch
856- and has no subtypes (or supertypes) which could appear in a call.
854+ Determine whether type `T` is a [`Tuple`](@ref) that could appear as a type
855+ signature in dispatch. For this to be true, every element of the tuple type
856+ must be either:
857+ - [concrete](@ref isconcretetype) but not a [kind type](@ref Base.iskindtype)
858+ - a [`Type{U}`](@ref Type) with no free type variables in `U`
859+
860+ !!! note
861+ A dispatch tuple is relevant for method dispatch because it has no inhabited
862+ subtypes.
863+
864+ For example, `Tuple{Int, DataType}` is concrete, but is not a dispatch tuple
865+ because `Tuple{Int, Type{Bool}}` is an inhabited subtype.
866+
867+ `Tuple{Tuple{DataType}}` *is* a dispatch tuple because `Tuple{DataType}` is
868+ concrete and not a kind; the subtype `Tuple{Tuple{Type{Int}}}` is not
869+ inhabited.
870+
857871If `T` is not a type, then return `false`.
872+
873+ # Examples
874+ ```jldoctest
875+ julia> isdispatchtuple(Int)
876+ false
877+
878+ julia> isdispatchtuple(Tuple{Int})
879+ true
880+
881+ julia> isdispatchtuple(Tuple{Number})
882+ false
883+
884+ julia> isdispatchtuple(Tuple{DataType})
885+ false
886+
887+ julia> isdispatchtuple(Tuple{Type{Int}})
888+ true
889+
890+ julia> isdispatchtuple(Tuple{Type})
891+ false
892+ ```
858893"""
859894isdispatchtuple (@nospecialize (t)) = (@_total_meta ; isa (t, DataType) && (t. flags & 0x0004 ) == 0x0004 )
860895
@@ -900,7 +935,40 @@ function isidentityfree(@nospecialize(t))
900935 return false
901936end
902937
938+ """
939+ Base.iskindtype(T)
940+
941+ Determine whether `T` is a kind, that is, the type of a Julia type:
942+ a [`DataType`](@ref), [`Union`](@ref), [`UnionAll`](@ref),
943+ or [`Core.TypeofBottom`](@ref).
944+
945+ All kinds are [concrete](@ref isconcretetype) because types are Julia values.
946+ """
903947iskindtype (@nospecialize t) = (t === DataType || t === UnionAll || t === Union || t === typeof (Bottom))
948+
949+ """
950+ Base.isconcretedispatch(T)
951+
952+ Returns true if `T` is a [concrete type](@ref isconcretetype) that could appear
953+ as an element of a [dispatch tuple](@ref isdispatchtuple).
954+
955+ See also: [`isdispatchtuple`](@ref).
956+
957+ # Examples
958+ ```jldoctest
959+ julia> Base.isconcretedispatch(Int)
960+ true
961+
962+ julia> Base.isconcretedispatch(Number)
963+ false
964+
965+ julia> Base.isconcretedispatch(DataType)
966+ false
967+
968+ julia> Base.isconcretedispatch(Type{Int})
969+ false
970+ ```
971+ """
904972isconcretedispatch (@nospecialize t) = isconcretetype (t) && ! iskindtype (t)
905973
906974using Core: has_free_typevars
@@ -923,6 +991,16 @@ Determine whether type `T` is a concrete type, meaning it could have direct inst
923991Note that this is not the negation of `isabstracttype(T)`.
924992If `T` is not a type, then return `false`.
925993
994+ !!! note
995+ While concrete types are not [abstract](@ref isabstracttype) and
996+ vice versa, types can be neither concrete nor abstract (for example,
997+ `Vector` (a [`UnionAll`](@ref))).
998+
999+ !!! note
1000+ `T` must be the exact type that would be returned from `typeof`. It is
1001+ possible for a type `U` to exist such that `T == U`, `isconcretetype(T)`,
1002+ but `!isconcretetype(U)`.
1003+
9261004See also: [`isbits`](@ref), [`isabstracttype`](@ref), [`issingletontype`](@ref).
9271005
9281006# Examples
@@ -933,6 +1011,9 @@ false
9331011julia> isconcretetype(Complex{Float32})
9341012true
9351013
1014+ julia> isconcretetype(Vector)
1015+ false
1016+
9361017julia> isconcretetype(Vector{Complex})
9371018true
9381019
@@ -944,6 +1025,9 @@ false
9441025
9451026julia> isconcretetype(Union{Int,String})
9461027false
1028+
1029+ julia> isconcretetype(Tuple{T} where T<:Int)
1030+ false
9471031```
9481032"""
9491033isconcretetype (@nospecialize (t)) = (@_total_meta ; isa (t, DataType) && (t. flags & 0x0002 ) == 0x0002 )
@@ -953,9 +1037,15 @@ isconcretetype(@nospecialize(t)) = (@_total_meta; isa(t, DataType) && (t.flags &
9531037
9541038Determine whether type `T` was declared as an abstract type
9551039(i.e. using the `abstract type` syntax).
956- Note that this is not the negation of `isconcretetype(T)`.
9571040If `T` is not a type, then return `false`.
9581041
1042+ !!! note
1043+ While abstract types are not [concrete](@ref isconcretetype) and
1044+ vice versa, types can be neither concrete nor abstract (for example,
1045+ `Vector` (a [`UnionAll`](@ref))).
1046+
1047+ See also: [`isconcretetype`](@ref).
1048+
9591049# Examples
9601050```jldoctest
9611051julia> isabstracttype(AbstractArray)
0 commit comments