master
  1const std = @import("std");
  2const builtin = @import("builtin");
  3const expect = std.testing.expect;
  4
  5test "try on error union" {
  6    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
  7
  8    try tryOnErrorUnionImpl();
  9    try comptime tryOnErrorUnionImpl();
 10}
 11
 12fn tryOnErrorUnionImpl() !void {
 13    const x = if (returnsTen()) |val| val + 1 else |err| switch (err) {
 14        error.ItBroke, error.NoMem => 1,
 15        error.CrappedOut => @as(i32, 2),
 16        else => unreachable,
 17    };
 18    try expect(x == 11);
 19}
 20
 21fn returnsTen() anyerror!i32 {
 22    return 10;
 23}
 24
 25test "try without vars" {
 26    const result1 = if (failIfTrue(true)) 1 else |_| @as(i32, 2);
 27    try expect(result1 == 2);
 28
 29    const result2 = if (failIfTrue(false)) 1 else |_| @as(i32, 2);
 30    try expect(result2 == 1);
 31}
 32
 33fn failIfTrue(ok: bool) anyerror!void {
 34    if (ok) {
 35        return error.ItBroke;
 36    } else {
 37        return;
 38    }
 39}
 40
 41test "try then not executed with assignment" {
 42    if (failIfTrue(true)) {
 43        unreachable;
 44    } else |err| {
 45        try expect(err == error.ItBroke);
 46    }
 47}
 48
 49test "`try`ing an if/else expression" {
 50    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 51    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 52    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 53
 54    const S = struct {
 55        fn getError() !void {
 56            return error.Test;
 57        }
 58
 59        fn getError2() !void {
 60            var a: u8 = 'c';
 61            _ = &a;
 62            try if (a == 'a') getError() else if (a == 'b') getError() else getError();
 63        }
 64    };
 65
 66    try std.testing.expectError(error.Test, S.getError2());
 67}
 68
 69test "'return try' of empty error set in function returning non-error" {
 70    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 71    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 72
 73    const S = struct {
 74        fn succeed0() error{}!u32 {
 75            return 123;
 76        }
 77        fn succeed1() !u32 {
 78            return 456;
 79        }
 80        fn tryNoError0() u32 {
 81            return try succeed0();
 82        }
 83        fn tryNoError1() u32 {
 84            return try succeed1();
 85        }
 86        fn tryNoError2() u32 {
 87            const e: error{}!u32 = 789;
 88            return try e;
 89        }
 90        fn doTheTest() !void {
 91            const res0 = tryNoError0();
 92            const res1 = tryNoError1();
 93            const res2 = tryNoError2();
 94            try expect(res0 == 123);
 95            try expect(res1 == 456);
 96            try expect(res2 == 789);
 97        }
 98    };
 99    try S.doTheTest();
100    try comptime S.doTheTest();
101}
102
103test "'return try' through conditional" {
104    const S = struct {
105        fn get(t: bool) !u32 {
106            return try if (t) inner() else error.TestFailed;
107        }
108        fn inner() !u16 {
109            return 123;
110        }
111    };
112
113    {
114        const result = try S.get(true);
115        try expect(result == 123);
116    }
117
118    {
119        const result = try comptime S.get(true);
120        comptime std.debug.assert(result == 123);
121    }
122}
123
124test "try ptr propagation const" {
125    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
126    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
127    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
128    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
129
130    const S = struct {
131        fn foo0() !u32 {
132            return 0;
133        }
134
135        fn foo1() error{Bad}!u32 {
136            return 1;
137        }
138
139        fn foo2() anyerror!u32 {
140            return 2;
141        }
142
143        fn doTheTest() !void {
144            const res0: *const u32 = &(try foo0());
145            const res1: *const u32 = &(try foo1());
146            const res2: *const u32 = &(try foo2());
147            try expect(res0.* == 0);
148            try expect(res1.* == 1);
149            try expect(res2.* == 2);
150        }
151    };
152    try S.doTheTest();
153    try comptime S.doTheTest();
154}
155
156test "try ptr propagation mutate" {
157    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
158    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
159    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
160    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
161
162    const S = struct {
163        fn foo0() !u32 {
164            return 0;
165        }
166
167        fn foo1() error{Bad}!u32 {
168            return 1;
169        }
170
171        fn foo2() anyerror!u32 {
172            return 2;
173        }
174
175        fn doTheTest() !void {
176            var f0 = foo0();
177            var f1 = foo1();
178            var f2 = foo2();
179
180            const res0: *u32 = &(try f0);
181            const res1: *u32 = &(try f1);
182            const res2: *u32 = &(try f2);
183
184            res0.* += 1;
185            res1.* += 1;
186            res2.* += 1;
187
188            try expect(f0 catch unreachable == 1);
189            try expect(f1 catch unreachable == 2);
190            try expect(f2 catch unreachable == 3);
191
192            try expect(res0.* == 1);
193            try expect(res1.* == 2);
194            try expect(res2.* == 3);
195        }
196    };
197    try S.doTheTest();
198    try comptime S.doTheTest();
199}