master
  1const builtin = @import("builtin");
  2const std = @import("std");
  3const expect = std.testing.expect;
  4
  5test "optional type" {
  6    const x: ?bool = true;
  7
  8    if (x) |y| {
  9        if (y) {
 10            // OK
 11        } else {
 12            unreachable;
 13        }
 14    } else {
 15        unreachable;
 16    }
 17
 18    const next_x: ?i32 = null;
 19
 20    const z = next_x orelse 1234;
 21
 22    try expect(z == 1234);
 23
 24    const final_x: ?i32 = 13;
 25
 26    const num = final_x orelse unreachable;
 27
 28    try expect(num == 13);
 29}
 30
 31test "test maybe object and get a pointer to the inner value" {
 32    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 33    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 34    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 35    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 36
 37    var maybe_bool: ?bool = true;
 38
 39    if (maybe_bool) |*b| {
 40        b.* = false;
 41    }
 42
 43    try expect(maybe_bool.? == false);
 44}
 45
 46test "rhs maybe unwrap return" {
 47    const x: ?bool = true;
 48    const y = x orelse return;
 49    _ = y;
 50}
 51
 52test "maybe return" {
 53    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 54    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 55
 56    try maybeReturnImpl();
 57    try comptime maybeReturnImpl();
 58}
 59
 60fn maybeReturnImpl() !void {
 61    try expect(foo(1235).?);
 62    if (foo(null) != null) unreachable;
 63    try expect(!foo(1234).?);
 64}
 65
 66fn foo(x: ?i32) ?bool {
 67    const value = x orelse return null;
 68    return value > 1234;
 69}
 70
 71test "test null runtime" {
 72    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 73    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 74
 75    try testTestNullRuntime(null);
 76}
 77fn testTestNullRuntime(x: ?i32) !void {
 78    try expect(x == null);
 79    try expect(!(x != null));
 80}
 81
 82test "optional void" {
 83    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 84    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 85
 86    try optionalVoidImpl();
 87    try comptime optionalVoidImpl();
 88}
 89
 90fn optionalVoidImpl() !void {
 91    try expect(bar(null) == null);
 92    try expect(bar({}) != null);
 93}
 94
 95fn bar(x: ?void) ?void {
 96    if (x) |_| {
 97        return {};
 98    } else {
 99        return null;
100    }
101}
102
103const Empty = struct {};
104
105test "optional struct{}" {
106    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
107    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
108
109    _ = try optionalEmptyStructImpl();
110    _ = try comptime optionalEmptyStructImpl();
111}
112
113fn optionalEmptyStructImpl() !void {
114    try expect(baz(null) == null);
115    try expect(baz(Empty{}) != null);
116}
117
118fn baz(x: ?Empty) ?Empty {
119    if (x) |_| {
120        return Empty{};
121    } else {
122        return null;
123    }
124}
125
126test "null with default unwrap" {
127    const x: i32 = null orelse 1;
128    try expect(x == 1);
129}
130
131test "optional pointer to 0 bit type null value at runtime" {
132    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
133    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
134
135    const EmptyStruct = struct {};
136    var x: ?*EmptyStruct = null;
137    _ = &x;
138    try expect(x == null);
139}
140
141test "if var maybe pointer" {
142    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
143    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
144    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
145    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
146
147    try expect(shouldBeAPlus1(Particle{
148        .a = 14,
149        .b = 1,
150        .c = 1,
151        .d = 1,
152    }) == 15);
153}
154fn shouldBeAPlus1(p: Particle) u64 {
155    var maybe_particle: ?Particle = p;
156    if (maybe_particle) |*particle| {
157        particle.a += 1;
158    }
159    if (maybe_particle) |particle| {
160        return particle.a;
161    }
162    return 0;
163}
164const Particle = struct {
165    a: u64,
166    b: u64,
167    c: u64,
168    d: u64,
169};
170
171test "null literal outside function" {
172    const is_null = here_is_a_null_literal.context == null;
173    try expect(is_null);
174
175    const is_non_null = here_is_a_null_literal.context != null;
176    try expect(!is_non_null);
177}
178
179const SillyStruct = struct {
180    context: ?i32,
181};
182
183const here_is_a_null_literal = SillyStruct{ .context = null };
184
185test "unwrap optional which is field of global var" {
186    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
187    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
188
189    struct_with_optional.field = null;
190    if (struct_with_optional.field) |payload| {
191        _ = payload;
192        unreachable;
193    }
194    struct_with_optional.field = 1234;
195    if (struct_with_optional.field) |payload| {
196        try expect(payload == 1234);
197    } else {
198        unreachable;
199    }
200}
201const StructWithOptional = struct {
202    field: ?i32,
203};
204
205var struct_with_optional: StructWithOptional = undefined;
206
207test "optional types" {
208    comptime {
209        const opt_type_struct = StructWithOptionalType{ .t = u8 };
210        try expect(opt_type_struct.t != null and opt_type_struct.t.? == u8);
211    }
212}
213
214const StructWithOptionalType = struct {
215    t: ?type,
216};