2022-01-25 23:29:02 -07:00
|
|
|
const builtin = @import("builtin");
|
2020-02-14 15:56:34 +01:00
|
|
|
const std = @import("std");
|
|
|
|
|
const expect = std.testing.expect;
|
|
|
|
|
const expectEqual = std.testing.expectEqual;
|
2017-01-05 03:57:48 -05:00
|
|
|
|
2017-09-09 22:53:32 -04:00
|
|
|
test "if statements" {
|
2016-12-22 00:20:14 -05:00
|
|
|
shouldBeEqual(1, 1);
|
|
|
|
|
firstEqlThird(2, 1, 2);
|
|
|
|
|
}
|
2018-01-25 04:10:11 -05:00
|
|
|
fn shouldBeEqual(a: i32, b: i32) void {
|
2016-12-22 00:20:14 -05:00
|
|
|
if (a != b) {
|
2017-03-26 04:58:48 -04:00
|
|
|
unreachable;
|
2016-12-22 00:20:14 -05:00
|
|
|
} else {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-01-25 04:10:11 -05:00
|
|
|
fn firstEqlThird(a: i32, b: i32, c: i32) void {
|
2016-12-22 00:20:14 -05:00
|
|
|
if (a == b) {
|
2017-03-26 04:58:48 -04:00
|
|
|
unreachable;
|
2016-12-22 00:20:14 -05:00
|
|
|
} else if (b == c) {
|
2017-03-26 04:58:48 -04:00
|
|
|
unreachable;
|
2016-12-22 00:20:14 -05:00
|
|
|
} else if (a == c) {
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
2017-03-26 04:58:48 -04:00
|
|
|
unreachable;
|
2016-12-22 00:20:14 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-09 22:53:32 -04:00
|
|
|
test "else if expression" {
|
2021-05-04 21:23:22 +03:00
|
|
|
try expect(elseIfExpressionF(1) == 1);
|
2016-12-22 01:42:30 -05:00
|
|
|
}
|
2018-01-25 04:10:11 -05:00
|
|
|
fn elseIfExpressionF(c: u8) u8 {
|
2016-12-22 01:42:30 -05:00
|
|
|
if (c == 0) {
|
2017-12-22 00:50:30 -05:00
|
|
|
return 0;
|
2016-12-22 01:42:30 -05:00
|
|
|
} else if (c == 1) {
|
2017-12-22 00:50:30 -05:00
|
|
|
return 1;
|
2016-12-22 01:42:30 -05:00
|
|
|
} else {
|
2019-11-06 23:25:57 -05:00
|
|
|
return @as(u8, 2);
|
2016-12-22 01:42:30 -05:00
|
|
|
}
|
|
|
|
|
}
|
2019-05-14 23:30:31 +02:00
|
|
|
|
|
|
|
|
// #2297
|
|
|
|
|
var global_with_val: anyerror!u32 = 0;
|
|
|
|
|
var global_with_err: anyerror!u32 = error.SomeError;
|
|
|
|
|
|
|
|
|
|
test "unwrap mutable global var" {
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2022-02-22 14:15:09 +01:00
|
|
|
|
2019-05-14 23:30:31 +02:00
|
|
|
if (global_with_val) |v| {
|
2021-05-04 21:23:22 +03:00
|
|
|
try expect(v == 0);
|
2021-06-19 21:10:22 -04:00
|
|
|
} else |_| {
|
2019-05-14 23:30:31 +02:00
|
|
|
unreachable;
|
|
|
|
|
}
|
|
|
|
|
if (global_with_err) |_| {
|
|
|
|
|
unreachable;
|
|
|
|
|
} else |e| {
|
2021-05-04 21:23:22 +03:00
|
|
|
try expect(e == error.SomeError);
|
2019-05-14 23:30:31 +02:00
|
|
|
}
|
|
|
|
|
}
|
2019-06-19 23:39:49 -04:00
|
|
|
|
|
|
|
|
test "labeled break inside comptime if inside runtime if" {
|
|
|
|
|
var answer: i32 = 0;
|
|
|
|
|
var c = true;
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = &c;
|
2019-06-19 23:39:49 -04:00
|
|
|
if (c) {
|
|
|
|
|
answer = if (true) blk: {
|
2019-11-06 23:25:57 -05:00
|
|
|
break :blk @as(i32, 42);
|
2019-06-19 23:39:49 -04:00
|
|
|
};
|
|
|
|
|
}
|
2021-05-04 21:23:22 +03:00
|
|
|
try expect(answer == 42);
|
2019-06-19 23:39:49 -04:00
|
|
|
}
|
2021-10-02 19:09:54 -07:00
|
|
|
|
|
|
|
|
test "const result loc, runtime if cond, else unreachable" {
|
|
|
|
|
const Num = enum { One, Two };
|
|
|
|
|
|
|
|
|
|
var t = true;
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = &t;
|
2021-10-02 19:09:54 -07:00
|
|
|
const x = if (t) Num.Two else unreachable;
|
|
|
|
|
try expect(x == .Two);
|
|
|
|
|
}
|
2021-10-28 17:23:02 -07:00
|
|
|
|
|
|
|
|
test "if copies its payload" {
|
2022-02-22 14:15:09 +01:00
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2022-02-22 14:15:09 +01:00
|
|
|
|
2021-10-28 17:23:02 -07:00
|
|
|
const S = struct {
|
|
|
|
|
fn doTheTest() !void {
|
|
|
|
|
var tmp: ?i32 = 10;
|
|
|
|
|
if (tmp) |value| {
|
|
|
|
|
// Modify the original variable
|
|
|
|
|
tmp = null;
|
|
|
|
|
try expect(value == 10);
|
|
|
|
|
} else unreachable;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
try S.doTheTest();
|
2023-06-05 14:29:28 +06:00
|
|
|
try comptime S.doTheTest();
|
2021-10-28 17:23:02 -07:00
|
|
|
}
|
2022-01-25 23:29:02 -07:00
|
|
|
|
|
|
|
|
test "if prongs cast to expected type instead of peer type resolution" {
|
|
|
|
|
const S = struct {
|
|
|
|
|
fn doTheTest(f: bool) !void {
|
|
|
|
|
var x: i32 = 0;
|
|
|
|
|
x = if (f) 1 else 2;
|
|
|
|
|
try expect(x == 2);
|
|
|
|
|
|
|
|
|
|
var b = true;
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = &b;
|
2022-01-25 23:29:02 -07:00
|
|
|
const y: i32 = if (b) 1 else 2;
|
|
|
|
|
try expect(y == 1);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
try S.doTheTest(false);
|
2023-06-05 14:29:28 +06:00
|
|
|
try comptime S.doTheTest(false);
|
2022-01-25 23:29:02 -07:00
|
|
|
}
|
2022-06-28 17:56:28 -07:00
|
|
|
|
|
|
|
|
test "if peer expressions inferred optional type" {
|
|
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2022-06-28 17:56:28 -07:00
|
|
|
|
|
|
|
|
var self: []const u8 = "abcdef";
|
|
|
|
|
var index: usize = 0;
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = .{ &self, &index };
|
|
|
|
|
const left_index = (index << 1) + 1;
|
|
|
|
|
const right_index = left_index + 1;
|
|
|
|
|
const left = if (left_index < self.len) self[left_index] else null;
|
|
|
|
|
const right = if (right_index < self.len) self[right_index] else null;
|
2022-06-28 17:56:28 -07:00
|
|
|
try expect(left_index < self.len);
|
|
|
|
|
try expect(right_index < self.len);
|
|
|
|
|
try expect(left.? == 98);
|
|
|
|
|
try expect(right.? == 99);
|
|
|
|
|
}
|
2022-07-14 16:48:44 -07:00
|
|
|
|
|
|
|
|
test "if-else expression with runtime condition result location is inferred optional" {
|
|
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2022-07-14 16:48:44 -07:00
|
|
|
|
|
|
|
|
const A = struct { b: u64, c: u64 };
|
|
|
|
|
var d: bool = true;
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = &d;
|
2022-07-14 16:48:44 -07:00
|
|
|
const e = if (d) A{ .b = 15, .c = 30 } else null;
|
|
|
|
|
try expect(e != null);
|
|
|
|
|
}
|
2022-07-14 18:10:54 -07:00
|
|
|
|
|
|
|
|
test "result location with inferred type ends up being pointer to comptime_int" {
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
|
|
|
|
|
2022-07-14 18:10:54 -07:00
|
|
|
var a: ?u32 = 1234;
|
|
|
|
|
var b: u32 = 2000;
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = .{ &a, &b };
|
|
|
|
|
const c = if (a) |d| blk: {
|
2022-07-14 18:10:54 -07:00
|
|
|
if (d < b) break :blk @as(u32, 1);
|
|
|
|
|
break :blk 0;
|
|
|
|
|
} else @as(u32, 0);
|
|
|
|
|
try expect(c == 1);
|
|
|
|
|
}
|
2023-05-28 03:15:49 +02:00
|
|
|
|
|
|
|
|
test "if-@as-if chain" {
|
|
|
|
|
var fast = true;
|
|
|
|
|
var very_fast = false;
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = .{ &fast, &very_fast };
|
2023-05-28 03:15:49 +02:00
|
|
|
|
|
|
|
|
const num_frames = if (fast)
|
|
|
|
|
@as(u32, if (very_fast) 16 else 4)
|
|
|
|
|
else
|
|
|
|
|
1;
|
|
|
|
|
|
|
|
|
|
try expect(num_frames == 4);
|
|
|
|
|
}
|
2024-01-02 13:08:26 +03:00
|
|
|
|
|
|
|
|
fn returnTrue() bool {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "if value shouldn't be load-elided if used later (structs)" {
|
|
|
|
|
const Foo = struct { x: i32 };
|
|
|
|
|
|
|
|
|
|
var a = Foo{ .x = 1 };
|
|
|
|
|
var b = Foo{ .x = 1 };
|
|
|
|
|
|
|
|
|
|
const c = if (@call(.never_inline, returnTrue, .{})) a else b;
|
|
|
|
|
// The second variable is superfluous with the current
|
|
|
|
|
// state of codegen optimizations, but in future
|
|
|
|
|
// "if (smthg) a else a" may be optimized simply into "a".
|
|
|
|
|
|
|
|
|
|
a.x = 2;
|
|
|
|
|
b.x = 3;
|
|
|
|
|
|
|
|
|
|
try std.testing.expectEqual(c.x, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "if value shouldn't be load-elided if used later (optionals)" {
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
|
|
|
|
|
2024-01-02 13:08:26 +03:00
|
|
|
var a: ?i32 = 1;
|
|
|
|
|
var b: ?i32 = 1;
|
|
|
|
|
|
|
|
|
|
const c = if (@call(.never_inline, returnTrue, .{})) a else b;
|
|
|
|
|
|
|
|
|
|
a = 2;
|
|
|
|
|
b = 3;
|
|
|
|
|
|
|
|
|
|
try std.testing.expectEqual(c, 1);
|
|
|
|
|
}
|
2024-01-02 17:33:41 +02:00
|
|
|
|
|
|
|
|
test "variable type inferred from if expression" {
|
|
|
|
|
var a = if (true) {
|
|
|
|
|
return;
|
|
|
|
|
} else true;
|
|
|
|
|
_ = &a;
|
|
|
|
|
return error.TestFailed;
|
|
|
|
|
}
|