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};