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 everythingbecause 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'aof some kindk, we substitute'ato 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'aof some kindk, we substitute'ato 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
privateabbreviation has the kind of its right-hand side. -
A
privateannotation 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_2has kindvalue mod aliased contended immutable non_floatwithout constraining the kinds of eitherty_1orty_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_ihas layoutlay_i. -
An applied type constructor
(ty_1, ..., ty_n) t(where n >= 0) has the kind assigned totat its declaration, with type arguments substituted into any type variables mentioned in thetwith-bounds. Each of thety_iis 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_iis 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 constructorsincludes 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 kindk0of the innerty. Then find the lowest kindkthat has no with-bounds but withk0 <= k. The kind of'a. tyisk. Note that ifk0has 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, analyzingSfor mode-crossing opportunities.) -
The type
'a arrayhas kindmutable_data with 'a. The kind of'amust be a subkind ofany mod non_null separable. -
The type
'a iarrayhas kindimmutable_data with 'a. The kind of'amust be a subkind ofany mod non_null separable. -
The type
'a lazy_thas kindvalue mod non_float. The kind of'amust be a subkind ofvalue.