Commit 69ab687156
Changed files (8)
test
behavior
cases
compile_errors
test/behavior/switch_on_captured_error.zig
@@ -0,0 +1,750 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const expect = std.testing.expect;
+const expectError = std.testing.expectError;
+const expectEqual = std.testing.expectEqual;
+
+test "switch on error union catch capture" {
+ const S = struct {
+ const Error = error{ A, B, C };
+ fn doTheTest() !void {
+ try testScalar();
+ try testMulti();
+ try testElse();
+ try testCapture();
+ try testInline();
+ try testEmptyErrSet();
+ }
+
+ fn testScalar() !void {
+ {
+ var a: Error!u64 = 3;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ error.A => 0,
+ error.B => 1,
+ error.C => 2,
+ };
+ try expectEqual(@as(u64, 3), b);
+ }
+ {
+ var a: Error!u64 = 3;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ error.A => 0,
+ error.B => @intFromError(err) + 4,
+ error.C => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 3), b);
+ }
+ {
+ var a: Error!u64 = error.A;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ error.A => 0,
+ error.B => @intFromError(err) + 4,
+ error.C => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 0), b);
+ }
+ }
+
+ fn testMulti() !void {
+ {
+ var a: Error!u64 = 3;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ error.A, error.B => 0,
+ error.C => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 3), b);
+ }
+ {
+ var a: Error!u64 = 3;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ error.A => 0,
+ error.B, error.C => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 3), b);
+ }
+ {
+ var a: Error!u64 = error.A;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ error.A, error.B => 0,
+ error.C => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 0), b);
+ }
+ {
+ var a: Error!u64 = error.A;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ error.A => 0,
+ error.B, error.C => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 0), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ error.A => 0,
+ error.B, error.C => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ }
+
+ fn testElse() !void {
+ {
+ var a: Error!u64 = 3;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ error.A => 0,
+ else => 1,
+ };
+ try expectEqual(@as(u64, 3), b);
+ }
+ {
+ var a: Error!u64 = 3;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ error.A => 0,
+ else => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 3), b);
+ }
+ {
+ var a: Error!u64 = error.A;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ error.A => 1,
+ else => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 1), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ error.A => 0,
+ else => 1,
+ };
+ try expectEqual(@as(u64, 1), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ error.A => 0,
+ else => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ }
+
+ fn testCapture() !void {
+ {
+ var a: Error!u64 = error.A;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ error.A => |e| @intFromError(e) + 4,
+ else => 0,
+ };
+ try expectEqual(@as(u64, @intFromError(error.A) + 4), b);
+ }
+ {
+ var a: Error!u64 = error.A;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ error.A => 0,
+ else => |e| @intFromError(e) + 4,
+ };
+ try expectEqual(@as(u64, 0), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ error.A => 0,
+ else => |e| @intFromError(e) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ error.A => |e| @intFromError(e) + 4,
+ else => |e| @intFromError(e) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ error.A => 0,
+ error.B, error.C => |e| @intFromError(e) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ }
+
+ fn testInline() !void {
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ error.A => 0,
+ inline else => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ error.A => |e| @intFromError(e) + 4,
+ inline else => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ inline else => |e| @intFromError(e) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ error.A => 0,
+ inline error.B, error.C => |e| @intFromError(e) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ }
+
+ fn testEmptyErrSet() !void {
+ {
+ var a: error{}!u64 = 0;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ else => |e| return e,
+ };
+ try expectEqual(@as(u64, 0), b);
+ }
+ {
+ var a: error{}!u64 = 0;
+ _ = &a;
+ const b: u64 = a catch |err| switch (err) {
+ error.UnknownError => return error.Fail,
+ else => |e| return e,
+ };
+ try expectEqual(@as(u64, 0), b);
+ }
+ }
+ };
+
+ try comptime S.doTheTest();
+ try S.doTheTest();
+}
+
+test "switch on error union if else capture" {
+ const S = struct {
+ const Error = error{ A, B, C };
+ fn doTheTest() !void {
+ try testScalar();
+ try testScalarPtr();
+ try testMulti();
+ try testMultiPtr();
+ try testElse();
+ try testElsePtr();
+ try testCapture();
+ try testCapturePtr();
+ try testInline();
+ try testInlinePtr();
+ try testEmptyErrSet();
+ try testEmptyErrSetPtr();
+ }
+
+ fn testScalar() !void {
+ {
+ var a: Error!u64 = 3;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ error.A => 0,
+ error.B => 1,
+ error.C => 2,
+ };
+ try expectEqual(@as(u64, 3), b);
+ }
+ {
+ var a: Error!u64 = 3;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ error.A => 0,
+ error.B => @intFromError(err) + 4,
+ error.C => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 3), b);
+ }
+ {
+ var a: Error!u64 = error.A;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ error.A => 0,
+ error.B => @intFromError(err) + 4,
+ error.C => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 0), b);
+ }
+ }
+
+ fn testScalarPtr() !void {
+ {
+ var a: Error!u64 = 3;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ error.A => 0,
+ error.B => 1,
+ error.C => 2,
+ };
+ try expectEqual(@as(u64, 3), b);
+ }
+ {
+ var a: Error!u64 = 3;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ error.A => 0,
+ error.B => @intFromError(err) + 4,
+ error.C => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 3), b);
+ }
+ {
+ var a: Error!u64 = error.A;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ error.A => 0,
+ error.B => @intFromError(err) + 4,
+ error.C => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 0), b);
+ }
+ }
+
+ fn testMulti() !void {
+ {
+ var a: Error!u64 = 3;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ error.A, error.B => 0,
+ error.C => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 3), b);
+ }
+ {
+ var a: Error!u64 = 3;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ error.A => 0,
+ error.B, error.C => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 3), b);
+ }
+ {
+ var a: Error!u64 = error.A;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ error.A, error.B => 0,
+ error.C => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 0), b);
+ }
+ {
+ var a: Error!u64 = error.A;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ error.A => 0,
+ error.B, error.C => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 0), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ error.A => 0,
+ error.B, error.C => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ }
+
+ fn testMultiPtr() !void {
+ {
+ var a: Error!u64 = 3;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ error.A, error.B => 0,
+ error.C => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 3), b);
+ }
+ {
+ var a: Error!u64 = 3;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ error.A => 0,
+ error.B, error.C => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 3), b);
+ }
+ {
+ var a: Error!u64 = error.A;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ error.A, error.B => 0,
+ error.C => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 0), b);
+ }
+ {
+ var a: Error!u64 = error.A;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ error.A => 0,
+ error.B, error.C => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 0), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ error.A => 0,
+ error.B, error.C => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ }
+
+ fn testElse() !void {
+ {
+ var a: Error!u64 = 3;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ error.A => 0,
+ else => 1,
+ };
+ try expectEqual(@as(u64, 3), b);
+ }
+ {
+ var a: Error!u64 = 3;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ error.A => 0,
+ else => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 3), b);
+ }
+ {
+ var a: Error!u64 = error.A;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ error.A => 1,
+ else => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 1), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ error.A => 0,
+ else => 1,
+ };
+ try expectEqual(@as(u64, 1), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ error.A => 0,
+ else => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ }
+
+ fn testElsePtr() !void {
+ {
+ var a: Error!u64 = 3;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ error.A => 0,
+ else => 1,
+ };
+ try expectEqual(@as(u64, 3), b);
+ }
+ {
+ var a: Error!u64 = 3;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ error.A => 0,
+ else => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 3), b);
+ }
+ {
+ var a: Error!u64 = error.A;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ error.A => 1,
+ else => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, 1), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ error.A => 0,
+ else => 1,
+ };
+ try expectEqual(@as(u64, 1), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ error.A => 0,
+ else => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ }
+
+ fn testCapture() !void {
+ {
+ var a: Error!u64 = error.A;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ error.A => |e| @intFromError(e) + 4,
+ else => 0,
+ };
+ try expectEqual(@as(u64, @intFromError(error.A) + 4), b);
+ }
+ {
+ var a: Error!u64 = error.A;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ error.A => 0,
+ else => |e| @intFromError(e) + 4,
+ };
+ try expectEqual(@as(u64, 0), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ error.A => 0,
+ else => |e| @intFromError(e) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ error.A => |e| @intFromError(e) + 4,
+ else => |e| @intFromError(e) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ error.A => 0,
+ error.B, error.C => |e| @intFromError(e) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ }
+
+ fn testCapturePtr() !void {
+ {
+ var a: Error!u64 = error.A;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ error.A => |e| @intFromError(e) + 4,
+ else => 0,
+ };
+ try expectEqual(@as(u64, @intFromError(error.A) + 4), b);
+ }
+ {
+ var a: Error!u64 = error.A;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ error.A => 0,
+ else => |e| @intFromError(e) + 4,
+ };
+ try expectEqual(@as(u64, 0), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ error.A => 0,
+ else => |e| @intFromError(e) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ error.A => |e| @intFromError(e) + 4,
+ else => |e| @intFromError(e) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ error.A => 0,
+ error.B, error.C => |e| @intFromError(e) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ }
+
+ fn testInline() !void {
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ error.A => 0,
+ inline else => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ error.A => |e| @intFromError(e) + 4,
+ inline else => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ inline else => |e| @intFromError(e) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ error.A => 0,
+ inline error.B, error.C => |e| @intFromError(e) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ }
+
+ fn testInlinePtr() !void {
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ error.A => 0,
+ inline else => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ error.A => |e| @intFromError(e) + 4,
+ inline else => @intFromError(err) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ inline else => |e| @intFromError(e) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ {
+ var a: Error!u64 = error.B;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ error.A => 0,
+ inline error.B, error.C => |e| @intFromError(e) + 4,
+ };
+ try expectEqual(@as(u64, @intFromError(error.B) + 4), b);
+ }
+ }
+
+ fn testEmptyErrSet() !void {
+ {
+ var a: error{}!u64 = 0;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ else => |e| return e,
+ };
+ try expectEqual(@as(u64, 0), b);
+ }
+ {
+ var a: error{}!u64 = 0;
+ _ = &a;
+ const b: u64 = if (a) |x| x else |err| switch (err) {
+ error.UnknownError => return error.Fail,
+ else => |e| return e,
+ };
+ try expectEqual(@as(u64, 0), b);
+ }
+ }
+
+ fn testEmptyErrSetPtr() !void {
+ {
+ var a: error{}!u64 = 0;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ else => |e| return e,
+ };
+ try expectEqual(@as(u64, 0), b);
+ }
+ {
+ var a: error{}!u64 = 0;
+ _ = &a;
+ const b: u64 = if (a) |*x| x.* else |err| switch (err) {
+ error.UnknownError => return error.Fail,
+ else => |e| return e,
+ };
+ try expectEqual(@as(u64, 0), b);
+ }
+ }
+ };
+
+ try comptime S.doTheTest();
+ try S.doTheTest();
+}
test/cases/compile_errors/switch_expression-duplicate_error_prong.zig
@@ -0,0 +1,33 @@
+fn f(n: Error!i32) i32 {
+ if (n) |x|
+ _ = x
+ else |e| switch (e) {
+ error.Foo => 1,
+ error.Bar => 2,
+ error.Baz => 3,
+ error.Foo => 2,
+ }
+}
+fn g(n: Error!i32) i32 {
+ n catch |e| switch (e) {
+ error.Foo => 1,
+ error.Bar => 2,
+ error.Baz => 3,
+ error.Foo => 2,
+ };
+}
+
+const Error = error{ Foo, Bar, Baz };
+
+export fn entry() usize {
+ return @sizeOf(@TypeOf(&f)) + @sizeOf(@TypeOf(&g));
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :8:9: error: duplicate switch value
+// :5:9: note: previous value here
+// :16:9: error: duplicate switch value
+// :13:9: note: previous value here
test/cases/compile_errors/switch_expression-duplicate_error_prong_when_else_present.zig
@@ -0,0 +1,35 @@
+fn f(n: Error!i32) i32 {
+ if (n) |x|
+ _ = x
+ else |e| switch (e) {
+ error.Foo => 1,
+ error.Bar => 2,
+ error.Baz => 3,
+ error.Foo => 2,
+ else => 10,
+ }
+}
+fn g(n: Error!i32) i32 {
+ n catch |e| switch (e) {
+ error.Foo => 1,
+ error.Bar => 2,
+ error.Baz => 3,
+ error.Foo => 2,
+ else => 10,
+ };
+}
+
+const Error = error{ Foo, Bar, Baz };
+
+export fn entry() usize {
+ return @sizeOf(@TypeOf(&f)) + @sizeOf(@TypeOf(&g));
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :8:9: error: duplicate switch value
+// :5:9: note: previous value here
+// :17:9: error: duplicate switch value
+// :14:9: note: previous value here
test/cases/compile_errors/switch_expression-missing_error_prong.zig
@@ -0,0 +1,33 @@
+const Error = error {
+ One,
+ Two,
+ Three,
+ Four,
+};
+fn f(n: Error!i32) i32 {
+ if (n) |x| x else |e| switch (e) {
+ error.One => 1,
+ error.Two => 2,
+ error.Three => 3,
+ }
+}
+fn h(n: Error!i32) i32 {
+ n catch |e| switch (e) {
+ error.One => 1,
+ error.Two => 2,
+ error.Three => 3,
+ };
+}
+
+export fn entry() usize {
+ return @sizeOf(@TypeOf(&f)) + @sizeOf(@TypeOf(&h));
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :8:27: error: switch must handle all possibilities
+// :8:27: note: unhandled error value: 'error.Four'
+// :15:17: error: switch must handle all possibilities
+// :15:17: note: unhandled error value: 'error.Four'
test/cases/compile_errors/switch_expression-multiple_else_prongs.zig
@@ -5,8 +5,24 @@ fn f(x: u32) void {
else => true,
};
}
+fn g(x: error{Foo, Bar, Baz}!u32) void {
+ const value: bool = if (x) |_| true else |e| switch (e) {
+ error.Foo => false,
+ else => true,
+ else => true,
+ };
+}
+fn h(x: error{Foo, Bar, Baz}!u32) void {
+ const value: u32 = x catch |e| switch (e) {
+ error.Foo => 1,
+ else => 2,
+ else => 3,
+ };
+}
export fn entry() void {
f(1234);
+ g(1234);
+ h(1234);
}
// error
@@ -15,3 +31,7 @@ export fn entry() void {
//
// :5:9: error: multiple else prongs in switch expression
// :4:9: note: previous else prong here
+// :12:9: error: multiple else prongs in switch expression
+// :11:9: note: previous else prong here
+// :19:9: error: multiple else prongs in switch expression
+// :18:9: note: previous else prong here
test/cases/compile_errors/switch_expression-unreachable_else_prong_error.zig
@@ -0,0 +1,32 @@
+fn foo(x: u2) void {
+ const y: Error!u2 = x;
+ if (y) |_| {} else |e| switch (e) {
+ error.Foo => {},
+ error.Bar => {},
+ error.Baz => {},
+ else => {},
+ }
+}
+
+fn bar(x: u2) void {
+ const y: Error!u2 = x;
+ y catch |e| switch (e) {
+ error.Foo => {},
+ error.Bar => {},
+ error.Baz => {},
+ else => {},
+ };
+}
+
+const Error = error{ Foo, Bar, Baz };
+
+export fn entry() usize {
+ return @sizeOf(@TypeOf(&foo)) + @sizeOf(@TypeOf(&bar));
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :7:14: error: unreachable else prong; all cases already handled
+// :17:14: error: unreachable else prong; all cases already handled
test/cases/compile_errors/switch_on_error_union_discard.zig
@@ -0,0 +1,12 @@
+export fn entry() void {
+ const x: error{}!u32 = 0;
+ if (x) |v| v else |_| switch (_) {
+ }
+}
+
+
+// error
+// backend=stage2
+// target=native
+//
+// :3:24: error: discard of error capture; omit it instead
test/cases/compile_errors/switch_on_error_with_1_field_with_no_prongs.zig
@@ -0,0 +1,20 @@
+const Error = error{M};
+
+export fn entry() void {
+ const f: Error!void = void{};
+ if (f) {} else |e| switch (e) {}
+}
+
+export fn entry2() void {
+ const f: Error!void = void{};
+ f catch |e| switch (e) {};
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :5:24: error: switch must handle all possibilities
+// :5:24: note: unhandled error value: 'error.M'
+// :10:17: error: switch must handle all possibilities
+// :10:17: note: unhandled error value: 'error.M'