Type coercion rules in Zig
The following small overview of type coercion rules in Zig is an amalgam of the official Zig documentation and a relevant exercise that is part of ziglings. It does not purport to be exhaustive and the official documentation should be consulted for in-depth explanations.
There exist three ways in which a type is coerced to another type:
By declaring a variable.
var a: u8 = 1; var b: u16 = a;
By calling a function:
fn foo(b: u16) void { _ = b; } var a: u8 = 1; foo(a);
By using the
@as
builtin:var a: u8 = 1; var b = @as(u16, a);
Mutable to immutable
Non-constant types can be coerced to const
types, thereby increasing the strictness.
var a: i32 = 1; var b: *i32 = &a; var c: *const i32 = b;
Error subsets to supersets
Error sets can be coerced from a subset to a superset.
const FirstError = error { SomethingWentWrong, SomethingElseWentWrong, }; const SecondError = error { SomethingWentWrong }; fn foo(err: SecondError) FirstError { return err; } foo(SecondError.SomethingWentWrong)
Integer widening
Integers can be coerced to wider types, iff every value of the old type can be represented by the new type.
var a: u8 = 255; var b: u16 = a; var c: u32 = b; var d: u64 = c; var e: u128 = d;
Unsigned integer to signed integer
Unsigned integers can be coerced to signed integers, iff every value of the old type can be represented by the new type.
var a: u8 = 255; var b: i16 = a;
Float widening
Floats can be coerced to wider types, iff every value of the old type can be represented by the new type.
var a: f16 = 3.14; var b: f32 = a; var c: f64 = b; var d: f128 = c;
Single-item pointers to arrays to slices
Single-item pointers pointing to an array can be coerced to many-item pointers.
var x: [3]u8 = [3]u8{1, 2, 3}; const y: []const u8 = &arr;
Single-item pointers to arrays to many-item pointers
Single-item pointers pointing to an array can be coerced to many-item pointers.
var x: [3]u8 = [3]u8{1, 2, 3}; const y: [*]const u8 = &arr;
Single-item pointers to single-item arrays
Single-item pointers can be coerced to pointers pointing to an array of length 1.
var x: i32 = 1234; const y: *[1]i32 = &x;
Optionals
Payload types of optionals and null
coerce to optionals.
var x: ?i32 = 1234; var y: ?i32 = null;
Error unions
Payload types of error unions and errors coerce to error unions.
var x: SomeError!i32 = 1234; var y: SomeError!i32 = SomeError.Failure;
Compile-time known numbers
Compile-time numbers coerce to types for which is it known during comptime
that the number is representable in the new type.
const x: u64 = 255; const y: u8 = x;
Tagged union
to enum
Tagged unions coerce to enums:
const E = enum { a, b, c }; const U = union(E) { a: f32, b: f32 }; var u = U{ .a = 3.14 }; var e: E = u;
Enums to tagged unions
Enums coerce to tagged unions when it is known during comptime
that the tagged field has only one possible value.
const E = enum { a }; const U = union(E) { a }; const x = E.a; const y: U = x;
Zero Bit Types
Zero bit types (e.g. void
, u0
, i0
, etc.) coerce to single-item pointers.
var x: void = {}; var y: *void = x;
undefined
undefined
can be coerced to any type.