Currently these are documented as valid type parameters:
Both abstract and concrete types can be parameterized by other types. They can also be parameterized by symbols, by values of any type for which
isbits
returns true (essentially, things like numbers and bools that are stored like C types orstruct
s with no pointers to other objects), and also by tuples thereof.
That is seemingly equivalent to this check:
function validparameter(x)
x isa Type || x isa Symbol || isbits(x) ||
# () isbits so don't need isempty check
(x isa Tuple && all(y -> (y isa Symbol || isbits(y)), x))
end
and some examples:
julia> validparameter.([Int :num () (:num, ()) (Int, Int) "num" Base])
1×7 BitMatrix:
1 1 1 1 0 0 0
Which mostly behave as expected when attempting to use as type parameters:
julia> Val.([Int :num () (:num, ())])
1×4 Matrix{Val}:
Val{Int64}() Val{:num}() Val{()}() Val{(:num, ())}()
julia> Val((Int, Int))
ERROR: TypeError: in Type, in parameter, expected Type, got a value of type Tuple{DataType, DataType}
...
julia> Val("num")
ERROR: TypeError: in Type, in parameter, expected Type, got a value of type String
...
Except for the module:
julia> Val(Base)
Val{Base}()
It’s useful for dispatch, but is this intentional and stable?