master
1const builtin = @import("builtin");
2const std = @import("std");
3const expect = std.testing.expect;
4const expectEqual = std.testing.expectEqual;
5
6test "if statements" {
7 shouldBeEqual(1, 1);
8 firstEqlThird(2, 1, 2);
9}
10fn shouldBeEqual(a: i32, b: i32) void {
11 if (a != b) {
12 unreachable;
13 } else {
14 return;
15 }
16}
17fn firstEqlThird(a: i32, b: i32, c: i32) void {
18 if (a == b) {
19 unreachable;
20 } else if (b == c) {
21 unreachable;
22 } else if (a == c) {
23 return;
24 } else {
25 unreachable;
26 }
27}
28
29test "else if expression" {
30 try expect(elseIfExpressionF(1) == 1);
31}
32fn elseIfExpressionF(c: u8) u8 {
33 if (c == 0) {
34 return 0;
35 } else if (c == 1) {
36 return 1;
37 } else {
38 return @as(u8, 2);
39 }
40}
41
42// #2297
43var global_with_val: anyerror!u32 = 0;
44var global_with_err: anyerror!u32 = error.SomeError;
45
46test "unwrap mutable global var" {
47 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
48
49 if (global_with_val) |v| {
50 try expect(v == 0);
51 } else |_| {
52 unreachable;
53 }
54 if (global_with_err) |_| {
55 unreachable;
56 } else |e| {
57 try expect(e == error.SomeError);
58 }
59}
60
61test "labeled break inside comptime if inside runtime if" {
62 var answer: i32 = 0;
63 var c = true;
64 _ = &c;
65 if (c) {
66 answer = if (true) blk: {
67 break :blk @as(i32, 42);
68 };
69 }
70 try expect(answer == 42);
71}
72
73test "const result loc, runtime if cond, else unreachable" {
74 const Num = enum { One, Two };
75
76 var t = true;
77 _ = &t;
78 const x = if (t) Num.Two else unreachable;
79 try expect(x == .Two);
80}
81
82test "if copies its payload" {
83 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
84 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
85
86 const S = struct {
87 fn doTheTest() !void {
88 var tmp: ?i32 = 10;
89 if (tmp) |value| {
90 // Modify the original variable
91 tmp = null;
92 try expect(value == 10);
93 } else unreachable;
94 }
95 };
96 try S.doTheTest();
97 try comptime S.doTheTest();
98}
99
100test "if prongs cast to expected type instead of peer type resolution" {
101 const S = struct {
102 fn doTheTest(f: bool) !void {
103 var x: i32 = 0;
104 x = if (f) 1 else 2;
105 try expect(x == 2);
106
107 var b = true;
108 _ = &b;
109 const y: i32 = if (b) 1 else 2;
110 try expect(y == 1);
111 }
112 };
113 try S.doTheTest(false);
114 try comptime S.doTheTest(false);
115}
116
117test "if peer expressions inferred optional type" {
118 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
119 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
120 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
121
122 var self: []const u8 = "abcdef";
123 var index: usize = 0;
124 _ = .{ &self, &index };
125 const left_index = (index << 1) + 1;
126 const right_index = left_index + 1;
127 const left = if (left_index < self.len) self[left_index] else null;
128 const right = if (right_index < self.len) self[right_index] else null;
129 try expect(left_index < self.len);
130 try expect(right_index < self.len);
131 try expect(left.? == 98);
132 try expect(right.? == 99);
133}
134
135test "if-else expression with runtime condition result location is inferred optional" {
136 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
137 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
138
139 const A = struct { b: u64, c: u64 };
140 var d: bool = true;
141 _ = &d;
142 const e = if (d) A{ .b = 15, .c = 30 } else null;
143 try expect(e != null);
144}
145
146test "result location with inferred type ends up being pointer to comptime_int" {
147 var a: ?u32 = 1234;
148 var b: u32 = 2000;
149 _ = .{ &a, &b };
150 const c = if (a) |d| blk: {
151 if (d < b) break :blk @as(u32, 1);
152 break :blk 0;
153 } else @as(u32, 0);
154 try expect(c == 1);
155}
156
157test "if-@as-if chain" {
158 var fast = true;
159 var very_fast = false;
160 _ = .{ &fast, &very_fast };
161
162 const num_frames = if (fast)
163 @as(u32, if (very_fast) 16 else 4)
164 else
165 1;
166
167 try expect(num_frames == 4);
168}
169
170fn returnTrue() bool {
171 return true;
172}
173
174test "if value shouldn't be load-elided if used later (structs)" {
175 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
176
177 const Foo = struct { x: i32 };
178
179 var a = Foo{ .x = 1 };
180 var b = Foo{ .x = 1 };
181
182 const c = if (@call(.never_inline, returnTrue, .{})) a else b;
183 // The second variable is superfluous with the current
184 // state of codegen optimizations, but in future
185 // "if (smthg) a else a" may be optimized simply into "a".
186
187 a.x = 2;
188 b.x = 3;
189
190 try std.testing.expectEqual(c.x, 1);
191}
192
193test "if value shouldn't be load-elided if used later (optionals)" {
194 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
195
196 var a: ?i32 = 1;
197 var b: ?i32 = 1;
198
199 const c = if (@call(.never_inline, returnTrue, .{})) a else b;
200
201 a = 2;
202 b = 3;
203
204 try std.testing.expectEqual(c, 1);
205}
206
207test "variable type inferred from if expression" {
208 var a = if (true) {
209 return;
210 } else true;
211 _ = &a;
212 return error.TestFailed;
213}