| author | |
| committer | |
| log | e48779fe1f6127d50008277fb8662566769975da |
| tree | 55a346d4c59937c493b5ca9efa02220cdf9d53ce |
| parent | d3056114f6f17bb4723cccfa4dd578ddafb909a9 |
Makes them more similar to other existing compile errors.3 files changed, 139 insertions(+), 47 deletions(-)
src/Sema.zig+36-22| ... | ... | @@ -11186,14 +11186,8 @@ fn validateSwitchBlock( |
| 11186 | 11186 | operand_ty.assertHasLayout(zcu); |
| 11187 | 11187 | const union_obj = ip.loadUnionType(operand_ty.toIntern()); |
| 11188 | 11188 | switch (union_obj.tag_usage) { |
| 11189 | .tagged => { | |
| 11190 | break :item_ty .fromInterned(union_obj.enum_tag_type); | |
| 11191 | }, | |
| 11192 | .none => { | |
| 11193 | if (union_obj.layout == .@"packed") { | |
| 11194 | break :item_ty operand_ty; | |
| 11195 | } | |
| 11196 | }, | |
| 11189 | .tagged => break :item_ty .fromInterned(union_obj.enum_tag_type), | |
| 11190 | .none => if (union_obj.layout == .@"packed") break :item_ty operand_ty, | |
| 11197 | 11191 | .safety => {}, |
| 11198 | 11192 | } |
| 11199 | 11193 | return sema.failWithOwnedErrorMsg(block, msg: { |
| ... | ... | @@ -11208,27 +11202,47 @@ fn validateSwitchBlock( |
| 11208 | 11202 | |
| 11209 | 11203 | .@"struct" => { |
| 11210 | 11204 | operand_ty.assertHasLayout(zcu); |
| 11211 | const layout = operand_ty.containerLayout(zcu); | |
| 11212 | if (layout == .@"packed") { | |
| 11213 | break :item_ty operand_ty; | |
| 11214 | } | |
| 11205 | if (operand_ty.containerLayout(zcu) == .@"packed") break :item_ty operand_ty; | |
| 11215 | 11206 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 11216 | const msg = try sema.errMsg(operand_src, "switch on struct with {t} layout", .{layout}); | |
| 11207 | const msg = try sema.errMsg(operand_src, "switch on non-packed struct", .{}); | |
| 11217 | 11208 | errdefer msg.destroy(sema.gpa); |
| 11218 | if (operand_ty.srcLocOrNull(zcu)) |struct_src| { | |
| 11219 | try sema.errNote(struct_src, msg, "consider 'packed struct' here", .{}); | |
| 11220 | } | |
| 11209 | try sema.addDeclaredHereNote(msg, operand_ty); | |
| 11221 | 11210 | break :msg msg; |
| 11222 | 11211 | }); |
| 11223 | 11212 | }, |
| 11224 | 11213 | |
| 11225 | .pointer => { | |
| 11226 | if (!operand_ty.isSlice(zcu)) { | |
| 11227 | break :item_ty operand_ty; | |
| 11228 | } | |
| 11229 | }, | |
| 11214 | .pointer => if (!operand_ty.isSlice(zcu)) break :item_ty operand_ty, | |
| 11230 | 11215 | |
| 11231 | else => {}, | |
| 11216 | .optional => return sema.failWithOwnedErrorMsg(block, msg: { | |
| 11217 | const msg = try sema.errMsg(operand_src, "switch on optional type '{f}'", .{ | |
| 11218 | operand_ty.fmt(pt), | |
| 11219 | }); | |
| 11220 | errdefer msg.destroy(gpa); | |
| 11221 | try sema.errNote(operand_src, msg, "consider using '.?', 'orelse', or 'if'", .{}); | |
| 11222 | break :msg msg; | |
| 11223 | }), | |
| 11224 | ||
| 11225 | .error_union => return sema.failWithOwnedErrorMsg(block, msg: { | |
| 11226 | const msg = try sema.errMsg(operand_src, "switch on error union type '{f}'", .{ | |
| 11227 | operand_ty.fmt(pt), | |
| 11228 | }); | |
| 11229 | errdefer msg.destroy(gpa); | |
| 11230 | try sema.errNote(operand_src, msg, "consider using 'try', 'catch', or 'if'", .{}); | |
| 11231 | break :msg msg; | |
| 11232 | }), | |
| 11233 | ||
| 11234 | .noreturn, | |
| 11235 | .float, | |
| 11236 | .comptime_float, | |
| 11237 | .array, | |
| 11238 | .vector, | |
| 11239 | .undefined, | |
| 11240 | .null, | |
| 11241 | .@"opaque", | |
| 11242 | .frame, | |
| 11243 | .@"anyframe", | |
| 11244 | .spirv, | |
| 11245 | => {}, | |
| 11232 | 11246 | } |
| 11233 | 11247 | return sema.fail(block, operand_src, "switch on type '{f}'", .{operand_ty.fmt(pt)}); |
| 11234 | 11248 | }; |
test/cases/compile_errors/switch_on_invalid_type.zig created+103| ... | ... | @@ -0,0 +1,103 @@ |
| 1 | const AutoUnion = union { a: u8 }; | |
| 2 | export fn entry1() void { | |
| 3 | switch (@as(AutoUnion, .{ .a = 123 })) { | |
| 4 | else => {}, | |
| 5 | } | |
| 6 | } | |
| 7 | ||
| 8 | const ExternUnion = union { a: u8 }; | |
| 9 | export fn entry2() void { | |
| 10 | switch (@as(ExternUnion, .{ .a = 123 })) { | |
| 11 | else => {}, | |
| 12 | } | |
| 13 | } | |
| 14 | ||
| 15 | const AutoStruct = struct { a: u8 }; | |
| 16 | export fn entry3() void { | |
| 17 | switch (@as(AutoStruct, .{ .a = 123 })) { | |
| 18 | else => {}, | |
| 19 | } | |
| 20 | } | |
| 21 | ||
| 22 | const ExternStruct = extern struct { a: u8 }; | |
| 23 | export fn entry4() void { | |
| 24 | switch (@as(ExternStruct, .{ .a = 123 })) { | |
| 25 | else => {}, | |
| 26 | } | |
| 27 | } | |
| 28 | ||
| 29 | export fn entry5() void { | |
| 30 | switch (@as([]const u16, &.{ 1, 2, 3 })) { | |
| 31 | else => {}, | |
| 32 | } | |
| 33 | } | |
| 34 | ||
| 35 | export fn entry6() void { | |
| 36 | switch (@as([3]u16, .{ 1, 2, 3 })) { | |
| 37 | else => {}, | |
| 38 | } | |
| 39 | } | |
| 40 | ||
| 41 | export fn entry7() void { | |
| 42 | switch (@as(@Vector(3, u16), .{ 1, 2, 3 })) { | |
| 43 | else => {}, | |
| 44 | } | |
| 45 | } | |
| 46 | ||
| 47 | export fn entry8() void { | |
| 48 | switch (@as(?u16, 123)) { | |
| 49 | else => {}, | |
| 50 | } | |
| 51 | } | |
| 52 | ||
| 53 | export fn entry9() void { | |
| 54 | switch (@as(anyerror!u16, 123)) { | |
| 55 | else => {}, | |
| 56 | } | |
| 57 | } | |
| 58 | ||
| 59 | export fn entry10() void { | |
| 60 | switch (@as(f32, 123)) { | |
| 61 | else => {}, | |
| 62 | } | |
| 63 | } | |
| 64 | ||
| 65 | export fn entry11() void { | |
| 66 | switch (@as(comptime_float, 123)) { | |
| 67 | else => {}, | |
| 68 | } | |
| 69 | } | |
| 70 | ||
| 71 | export fn entry12() void { | |
| 72 | switch (undefined) { | |
| 73 | else => {}, | |
| 74 | } | |
| 75 | } | |
| 76 | ||
| 77 | export fn entry13() void { | |
| 78 | switch (null) { | |
| 79 | else => {}, | |
| 80 | } | |
| 81 | } | |
| 82 | ||
| 83 | // error | |
| 84 | // | |
| 85 | // :3:13: error: switch on union with no attached enum | |
| 86 | // :1:19: note: consider 'union(enum)' here | |
| 87 | // :10:13: error: switch on union with no attached enum | |
| 88 | // :8:21: note: consider 'union(enum)' here | |
| 89 | // :17:13: error: switch on non-packed struct | |
| 90 | // :15:20: note: struct declared here | |
| 91 | // :24:13: error: switch on non-packed struct | |
| 92 | // :22:29: note: struct declared here | |
| 93 | // :30:13: error: switch on type '[]const u16' | |
| 94 | // :36:13: error: switch on type '[3]u16' | |
| 95 | // :42:13: error: switch on type '@Vector(3, u16)' | |
| 96 | // :48:13: error: switch on optional type '?u16' | |
| 97 | // :48:13: note: consider using '.?', 'orelse', or 'if' | |
| 98 | // :54:13: error: switch on error union type 'anyerror!u16' | |
| 99 | // :54:13: note: consider using 'try', 'catch', or 'if' | |
| 100 | // :60:13: error: switch on type 'f32' | |
| 101 | // :66:13: error: switch on type 'comptime_float' | |
| 102 | // :72:13: error: switch on type '@TypeOf(undefined)' | |
| 103 | // :78:13: error: switch on type '@TypeOf(null)' |
test/cases/compile_errors/switch_on_non_packed_struct.zig deleted-25| ... | ... | @@ -1,25 +0,0 @@ |
| 1 | const Auto = struct { | |
| 2 | a: u8, | |
| 3 | }; | |
| 4 | export fn entry1(a: u8) void { | |
| 5 | const s: Auto = .{ .a = a }; | |
| 6 | switch (s) { | |
| 7 | else => {}, | |
| 8 | } | |
| 9 | } | |
| 10 | ||
| 11 | const Extern = extern struct { | |
| 12 | a: u8, | |
| 13 | }; | |
| 14 | export fn entry2(s: Extern) void { | |
| 15 | switch (s) { | |
| 16 | else => {}, | |
| 17 | } | |
| 18 | } | |
| 19 | ||
| 20 | // error | |
| 21 | // | |
| 22 | // :6:13: error: switch on struct with auto layout | |
| 23 | // :1:14: note: consider 'packed struct' here | |
| 24 | // :15:13: error: switch on struct with extern layout | |
| 25 | // :11:23: note: consider 'packed struct' here |