Undefined Behavior

    When a safety check fails, Zig crashes with a stack trace, like this:

    test.zig

    1. Test 1/1 safety check...reached unreachable code
    2. /home/andy/dev/zig/docgen_tmp/test.zig:2:5: 0x2040d7 in ??? (test)
    3. unreachable;
    4. ^
    5. /home/andy/dev/zig/build/lib/zig/std/special/test_runner.zig:13:25: 0x225bab in ??? (test)
    6. if (test_fn.func()) |_| {
    7. ^
    8. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:122:22: 0x225336 in ??? (test)
    9. root.main() catch |err| {
    10. ^
    11. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:43:5: 0x2250a1 in ??? (test)
    12. @noInlineCall(posixCallMainAndExit);
    13. ^
    14. Tests failed. Use the following command to reproduce the failure:
    15. /home/andy/dev/zig/docgen_tmp/test

    At compile-time:

    test.zig

    1. comptime {
    2. assert(false);
    3. }
    4. fn assert(ok: bool) void {
    5. if (!ok) unreachable; // assertion failure
    6. }
    1. $ zig test test.zig
    2. /home/andy/dev/zig/docgen_tmp/test.zig:5:14: error: unable to evaluate constant expression
    3. if (!ok) unreachable; // assertion failure
    4. ^
    5. /home/andy/dev/zig/docgen_tmp/test.zig:2:11: note: called from here
    6. assert(false);
    7. ^
    8. /home/andy/dev/zig/docgen_tmp/test.zig:1:10: note: called from here
    9. comptime {
    10. ^

    At runtime:

    test.zig

    1. const std = @import("std");
    2. pub fn main() void {
    3. std.debug.assert(false);
    4. }
    1. $ zig build-exe test.zig
    2. $ ./test
    3. reached unreachable code
    4. /home/andy/dev/zig/build/lib/zig/std/debug.zig:169:14: 0x20402c in ??? (test)
    5. if (!ok) unreachable; // assertion failure
    6. ^
    7. /home/andy/dev/zig/docgen_tmp/test.zig:4:21: 0x22581b in ??? (test)
    8. std.debug.assert(false);
    9. ^
    10. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:112:22: 0x22528b in ??? (test)
    11. root.main();
    12. ^
    13. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:43:5: 0x225081 in ??? (test)
    14. @noInlineCall(posixCallMainAndExit);
    15. ^

    Index out of Bounds

    At compile-time:

    test.zig

    1. comptime {
    2. const array = "hello";
    3. const garbage = array[5];
    4. }
    1. $ zig test test.zig
    2. /home/andy/dev/zig/docgen_tmp/test.zig:3:26: error: index 5 outside array of size 5
    3. const garbage = array[5];
    4. ^

    At runtime:

    test.zig

    1. pub fn main() void {
    2. var x = foo("hello");
    3. }
    4. fn foo(x: []const u8) u8 {
    5. return x[5];
    6. }
    1. $ zig build-exe test.zig
    2. $ ./test
    3. index out of bounds
    4. /home/andy/dev/zig/docgen_tmp/test.zig:6:13: 0x22585a in ??? (test)
    5. return x[5];
    6. ^
    7. /home/andy/dev/zig/docgen_tmp/test.zig:2:16: 0x225827 in ??? (test)
    8. var x = foo("hello");
    9. ^
    10. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:112:22: 0x22528b in ??? (test)
    11. root.main();
    12. ^
    13. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:43:5: 0x225081 in ??? (test)
    14. @noInlineCall(posixCallMainAndExit);
    15. ^

    Cast Negative Number to Unsigned Integer

    At compile-time:

    test.zig

    1. comptime {
    2. const value: i32 = -1;
    3. const unsigned = @intCast(u32, value);
    4. }
    1. $ zig test test.zig
    2. /home/andy/dev/zig/docgen_tmp/test.zig:3:36: error: cannot cast negative value -1 to unsigned integer type 'u32'
    3. const unsigned = @intCast(u32, value);
    4. ^

    At runtime:

    test.zig

    1. const std = @import("std");
    2. pub fn main() void {
    3. var value: i32 = -1;
    4. var unsigned = @intCast(u32, value);
    5. std.debug.warn("value: {}\n", unsigned);
    6. }
    1. $ zig build-exe test.zig
    2. $ ./test
    3. attempt to cast negative value to unsigned integer
    4. /home/andy/dev/zig/docgen_tmp/test.zig:5:20: 0x225851 in ??? (test)
    5. var unsigned = @intCast(u32, value);
    6. ^
    7. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:112:22: 0x22528b in ??? (test)
    8. root.main();
    9. ^
    10. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:43:5: 0x225081 in ??? (test)
    11. @noInlineCall(posixCallMainAndExit);
    12. ^

    To obtain the maximum value of an unsigned integer, use std.math.maxInt.

    Cast Truncates Data

    At compile-time:

    test.zig

    1. comptime {
    2. const spartan_count: u16 = 300;
    3. const byte = @intCast(u8, spartan_count);
    4. }
    1. $ zig test test.zig
    2. /home/andy/dev/zig/docgen_tmp/test.zig:3:31: error: integer value 300 cannot be implicitly casted to type 'u8'
    3. const byte = @intCast(u8, spartan_count);
    4. ^

    At runtime:

    test.zig

    1. const std = @import("std");
    2. pub fn main() void {
    3. var spartan_count: u16 = 300;
    4. const byte = @intCast(u8, spartan_count);
    5. std.debug.warn("value: {}\n", byte);
    6. }
    1. $ zig build-exe test.zig
    2. $ ./test
    3. integer cast truncated bits
    4. /home/andy/dev/zig/docgen_tmp/test.zig:5:18: 0x22585a in ??? (test)
    5. const byte = @intCast(u8, spartan_count);
    6. ^
    7. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:112:22: 0x22528b in ??? (test)
    8. root.main();
    9. ^
    10. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:43:5: 0x225081 in ??? (test)
    11. @noInlineCall(posixCallMainAndExit);
    12. ^

    To truncate bits, use .

    Integer Overflow

    The following operators can cause integer overflow:

    • + (addition)
    • - (subtraction)
    • - (negation)
    • * (multiplication)
    • / (division)
    • @divTrunc (division)
    • (division)
    • @divExact (division)

    Example with addition at compile-time:

    test.zig

    1. comptime {
    2. var byte: u8 = 255;
    3. byte += 1;
    4. }
    1. $ zig test test.zig
    2. /home/andy/dev/zig/docgen_tmp/test.zig:3:10: error: operation caused overflow
    3. byte += 1;
    4. ^

    At runtime:

    test.zig

    1. const std = @import("std");
    2. pub fn main() void {
    3. var byte: u8 = 255;
    4. byte += 1;
    5. std.debug.warn("value: {}\n", byte);
    6. }
    1. $ zig build-exe test.zig
    2. $ ./test
    3. integer overflow
    4. /home/andy/dev/zig/docgen_tmp/test.zig:5:10: 0x225841 in ??? (test)
    5. byte += 1;
    6. ^
    7. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:112:22: 0x22528b in ??? (test)
    8. root.main();
    9. ^
    10. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:43:5: 0x225081 in ??? (test)
    11. @noInlineCall(posixCallMainAndExit);
    12. ^

    These functions provided by the standard library return possible errors.

    • @import("std").math.add
    • @import("std").math.sub
    • @import("std").math.mul
    • @import("std").math.divTrunc
    • @import("std").math.divFloor
    • @import("std").math.divExact
    • @import("std").math.shl

    Example of catching an overflow for addition:

    test.zig

    1. const math = @import("std").math;
    2. const warn = @import("std").debug.warn;
    3. pub fn main() !void {
    4. var byte: u8 = 255;
    5. byte = if (math.add(u8, byte, 1)) |result| result else |err| {
    6. warn("unable to add one: {}\n", @errorName(err));
    7. return err;
    8. };
    9. warn("result: {}\n", byte);
    10. }
    1. $ zig build-exe test.zig
    2. $ ./test
    3. unable to add one: Overflow
    4. error: Overflow
    5. /home/andy/dev/zig/build/lib/zig/std/math.zig:268:5: 0x225c4e in ??? (test)
    6. return if (@addWithOverflow(T, a, b, &answer)) error.Overflow else answer;
    7. ^
    8. /home/andy/dev/zig/docgen_tmp/test.zig:8:9: 0x225a3e in ??? (test)
    9. return err;
    10. ^

    These builtins return a bool of whether or not overflow occurred, as well as returning the overflowed bits:

    Example of :

    test.zig

    1. const warn = @import("std").debug.warn;
    2. pub fn main() void {
    3. var byte: u8 = 255;
    4. var result: u8 = undefined;
    5. if (@addWithOverflow(u8, byte, 10, &result)) {
    6. warn("overflowed result: {}\n", result);
    7. } else {
    8. warn("result: {}\n", result);
    9. }
    10. }
    1. $ zig build-exe test.zig
    2. $ ./test
    3. overflowed result: 9

    These operations have guaranteed wraparound semantics.

    • +% (wraparound addition)
    • -% (wraparound subtraction)
    • -% (wraparound negation)
    • *% (wraparound multiplication)

    test.zig

    1. const std = @import("std");
    2. const assert = std.debug.assert;
    3. const minInt = std.math.minInt;
    4. const maxInt = std.math.maxInt;
    5. test "wraparound addition and subtraction" {
    6. const x: i32 = maxInt(i32);
    7. const min_val = x +% 1;
    8. const max_val = min_val -% 1;
    9. assert(max_val == maxInt(i32));
    10. }
    1. $ zig test test.zig
    2. Test 1/1 wraparound addition and subtraction...OK
    3. All tests passed.

    Exact Left Shift Overflow

    test.zig

    1. comptime {
    2. const x = @shlExact(u8(0b01010101), 2);
    3. }
    1. $ zig test test.zig
    2. /home/andy/dev/zig/docgen_tmp/test.zig:2:15: error: operation caused overflow
    3. const x = @shlExact(u8(0b01010101), 2);
    4. ^

    At runtime:

    test.zig

    1. $ zig build-exe test.zig
    2. $ ./test
    3. left shift overflowed bits
    4. /home/andy/dev/zig/docgen_tmp/test.zig:5:13: 0x225858 in ??? (test)
    5. var y = @shlExact(x, 2);
    6. ^
    7. root.main();
    8. ^
    9. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:43:5: 0x225081 in ??? (test)
    10. @noInlineCall(posixCallMainAndExit);
    11. ^

    At compile-time:

    test.zig

    1. comptime {
    2. const x = @shrExact(u8(0b10101010), 2);
    3. }
    1. $ zig test test.zig
    2. /home/andy/dev/zig/docgen_tmp/test.zig:2:15: error: exact shift shifted out 1 bits
    3. const x = @shrExact(u8(0b10101010), 2);
    4. ^

    At runtime:

    test.zig

    1. const std = @import("std");
    2. pub fn main() void {
    3. var x: u8 = 0b10101010;
    4. var y = @shrExact(x, 2);
    5. std.debug.warn("value: {}\n", y);
    6. }
    1. $ zig build-exe test.zig
    2. $ ./test
    3. right shift overflowed bits
    4. /home/andy/dev/zig/docgen_tmp/test.zig:5:13: 0x225858 in ??? (test)
    5. var y = @shrExact(x, 2);
    6. ^
    7. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:112:22: 0x22528b in ??? (test)
    8. root.main();
    9. ^
    10. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:43:5: 0x225081 in ??? (test)
    11. @noInlineCall(posixCallMainAndExit);
    12. ^

    Division by Zero

    At compile-time:

    test.zig

    1. comptime {
    2. const a: i32 = 1;
    3. const b: i32 = 0;
    4. const c = a / b;
    5. }
    1. $ zig test test.zig
    2. /home/andy/dev/zig/docgen_tmp/test.zig:4:17: error: division by zero
    3. const c = a / b;
    4. ^

    At runtime:

    test.zig

    1. const std = @import("std");
    2. pub fn main() void {
    3. var a: u32 = 1;
    4. var b: u32 = 0;
    5. var c = a / b;
    6. std.debug.warn("value: {}\n", c);
    7. }
    1. $ zig build-exe test.zig
    2. $ ./test
    3. division by zero
    4. /home/andy/dev/zig/docgen_tmp/test.zig:6:15: 0x22584a in ??? (test)
    5. var c = a / b;
    6. ^
    7. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:112:22: 0x22528b in ??? (test)
    8. root.main();
    9. ^
    10. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:43:5: 0x225081 in ??? (test)
    11. @noInlineCall(posixCallMainAndExit);
    12. ^

    Remainder Division by Zero

    At compile-time:

    test.zig

    1. comptime {
    2. const a: i32 = 10;
    3. const b: i32 = 0;
    4. const c = a % b;
    5. }
    1. $ zig test test.zig
    2. /home/andy/dev/zig/docgen_tmp/test.zig:4:17: error: division by zero
    3. const c = a % b;
    4. ^

    At runtime:

    test.zig

    1. const std = @import("std");
    2. pub fn main() void {
    3. var a: u32 = 10;
    4. var b: u32 = 0;
    5. var c = a % b;
    6. std.debug.warn("value: {}\n", c);
    7. }
    1. $ zig build-exe test.zig
    2. $ ./test
    3. remainder division by zero or negative value
    4. /home/andy/dev/zig/docgen_tmp/test.zig:6:15: 0x225865 in ??? (test)
    5. var c = a % b;
    6. ^
    7. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:112:22: 0x22528b in ??? (test)
    8. root.main();
    9. ^
    10. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:43:5: 0x225081 in ??? (test)
    11. @noInlineCall(posixCallMainAndExit);
    12. ^

    Exact Division Remainder

    At compile-time:

    test.zig

    1. comptime {
    2. const a: u32 = 10;
    3. const b: u32 = 3;
    4. const c = @divExact(a, b);
    5. }
    1. $ zig test test.zig
    2. /home/andy/dev/zig/docgen_tmp/test.zig:4:15: error: exact division had a remainder
    3. const c = @divExact(a, b);
    4. ^

    At runtime:

    test.zig

    1. const std = @import("std");
    2. pub fn main() void {
    3. var a: u32 = 10;
    4. var b: u32 = 3;
    5. var c = @divExact(a, b);
    6. std.debug.warn("value: {}\n", c);
    7. }
    1. $ zig build-exe test.zig
    2. $ ./test
    3. exact division produced remainder
    4. /home/andy/dev/zig/docgen_tmp/test.zig:6:13: 0x225887 in ??? (test)
    5. var c = @divExact(a, b);
    6. ^
    7. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:112:22: 0x22528b in ??? (test)
    8. root.main();
    9. ^
    10. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:43:5: 0x225081 in ??? (test)
    11. @noInlineCall(posixCallMainAndExit);
    12. ^

    Slice Widen Remainder

    At compile-time:

    test.zig

    1. comptime {
    2. var bytes = [5]u8{ 1, 2, 3, 4, 5 };
    3. var slice = @bytesToSlice(u32, bytes);
    4. }
    1. $ zig test test.zig
    2. /home/andy/dev/zig/docgen_tmp/test.zig:3:17: error: unable to convert [5]u8 to []align(1) const u32: size mismatch
    3. var slice = @bytesToSlice(u32, bytes);
    4. ^
    5. /home/andy/dev/zig/docgen_tmp/test.zig:3:31: note: u32 has size 4; remaining bytes: 1
    6. var slice = @bytesToSlice(u32, bytes);
    7. ^

    At runtime:

    test.zig

    1. const std = @import("std");
    2. pub fn main() void {
    3. var bytes = [5]u8{ 1, 2, 3, 4, 5 };
    4. var slice = @bytesToSlice(u32, bytes[0..]);
    5. std.debug.warn("value: {}\n", slice[0]);
    6. }
    1. $ zig build-exe test.zig
    2. $ ./test
    3. slice widening size mismatch
    4. /home/andy/dev/zig/docgen_tmp/test.zig:5:17: 0x2258ae in ??? (test)
    5. var slice = @bytesToSlice(u32, bytes[0..]);
    6. ^
    7. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:112:22: 0x22528b in ??? (test)
    8. root.main();
    9. ^
    10. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:43:5: 0x225081 in ??? (test)
    11. @noInlineCall(posixCallMainAndExit);
    12. ^

    Attempt to Unwrap Null

    At compile-time:

    test.zig

    1. comptime {
    2. const optional_number: ?i32 = null;
    3. const number = optional_number.?;
    4. }
    1. $ zig test test.zig
    2. /home/andy/dev/zig/docgen_tmp/test.zig:3:35: error: unable to unwrap null
    3. const number = optional_number.?;
    4. ^

    At runtime:

    test.zig

    1. const std = @import("std");
    2. pub fn main() void {
    3. var optional_number: ?i32 = null;
    4. var number = optional_number.?;
    5. std.debug.warn("value: {}\n", number);
    6. }
    1. $ zig build-exe test.zig
    2. $ ./test
    3. attempt to unwrap null
    4. /home/andy/dev/zig/docgen_tmp/test.zig:5:33: 0x225853 in ??? (test)
    5. var number = optional_number.?;
    6. ^
    7. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:112:22: 0x22528b in ??? (test)
    8. root.main();
    9. ^
    10. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:43:5: 0x225081 in ??? (test)
    11. @noInlineCall(posixCallMainAndExit);
    12. ^

    One way to avoid this crash is to test for null instead of assuming non-null, with the if expression:

    test.zig

    1. const warn = @import("std").debug.warn;
    2. pub fn main() void {
    3. const optional_number: ?i32 = null;
    4. if (optional_number) |number| {
    5. warn("got number: {}\n", number);
    6. } else {
    7. warn("it's null\n");
    8. }
    9. }
    1. $ zig build-exe test.zig
    2. $ ./test
    3. it's null

    See also:

    At compile-time:

    test.zig

    1. comptime {
    2. const number = getNumberOrFail() catch unreachable;
    3. }
    4. fn getNumberOrFail() !i32 {
    5. return error.UnableToReturnNumber;
    6. }
    1. $ zig test test.zig
    2. /home/andy/dev/zig/docgen_tmp/test.zig:2:38: error: caught unexpected error 'UnableToReturnNumber'
    3. const number = getNumberOrFail() catch unreachable;
    4. ^

    At runtime:

    1. $ zig build-exe test.zig
    2. $ ./test
    3. attempt to unwrap error: UnableToReturnNumber
    4. /home/andy/dev/zig/docgen_tmp/test.zig:9:5: 0x2258bb in ??? (test)
    5. return error.UnableToReturnNumber;
    6. ^
    7. ???:?:?: 0x225948 in ??? (???)
    8. /home/andy/dev/zig/docgen_tmp/test.zig:4:38: 0x22587c in ??? (test)
    9. const number = getNumberOrFail() catch unreachable;
    10. ^
    11. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:112:22: 0x22528b in ??? (test)
    12. root.main();
    13. ^
    14. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:43:5: 0x225081 in ??? (test)
    15. @noInlineCall(posixCallMainAndExit);
    16. ^

    One way to avoid this crash is to test for an error instead of assuming a successful result, with the if expression:

    test.zig

    1. const warn = @import("std").debug.warn;
    2. pub fn main() void {
    3. const result = getNumberOrFail();
    4. if (result) |number| {
    5. warn("got number: {}\n", number);
    6. } else |err| {
    7. warn("got error: {}\n", @errorName(err));
    8. }
    9. }
    10. fn getNumberOrFail() !i32 {
    11. return error.UnableToReturnNumber;
    12. }
    1. $ zig build-exe test.zig
    2. $ ./test

    See also:

    Invalid Error Code

    At compile-time:

    test.zig

    1. comptime {
    2. const err = error.AnError;
    3. const number = @errorToInt(err) + 10;
    4. const invalid_err = @intToError(number);
    5. }
    1. $ zig test test.zig
    2. /home/andy/dev/zig/docgen_tmp/test.zig:4:25: error: integer value 11 represents no error
    3. const invalid_err = @intToError(number);

    At runtime:

    test.zig

    1. const std = @import("std");
    2. pub fn main() void {
    3. var err = error.AnError;
    4. var number = @errorToInt(err) + 500;
    5. var invalid_err = @intToError(number);
    6. std.debug.warn("value: {}\n", number);
    7. }
    1. $ zig build-exe test.zig
    2. $ ./test
    3. invalid error code
    4. /home/andy/dev/zig/docgen_tmp/test.zig:6:23: 0x22586d in ??? (test)
    5. var invalid_err = @intToError(number);
    6. ^
    7. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:112:22: 0x22528b in ??? (test)
    8. root.main();
    9. ^
    10. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:43:5: 0x225081 in ??? (test)
    11. @noInlineCall(posixCallMainAndExit);
    12. ^

    Invalid Enum Cast

    At compile-time:

    test.zig

    1. const Foo = enum {
    2. A,
    3. B,
    4. C,
    5. };
    6. comptime {
    7. const a: u2 = 3;
    8. const b = @intToEnum(Foo, a);
    9. }
    1. $ zig test test.zig
    2. /home/andy/dev/zig/docgen_tmp/test.zig:8:15: error: enum 'Foo' has no tag matching integer value 3
    3. const b = @intToEnum(Foo, a);
    4. ^
    5. /home/andy/dev/zig/docgen_tmp/test.zig:1:13: note: 'Foo' declared here
    6. const Foo = enum {
    7. ^

    At runtime:

    test.zig

    1. const std = @import("std");
    2. const Foo = enum {
    3. A,
    4. B,
    5. C,
    6. };
    7. pub fn main() void {
    8. var a: u2 = 3;
    9. var b = @intToEnum(Foo, a);
    10. std.debug.warn("value: {}\n", @tagName(b));
    11. }
    1. $ zig build-exe test.zig
    2. $ ./test
    3. invalid enum value
    4. /home/andy/dev/zig/docgen_tmp/test.zig:11:13: 0x225850 in ??? (test)
    5. var b = @intToEnum(Foo, a);
    6. ^
    7. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:112:22: 0x22528b in ??? (test)
    8. root.main();
    9. ^
    10. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:43:5: 0x225081 in ??? (test)
    11. @noInlineCall(posixCallMainAndExit);
    12. ^

    Invalid Error Set Cast

    At compile-time:

    test.zig

    1. const Set1 = error{
    2. A,
    3. B,
    4. };
    5. const Set2 = error{
    6. A,
    7. C,
    8. };
    9. comptime {
    10. _ = @errSetCast(Set2, Set1.B);
    11. }
    1. $ zig test test.zig
    2. /home/andy/dev/zig/docgen_tmp/test.zig:10:9: error: error.B not a member of error set 'Set2'
    3. _ = @errSetCast(Set2, Set1.B);
    4. ^

    At runtime:

    test.zig

    1. const std = @import("std");
    2. const Set1 = error{
    3. A,
    4. B,
    5. };
    6. const Set2 = error{
    7. A,
    8. C,
    9. };
    10. pub fn main() void {
    11. foo(Set1.B);
    12. }
    13. fn foo(set1: Set1) void {
    14. const x = @errSetCast(Set2, set1);
    15. std.debug.warn("value: {}\n", x);
    16. }
    1. $ zig build-exe test.zig
    2. $ ./test
    3. invalid error code
    4. /home/andy/dev/zig/docgen_tmp/test.zig:15:15: 0x225880 in ??? (test)
    5. const x = @errSetCast(Set2, set1);
    6. ^
    7. /home/andy/dev/zig/docgen_tmp/test.zig:12:8: 0x22581e in ??? (test)
    8. foo(Set1.B);
    9. ^
    10. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:112:22: 0x22528b in ??? (test)
    11. root.main();
    12. ^
    13. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:43:5: 0x225081 in ??? (test)
    14. @noInlineCall(posixCallMainAndExit);
    15. ^

    Incorrect Pointer Alignment

    At compile-time:

    test.zig

    1. comptime {
    2. const ptr = @intToPtr(*i32, 0x1);
    3. const aligned = @alignCast(4, ptr);
    4. }
    1. $ zig test test.zig
    2. /home/andy/dev/zig/docgen_tmp/test.zig:3:35: error: pointer address 0x1 is not aligned to 4 bytes
    3. const aligned = @alignCast(4, ptr);
    4. ^

    At runtime:

    test.zig

    1. pub fn main() !void {
    2. var array align(4) = []u32{ 0x11111111, 0x11111111 };
    3. const bytes = @sliceToBytes(array[0..]);
    4. if (foo(bytes) != 0x11111111) return error.Wrong;
    5. }
    6. fn foo(bytes: []u8) u32 {
    7. const slice4 = bytes[1..5];
    8. const int_slice = @bytesToSlice(u32, @alignCast(4, slice4));
    9. return int_slice[0];
    10. }
    1. $ zig build-exe test.zig
    2. $ ./test
    3. incorrect alignment
    4. /home/andy/dev/zig/docgen_tmp/test.zig:8:56: 0x225be6 in ??? (test)
    5. const int_slice = @bytesToSlice(u32, @alignCast(4, slice4));
    6. ^
    7. /home/andy/dev/zig/docgen_tmp/test.zig:4:12: 0x225a22 in ??? (test)
    8. if (foo(bytes) != 0x11111111) return error.Wrong;
    9. ^
    10. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:122:22: 0x225316 in ??? (test)
    11. root.main() catch |err| {
    12. ^
    13. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:43:5: 0x225081 in ??? (test)
    14. @noInlineCall(posixCallMainAndExit);
    15. ^

    Wrong Union Field Access

    At compile-time:

    test.zig

    1. comptime {
    2. var f = Foo{ .int = 42 };
    3. f.float = 12.34;
    4. }
    5. const Foo = union {
    6. float: f32,
    7. int: u32,
    8. };
    1. $ zig test test.zig
    2. /home/andy/dev/zig/docgen_tmp/test.zig:3:6: error: accessing union field 'float' while field 'int' is set
    3. f.float = 12.34;
    4. ^

    At runtime:

    test.zig

    1. const std = @import("std");
    2. const Foo = union {
    3. float: f32,
    4. int: u32,
    5. };
    6. pub fn main() void {
    7. var f = Foo{ .int = 42 };
    8. bar(&f);
    9. }
    10. fn bar(f: *Foo) void {
    11. f.float = 12.34;
    12. std.debug.warn("value: {}\n", f.float);
    13. }
    1. $ zig build-exe test.zig
    2. $ ./test
    3. access of inactive union field
    4. /home/andy/dev/zig/docgen_tmp/test.zig:14:6: 0x22c88b in ??? (test)
    5. f.float = 12.34;
    6. ^
    7. /home/andy/dev/zig/docgen_tmp/test.zig:10:8: 0x22c82d in ??? (test)
    8. bar(&f);
    9. ^
    10. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:112:22: 0x22c28b in ??? (test)
    11. root.main();
    12. ^
    13. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:43:5: 0x22c081 in ??? (test)
    14. @noInlineCall(posixCallMainAndExit);
    15. ^

    This safety is not available for extern or packed unions.

    To change the active field of a union, assign the entire union, like this:

    test.zig

    1. const std = @import("std");
    2. const Foo = union {
    3. float: f32,
    4. int: u32,
    5. };
    6. pub fn main() void {
    7. var f = Foo{ .int = 42 };
    8. bar(&f);
    9. }
    10. fn bar(f: *Foo) void {
    11. f.* = Foo{ .float = 12.34 };
    12. std.debug.warn("value: {}\n", f.float);
    13. }
    1. $ zig build-exe test.zig
    2. $ ./test
    3. value: 1.23400001e+01

    To change the active field of a union when a meaningful value for the field is not known, use undefined, like this:

    test.zig

    1. const std = @import("std");
    2. const Foo = union {
    3. float: f32,
    4. int: u32,
    5. };
    6. pub fn main() void {
    7. var f = Foo{ .int = 42 };
    8. f = Foo{ .float = undefined };
    9. bar(&f);
    10. std.debug.warn("value: {}\n", f.float);
    11. }
    12. fn bar(f: *Foo) void {
    13. f.float = 12.34;
    14. }
    1. $ zig build-exe test.zig
    2. $ ./test
    3. value: 1.23400001e+01

    See also:

    TODO

    Pointer Cast Invalid Null

    This happens when casting a pointer with the address 0 to a pointer which may not have the address 0. For example, , Optional Pointers, and pointers allow address zero, but normal Pointers do not.

    At compile-time:

    test.zig

    1. comptime {
    2. const opt_ptr: ?*i32 = null;
    3. const ptr = @ptrCast(*i32, opt_ptr);
    4. }
    1. $ zig test test.zig
    2. /home/andy/dev/zig/docgen_tmp/test.zig:3:17: error: null pointer casted to type '*i32'
    3. const ptr = @ptrCast(*i32, opt_ptr);
    4. ^

    test.zig

    1. $ zig build-exe test.zig
    2. $ ./test
    3. cast causes pointer to be null
    4. /home/andy/dev/zig/docgen_tmp/test.zig:3:15: 0x225841 in ??? (test)
    5. var ptr = @ptrCast(*i32, opt_ptr);
    6. ^
    7. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:112:22: 0x22528b in ??? (test)
    8. root.main();
    9. ^
    10. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:43:5: 0x225081 in ??? (test)
    11. @noInlineCall(posixCallMainAndExit);