Structs
Structs
Section titled “Structs”struct declares a nominal type:
struct Point { Int x; Int y;}
struct Offset { Int x, y;}Int x, y; is shorthand for two fields of the same type.
Layout Options
Section titled “Layout Options”Struct layout options are written after struct:
struct [packed, align: 8] Packet { UInt8 tag; UInt32 value;}packed places fields without natural field padding. align: N sets the aggregate alignment to at
least N, and N must be a power of two. Option order does not matter, so
struct [align: 8, packed] is equivalent to struct [packed, align: 8]. Repeating the same option is
an error.
Default Constructors
Section titled “Default Constructors”Structs without custom init can use the compiler-provided default constructor. The default
constructor uses field names as required argument labels:
Point point = Point(x: 0, y: 0);Point^ heap_point = new Point(x: 100, y: 200);Positional arguments are not accepted for the default constructor:
Point point = Point(0, 0); // errorFields can have default values. A field with a default value can be omitted from the default constructor call:
struct Window { Int width; Int height = 600; Bool visible = true;}
Window window = Window(width: 800);When an expected type is available, the type name can be omitted with .(...):
Window make_window() { return .(width: 1024, visible: false);}Owning pointers can auto-dereference when the expected type is the pointee type. Field access can
also pass through T^:
print(heap_point.x);Field Mutability
Section titled “Field Mutability”A field is writable only when both the access path and the field declaration are writable. An
immutable binding, a shared T&, or another access path without write capability freezes reachable
fields:
struct User { Int id; Int age!; UInt8[]&? nick_name;}
User user! = User(id: 123, age: 18)user.age = user.age + 1;// user.id = 200; // error
User& readonly = user$.ref();// readonly.age = 20; // error: readonly outer borrowinit is a constructor entry in a struct body:
struct Point { Int x; Int y;
init(self, Int x, Int y) { self.x = x; self.y = y; return (); }
init(self, Int value) { self.x = value; self.y = value; return (); }}
Point p1 = Point(1, 2);Point p2 = Point(3);Point^ p3 = new Point(4, 5);Use init(self, ...) for ordinary custom constructors. self names the initializing target and is
not supplied at the call site. Remaining parameters follow normal function argument rules, including
named arguments and defaults. Once a struct declares any custom init, the compiler-provided field
constructor is not used.
deinit
Section titled “deinit”deinit is declared without a return type:
struct Buffer { UInt8* data;
deinit(self) { unsafe { self.data$.dealloc(); } return (); }}Methods
Section titled “Methods”Types define an instance method by putting a receiver first in the parameter list. Functions without a receiver are associated functions:
struct User { Int id;
Int zero() { return 0; }
Int value(self) { return self.id; }}
Int a = User.zero();User u = User(id: 42)Int b = u.value();The receiver shorthand self is readonly Self&. A method that writes mutable fields declares
Self&! self explicitly; borrow checking creates a unique mutable reborrow at the call site.
Local Declarations
Section titled “Local Declarations”Local variable declarations bind one name at a time:
Int a = 1;Int b = 2;Int c = 3;