Skip to content

Commit 1d67722

Browse files
authored
Update docs for various type predicates (#58774)
Makes the description for `isdispatchtuple` accurate, adds a docstring for `iskindtype` and `isconcretedispatch`, and adds notes to the docs for `isconcretetype` and `isabstracttype` explaining why they aren't antonyms.
1 parent 7b6065e commit 1d67722

File tree

2 files changed

+96
-4
lines changed

2 files changed

+96
-4
lines changed

base/runtime_internals.jl

Lines changed: 94 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
857871
If `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
"""
859894
isdispatchtuple(@nospecialize(t)) = (@_total_meta; isa(t, DataType) && (t.flags & 0x0004) == 0x0004)
860895

@@ -900,7 +935,40 @@ function isidentityfree(@nospecialize(t))
900935
return false
901936
end
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+
"""
903947
iskindtype(@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+
"""
904972
isconcretedispatch(@nospecialize t) = isconcretetype(t) && !iskindtype(t)
905973

906974
using Core: has_free_typevars
@@ -923,6 +991,16 @@ Determine whether type `T` is a concrete type, meaning it could have direct inst
923991
Note that this is not the negation of `isabstracttype(T)`.
924992
If `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+
9261004
See also: [`isbits`](@ref), [`isabstracttype`](@ref), [`issingletontype`](@ref).
9271005
9281006
# Examples
@@ -933,6 +1011,9 @@ false
9331011
julia> isconcretetype(Complex{Float32})
9341012
true
9351013
1014+
julia> isconcretetype(Vector)
1015+
false
1016+
9361017
julia> isconcretetype(Vector{Complex})
9371018
true
9381019
@@ -944,6 +1025,9 @@ false
9441025
9451026
julia> isconcretetype(Union{Int,String})
9461027
false
1028+
1029+
julia> isconcretetype(Tuple{T} where T<:Int)
1030+
false
9471031
```
9481032
"""
9491033
isconcretetype(@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
9541038
Determine 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)`.
9571040
If `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
9611051
julia> isabstracttype(AbstractArray)

doc/src/base/base.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ Base.typeintersect
193193
Base.promote_type
194194
Base.promote_rule
195195
Base.promote_typejoin
196+
Base.iskindtype
196197
Base.isdispatchtuple
197198
```
198199

@@ -251,6 +252,7 @@ Base.instances
251252
Core.Any
252253
Core.Union
253254
Union{}
255+
Core.TypeofBottom
254256
Core.UnionAll
255257
Core.Tuple
256258
Core.NTuple

0 commit comments

Comments
 (0)