The Mojo ManualXYZ Homework Edition

⇩ Download ▾

4.3 Initialization state

Mojo tracks two kinds of initialization for structs: fieldwise and logical.

Fieldwise initialization means every field contains a valid value. Logical initialization means the instance as a whole is valid and ready to use. A struct needs both before you can use it.

The basics

You create struct instances by calling the __init__() initializer:

struct Person:
    var name: String
    var age: Int

    def __init__(out self, name: String, age: Int):
        self.name = name
        self.age = age

def main():
    var me = Person("Alice", 30)

Calling Person("Alice", 30) is syntactic sugar for calling the initializer directly:

var me: Person
me = Person.__init__("Alice", 30) # Identical

When constructing a Person, the compiler allocates the necessary storage and __init__() initializes that memory.

Fieldwise vs logical initialization

Initializing a struct by assigning values directly to its fields may populate the data, but it doesn't make the instance usable:

@fieldwise_init
struct Person(Writable):
    var name: String
    var age: Int

def main():
    var me: Person
    me.name = "Alice"
    me.age = 25
    print(me)  # Error
    # error: 'me' used with all fields manually initialized
    # but without calling an '__init__' method
Show error output ✓ Verified · Mojo 1.1.0 (8189361e)
ch04-002.mojo:10:10: error: 'me' used with all fields manually initialized but without calling an '__init__' method
    print(me)  # Error
         ^
ch04-002.mojo:7:9: note: 'me' declared here
    var me: Person
        ^
mojo: error: failed to run the pass manager

In this example, all fields contain valid values, but the instance is still not considered initialized.

Assigning every field satisfies fieldwise initialization, but without running an __init__() method, it doesn't satisfy logical initialization.

Construct the value with an initializer to establish both:

var me: Person      # Not initialized
me = Person("Alice", 30)  # Logically and fieldwise initialized after call
print(me)

After __init__() completes, the instance is safe to use.

Inside __init__()

Within __init__(), self is logically initialized, but its fields are uninitialized. This reverses the situation before calling __init__(), where the fields are initialized but self is not:

def __init__(out self, name: String, age: Int):
    # At this point:
    # - Logically initialized (self is valid as an instance)
    # - Fieldwise uninitialized (fields have no values yet)

    self.name = name
    self.age = age

    # Now both logically and fieldwise initialized

Entering __init__() establishes the instance. It's your responsibility to populate every field:

def __init__(out self, name: String, age: Int):
    self.name = name
    # Error: field 'age' not initialized in __init__

The __init__() signature doesn't have to mirror the struct's fields. You can use parameters, constants, or external values to initialize them:

# Parameters can be used to initialize fields
self._store = List[T](capacity=Count)

# Constants can be used to initialize fields
self.string = ""

# External values can be used to initialize fields
from std.math import pi
self.default_angle = pi / 2.0
self.uuid = MyUUIDImplementation.uuid()

Calling methods

You can't call methods until all fields are initialized:

def __init__(out self, name: String):
    self.greet()      # Error: self not fully initialized
    self.name = name
    self.greet()      # OK: all fields initialized

Field initialization is limited to __init__() methods.

Regular methods can't initialize individual fields of an out argument, but __init__() methods can.

Adapted from the Mojo Manual and the MAX GPU programming guides, part of the Modular Platform repository (github.com/modular/modular), Copyright (c) Modular Inc., licensed under the Apache License v2.0 with LLVM Exceptions. Changes were made: reformatted as an accessible XYZ web edition with build-verified example outputs. Mojo and MAX are trademarks of Modular Inc.; this edition is not affiliated with or endorsed by Modular. License: Apache-2.0 WITH LLVM-exception.

These eBooks are a prerelease and are not yet certified conformant with WCAG 2.1 AA or any other accessibility standard. Every page is built against an automated accessibility gate, and our target for the published editions is WCAG 2.2 Level AA. If something is unusable, please tell us.