Kinds and nominal conformance
Every E# type has a kind. Kind controls copying, identity, construction, nullability, and CLR interoperability; it is not inferred from how an individual value happens to be allocated.
Type-kind grammar
Section titled “Type-kind grammar”TypeKind = StructType | ClassType | UnionType | RefUnionType | EnumType | InterfaceType | DelegateType | PointerType | PrimitiveType | TupleType .StructType = "struct" TypeName [ TypeParameters ] .ClassType = [ "open" | "abstract" ] "class" TypeName [ TypeParameters ] .UnionType = "union" TypeName [ TypeParameters ] .RefUnionType = "ref" "union" TypeName [ TypeParameters ] .InterfaceType = "interface" TypeName [ TypeParameters ] .DelegateType = "delegate" "func" TypeName "(" [ ParameterList ] ")" [ ReturnType ] .PointerType = "*" Type .TupleType = "(" TupleElem { "," TupleElem } ")" .TupleElem = [ identifier ":" ] Type . // (x: int, y: int) , (count: int, int)struct, union, enum, primitives, and tuples have value discipline: assignment, argument passing, return,
and storage copy their value. class and ref union have reference discipline: those operations copy a
reference to one object. A pointer is a reference to a value location and is specified separately in
Pointers.
Value kinds
Section titled “Value kinds”A struct is a user-defined value type. It has no object identity and cannot contain itself by value. Its
construction forms are composite literals and positional struct construction; an init block is not valid.
readonly struct makes its fields immutable. A value union has the same value discipline, but represents
exactly one named case plus its case payload. An enum represents an int32-backed named integral value.
struct Point { var x: int, var y: int }union Parse { number(value: int), missing }enum Direction { north, east, south, west }Value equality is supplied by the type’s equality contract (derive equality for a user struct) or the CLR
default. It is not reference equality. Passing a value through an interface/object box creates an object that
contains a copy; it does not change the source value into a shared object.
Reference kinds
Section titled “Reference kinds”A class has object identity, supports constructors and inheritance, and is sealed by default. open makes
the class inheritable; abstract makes it non-instantiable. A ref union represents its cases as an abstract
reference base and sealed case objects; each constructed case has reference identity. A reference can be
absent (nil) and is usable where its nullable form is expected.
Nominal interfaces
Section titled “Nominal interfaces”An interface is a named contract. A type conforms only by declaring that interface in its base list; matching
members without that declaration does not create structural conformance. Member contracts include methods,
events, and properties. A property implementer must be declared as let or var and expose at least the
required accessor set. A field remains a field and never receives synthesized property accessors through
conformance. E# interface declarations conventionally use
the .NET I-prefixed PascalCase form (ISized, IMap<K, V>). The prefix is a source convention rather than
part of interface identity, so an imported or deliberately non-prefixed interface remains legal.
interface ISized { func size() -> int }
class Buffer : ISized { var count: int init(count: int) { self.count = count } func size() -> int = self.count}Conformance is exact in member name, parameter types, return type, and required property accessors. Generic
interfaces are reified and conformance is to the closed instantiation named by the type (IBox<int> is not
IBox<string>). The pointer method-set wrapper may implement an interface where only *T has the required
methods; see Pointers → method sets.
Reified generic identity
Section titled “Reified generic identity”Generic types and generic functions are reified. Option<int> and Option<string> are distinct CLR closed
types with their actual arguments, not erased object containers. Declaration identity is the pair of name
and arity, so Result<T, E> can coexist with a non-generic static Result factory facet. The generic rules,
constraints, and inference algorithm are specified in Generics.