Kinds of types
This page describes how we compute the kind of both built-in types and user-defined types. You may want to read the overview of the kind system first.
Kinds of user-defined types
-
A boxed record type with at least one mutable field has the kind
mutable_data with <<all record fields, with their modalities>>
. -
A boxed record type with no mutable fields has the kind
immutable_data with <<all record fields, with their modalities>>
. -
An unboxed record type (including ones implicitly declared when making a boxed record declaration) has the kind
lay_1 & ... & lay_n mod everything with <<all record fields, with their modalities>>
. (It ismod everything
because it does not allocate.) -
A record declared with
[@@unboxed]
has the same kind as its field. -
A variant type with all constant constructors has the kind
immediate
. -
A variant type with at least one mutable field has the kind
mutable_data with <<all fields from all constructors, with their modalities>>
. For every existentially bound variable'a
of some kindk
, we substitute'a
to become(type : k)
when building the with-bounds. (Otherwise, the existential would be out of scope in the with-bounds.) -
A variant type with no mutable fields (but at least one field) has the kind
immutable_data with <<all fields from all constructors, with their modalities>>
. For every existentially bound variable'a
of some kindk
, we substitute'a
to become(type : k)
when building the with-bounds. (Otherwise, the existential would be out of scope in the with-bounds.) -
An extensible variant (declared with
= ..
) has kindvalue mod non_float
. -
A
private
abbreviation has the kind of its right-hand side. -
A
private
annotation on a record or variant type does not affect its kind. -
Records and variants can have the attribute
[@@unsafe_allow_any_mode_crossing]
; these declarations must have a kind annotation. The bounds given in the kind annotation override the bounds determined by the rules above.
Kinds of types in the type algebra
Types formed from the type algebra are also assigned kinds, according to the following algorithm.
-
All type variables have a kind. As described more on the syntax page, flexible type variables infer their kinds, while rigid type variables must be assigned a kind when they are brought into scope. A rigid type variable brought into scope without a kind annotation defaults to kind
value
. -
A function type
ty_1 -> ty_2
has kindvalue mod aliased contended immutable non_float
without constraining the kinds of eitherty_1
orty_2
. -
A tuple
ty_1 * ... * ty_n
(where n >= 2) has kindimmutable_data with <<all the component types>>
without constraining the kinds of any of thety_i
. -
An unboxed tuple
#( ty_1 * ... * ty_n )
(where n >= 2) has kindlay_1 & ... & lay_n mod everything with <<all the component types>>
, wherety_i
has layoutlay_i
. -
An applied type constructor
(ty_1, ..., ty_n) t
(where n >= 0) has the kind assigned tot
at its declaration, with type arguments substituted into any type variables mentioned in thet
with-bounds. Each of thety_i
is constrained to be a subkind of the kind on the corresponding type parameter tot
. -
An object type
< f1 : ty_1; ...; fn : ty_n >
has kindvalue mod non_float
. Eachty_i
is constrained to have a kind that is a subkind ofvalue
. -
A polymorphic variant type written via expansion of another type, such as
[ t | `C ]
, is expanded before computing its kind, which will use the rules below. -
A closed polymorphic variant type (
[ `K_1 | ... | `K_n ]
or[< `K_1 | ... `K_n ]
or[< `K_1 | ... | `K_n > `K_j | ... | `K_k ]
), where all constructors are constant constructors, has kindimmediate
. -
A closed polymorphic variant type with at least one non-constant constructor has kind
immutable_data with <<all fields from all constructors>>
. Theall fields from all constructors
includes any types in a conjunction built with&
. -
An open polymorphic variant type
[> `K_1 of tys_1 | ... | `K_n of tys_n ]
has kindvalue mod non_float
. -
To compute the kind of a polymorphic type
'a. ty
, start with the kindk0
of the innerty
. Then find the lowest kindk
that has no with-bounds but withk0 <= k
. The kind of'a. ty
isk
. Note that ifk0
has no with-bounds, thenk = k0
. (We will improve this in the future, with a treatment like that for existentials in variant type declarations.) -
A first-class module type
(module S)
has kindvalue mod non_float
. (We may be able to improve this, analyzingS
for mode-crossing opportunities.) -
The type
'a array
has kindmutable_data with 'a
. The kind of'a
must be a subkind ofany mod non_null separable
. -
The type
'a iarray
has kindimmutable_data with 'a
. The kind of'a
must be a subkind ofany mod non_null separable
. -
The type
'a lazy_t
has kindvalue mod non_float
. The kind of'a
must be a subkind ofvalue
.