As mentioned earlier, every value has a type it belongs to. Each type establishes all its permissible data values, determines how those values are digitally encoded, and specifies what operations can be performed on values of that type.
Cone offers a comprehensive repertoire of types:
- Primitive integer and floating-point number types. Several are built-in, such as i32, u8, f32 and Bool, as illustrated in prior page examples. Additional distinct number types may be defined using the integer or float keywords.
- enum types, which enumerate a set of named values, each mapped to a unique integer.
- struct types. Each named struct type is composed of some number of co-located, named, and typed fields.
- array types. Statically-sized arrays are composed of a fixed, constant number of values, all of the same type.
- union types. Each named union type specifies multiple type definitions. Any value of this union type could belong to one of these alternative types. Cone builds in support (and syntactic sugar) for two union types: Option and Result.
- reference types. These offer a safe way to point at some value stored in memory. There are three flavors: regular, array and virtual. References can additionally be region-managed or borrowed. Race safety is protected via permissions.
- pointer types. Like references, pointer types also point at some memory-stored value. Unlike reference, pointers do not have compiler-enforced guard rails to ensure their use is safe.
- traits types. Traits are supertypes that abstract the type signature (interface) that is common across several types. They are very useful when we want to work with values of many different types in the same way.
- void type. This built-in type represents the absence of any value. It does have its uses.
As you will see explored later, Cone's type system supports a rich and useful variety of semantics:
- Most types are concrete, but some (particularly trait) are abstract. Only concrete-typed values can be passed around or stored in variables. Abstract values can only be pointed-at using a reference.
- Most types are defined and used by name (nominal). Others are defined by their structure (e.g., arrays and references).
- Some types enforce constraints on how its values may be used:
- The values of most types may be freely copied. However, some types are defined with move semantics, which prevents the existence of multiple copies of the same object.
- Most values may freely move around anywhere in a program. However, some types restrict its values to a particular scope, such as the lifetime of a block, a particular thread, or a region.
- In certain cases, it is safe and possible to implicitly coerce a value of one type into its supertype's comparable value.
- Named types can be genericized using type parameters.
Let's start our type journey by introducing a number of the concrete types listed above. Later on, references and traits will be covered separately.
These pages will focus on how to define the structure of these type's data values. Subsequent pages will show how to also specify a type's functional behavior in the form of methods.