Types

Table of Contents

1. Enumerations

2. Bit Sets

bit_set type models the mathematical notion of a set. A bitset’s element type can be either an enumeration or a range. They are implemented as bit vectors internally for high performance.

  • A + B, A | B union
  • A - B, A &~ B difference set. (A without B’s element)
  • A & B intersect
  • A <= B A subseteq B
  • e in A membership
  • e not_in A not membership

3. Pointers

&x takes the address (reference) and p^ dereferences pointer p.

4. Structs

Similar to structs in C. Struct fields can be accessed through struct pointer without dereferencing.

Vector2 :: struct {
  x: f32,
  y: f32
}

v := Vector2 {1, 2}
v.x = 4

// or through pointers
p := &v
p.x = 114514

structs can be nested.

4.1. Directives

structs can be annotated with different memory layout and alignment requirements.

  • struct #align(4) {} aligns to 4 bytes
  • #raw_union all fields share the same offset. same as C’s union.
  • #packed remove paddings between fields
  • #min_field_align(4) all fields must have a minimum alignment of 4 bytes
  • #max_field_align(4) … maximum alignment
  • #simple
  • #all_or_none prevents partial initialization

4.2. Struct field tags

String attached to the field for documentation.

5. Unions

Value :: union {
  bool,
  i32,
  f32
}

v : Value
v = "Hello"

s1 := v.(string) // type assert that v is a string, panic otherwise
s2, ok := v.(string) // explicit boolean check, will not panic

5.1. Type switch statement

value: Value = ...

switch v in value {
case string:
    #assert(type_of(v) == string)

case bool:
    #assert(type_of(v) == bool)

case i32, f32:
    // This case allows for multiple types, therefore we cannot know which type to use
    // `v` remains the original union value
    #assert(type_of(v) == Value)
case:
    // Default case
    // In this case, it is `nil`
}

5.2. Union Tags

#no_nil to a union type states it does not have a nil value. Union with #no_nil must have 2+ variants and the first variant is its default type.

#shared_nil

6. Maps

7. Bit Fields

Foo :: bit_field u16 { // backing type must be an integer or array of integers
    x: i32     | 3, // signed integers will be signed extended on use
    y: u16     | 2 + 3, // general expressions
    z: My_Enum | foo.SOME_CONSTANT, // ability to define the bit-width elsewhere
    w: bool    | 2 when foo.SOME_CONSTANT > 10 else 1,
}

v := Foo{}
v.x = 3 // truncates the value to fit into 3 bits
fmt.println(v.x) // accessing will convert `v.x` to an `i32` and do an appropriate sign extension

8. Procedure Type

A procedure type is internally a pointer to a procedure in memory. nil is the zero value of a procedure type.

8.1. Calling Conventions

proc "odin" (...)
default convention. pass all params >= 16 bytes by reference; pass an implicit context pointer on each call.
contextless
without context pointer
stdcall, std
stdcall convention by Microsoft
cdecl, c
as in C
fastcall, fast
compiler dependent calling convention.
none
do nothing to params

When working with C libs, often proc "c" is needed and should pass context explicitly.

8.2. Pass context explicitly

9. Multi Pointers

Date: 2026-06-11 Thu