Skip to main content
Tolk supports union types such as T1 | T2 | T3. A union type represents a value that can be one of several types. Pattern matching is used to distinguish union variants. A special case T | null is written as T? and referred to as a nullable type.

Arbitrary union types

Union types are not limited to structures. Any types can be combined into a union. The following union types are valid:
  • int | slice;
  • address | Point | null;
  • Increment | Reset | coins;
  • int8 | int16 | int32 | int64.
Union types are automatically flattened:
Union types support assignment based on subtype relations. For example, a value of type B | C can be passed to or assigned to A | B | C | D:

Exhaustive pattern matching

A match expression must cover all possible cases. It must be exhaustive.
match can be used with nullable types, since T? is equivalent to T | null. It can also be used as an expression:

Union type inference errors

Auto-inference of a union type results in an error. If match arms produce values of different types, the inferred result is a union, which is typically not intended:
The type of a is inferred as builder | int. In most cases, this indicates an error in the code. In such cases, the compiler emits the following message:
To resolve this, either explicitly declare a as a union type or fix the code if the union is unintended. The same rule applies to other cases, such as return type inference:
The result is inferred as int32 | int64. While it is valid, a single integer type is usually expected. The compiler reports an error. To fix it, explicitly declare the return type:
Declaring return types is recommended practice.

is and !is operators

Union types can be tested using the is operator:

lazy matching for unions

In message-handling, union values are commonly parsed using lazy:
This pattern is referred to as lazy match:
  1. No union is allocated on the stack upfront; loading is deferred until needed.
  2. match operates by inspecting the slice prefix (opcode), instead of checking a type identifier on the stack.
Union types continue to work correctly without lazy and follow the same type-system rules.

Stack layout and serialization

Union types have a complex stack layout, commonly referred to as tagged unions. Serialization depends on whether the union consists of structures with manual serialization prefixes:
  • if yes; for example, struct (0x1234) A, those prefixes are used;
  • if no, the compiler automatically generates a prefix tree; for example, T1 | T2 is called Either type: 0 + T1 or 1 + T2.