authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-01-05 13:09:07+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-01-05 13:11:36+02:00
log352c71873b1c018fed8821d275b490be8c881792
tree1692cba2ea0a2d5f0d2f2c97de0fe37b9ac1bcc6
parent2d617c482ca24563a27125d626ac51e194d49eff

Sema: improve struct/union field error locations

Closes #14206

12 files changed, 194 insertions(+), 94 deletions(-)

src/Sema.zig+142-59
...@@ -30662,14 +30662,19 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -30662,14 +30662,19 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
30662 const gop = struct_obj.fields.getOrPutAssumeCapacity(field_name);30662 const gop = struct_obj.fields.getOrPutAssumeCapacity(field_name);
30663 if (gop.found_existing) {30663 if (gop.found_existing) {
30664 const msg = msg: {30664 const msg = msg: {
30665 const tree = try sema.getAstTree(&block_scope);30665 const field_src = struct_obj.fieldSrcLoc(sema.mod, .{
30666 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i);30666 .index = field_i,
30667 .range = .name,
30668 }).lazy;
30667 const msg = try sema.errMsg(&block_scope, field_src, "duplicate struct field: '{s}'", .{field_name});30669 const msg = try sema.errMsg(&block_scope, field_src, "duplicate struct field: '{s}'", .{field_name});
30668 errdefer msg.destroy(gpa);30670 errdefer msg.destroy(gpa);
3066930671
30670 const prev_field_index = struct_obj.fields.getIndex(field_name).?;30672 const prev_field_index = struct_obj.fields.getIndex(field_name).?;
30671 const prev_field_src = enumFieldSrcLoc(decl, tree.*, 0, prev_field_index);30673 const prev_field_src = struct_obj.fieldSrcLoc(sema.mod, .{
30672 try sema.mod.errNoteNonLazy(prev_field_src.toSrcLoc(decl), msg, "other field here", .{});30674 .index = prev_field_index,
30675 .range = .name,
30676 });
30677 try sema.mod.errNoteNonLazy(prev_field_src, msg, "other field here", .{});
30673 try sema.errNote(&block_scope, src, msg, "struct declared here", .{});30678 try sema.errNote(&block_scope, src, msg, "struct declared here", .{});
30674 break :msg msg;30679 break :msg msg;
30675 };30680 };
...@@ -30699,34 +30704,51 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -30699,34 +30704,51 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
30699 // so that init values may depend on type layout.30704 // so that init values may depend on type layout.
30700 const bodies_index = extra_index;30705 const bodies_index = extra_index;
3070130706
30702 for (fields) |zir_field, i| {30707 for (fields) |zir_field, field_i| {
30703 // TODO emit compile errors for invalid field types
30704 // such as arrays and pointers inside packed structs.
30705 const field_ty: Type = ty: {30708 const field_ty: Type = ty: {
30706 if (zir_field.type_ref != .none) {30709 if (zir_field.type_ref != .none) {
30707 // TODO: if we need to report an error here, use a source location30710 break :ty sema.resolveType(&block_scope, .unneeded, zir_field.type_ref) catch |err| switch (err) {
30708 // that points to this type expression rather than the struct.30711 error.NeededSourceLocation => {
30709 // But only resolve the source location if we need to emit a compile error.30712 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{
30710 break :ty try sema.resolveType(&block_scope, src, zir_field.type_ref);30713 .index = field_i,
30714 .range = .type,
30715 }).lazy;
30716 _ = try sema.resolveType(&block_scope, ty_src, zir_field.type_ref);
30717 unreachable;
30718 },
30719 else => |e| return e,
30720 };
30711 }30721 }
30712 assert(zir_field.type_body_len != 0);30722 assert(zir_field.type_body_len != 0);
30713 const body = zir.extra[extra_index..][0..zir_field.type_body_len];30723 const body = zir.extra[extra_index..][0..zir_field.type_body_len];
30714 extra_index += body.len;30724 extra_index += body.len;
30715 const ty_ref = try sema.resolveBody(&block_scope, body, struct_obj.zir_index);30725 const ty_ref = try sema.resolveBody(&block_scope, body, struct_obj.zir_index);
30716 break :ty try sema.analyzeAsType(&block_scope, src, ty_ref);30726 break :ty sema.analyzeAsType(&block_scope, .unneeded, ty_ref) catch |err| switch (err) {
30727 error.NeededSourceLocation => {
30728 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{
30729 .index = field_i,
30730 .range = .type,
30731 }).lazy;
30732 _ = try sema.analyzeAsType(&block_scope, ty_src, ty_ref);
30733 unreachable;
30734 },
30735 else => |e| return e,
30736 };
30717 };30737 };
30718 if (field_ty.tag() == .generic_poison) {30738 if (field_ty.tag() == .generic_poison) {
30719 return error.GenericPoison;30739 return error.GenericPoison;
30720 }30740 }
3072130741
30722 const field = &struct_obj.fields.values()[i];30742 const field = &struct_obj.fields.values()[field_i];
30723 field.ty = try field_ty.copy(decl_arena_allocator);30743 field.ty = try field_ty.copy(decl_arena_allocator);
3072430744
30725 if (field_ty.zigTypeTag() == .Opaque) {30745 if (field_ty.zigTypeTag() == .Opaque) {
30726 const msg = msg: {30746 const msg = msg: {
30727 const tree = try sema.getAstTree(&block_scope);30747 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{
30728 const field_src = enumFieldSrcLoc(decl, tree.*, 0, i);30748 .index = field_i,
30729 const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});30749 .range = .type,
30750 }).lazy;
30751 const msg = try sema.errMsg(&block_scope, ty_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
30730 errdefer msg.destroy(sema.gpa);30752 errdefer msg.destroy(sema.gpa);
3073130753
30732 try sema.addDeclaredHereNote(msg, field_ty);30754 try sema.addDeclaredHereNote(msg, field_ty);
...@@ -30736,9 +30758,11 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -30736,9 +30758,11 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
30736 }30758 }
30737 if (field_ty.zigTypeTag() == .NoReturn) {30759 if (field_ty.zigTypeTag() == .NoReturn) {
30738 const msg = msg: {30760 const msg = msg: {
30739 const tree = try sema.getAstTree(&block_scope);30761 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{
30740 const field_src = enumFieldSrcLoc(decl, tree.*, 0, i);30762 .index = field_i,
30741 const msg = try sema.errMsg(&block_scope, field_src, "struct fields cannot be 'noreturn'", .{});30763 .range = .type,
30764 }).lazy;
30765 const msg = try sema.errMsg(&block_scope, ty_src, "struct fields cannot be 'noreturn'", .{});
30742 errdefer msg.destroy(sema.gpa);30766 errdefer msg.destroy(sema.gpa);
3074330767
30744 try sema.addDeclaredHereNote(msg, field_ty);30768 try sema.addDeclaredHereNote(msg, field_ty);
...@@ -30748,12 +30772,14 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -30748,12 +30772,14 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
30748 }30772 }
30749 if (struct_obj.layout == .Extern and !try sema.validateExternType(field.ty, .struct_field)) {30773 if (struct_obj.layout == .Extern and !try sema.validateExternType(field.ty, .struct_field)) {
30750 const msg = msg: {30774 const msg = msg: {
30751 const tree = try sema.getAstTree(&block_scope);30775 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{
30752 const fields_src = enumFieldSrcLoc(decl, tree.*, 0, i);30776 .index = field_i,
30753 const msg = try sema.errMsg(&block_scope, fields_src, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});30777 .range = .type,
30778 });
30779 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});
30754 errdefer msg.destroy(sema.gpa);30780 errdefer msg.destroy(sema.gpa);
3075530781
30756 try sema.explainWhyTypeIsNotExtern(msg, fields_src.toSrcLoc(decl), field.ty, .struct_field);30782 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field.ty, .struct_field);
3075730783
30758 try sema.addDeclaredHereNote(msg, field.ty);30784 try sema.addDeclaredHereNote(msg, field.ty);
30759 break :msg msg;30785 break :msg msg;
...@@ -30761,12 +30787,14 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -30761,12 +30787,14 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
30761 return sema.failWithOwnedErrorMsg(msg);30787 return sema.failWithOwnedErrorMsg(msg);
30762 } else if (struct_obj.layout == .Packed and !(validatePackedType(field.ty))) {30788 } else if (struct_obj.layout == .Packed and !(validatePackedType(field.ty))) {
30763 const msg = msg: {30789 const msg = msg: {
30764 const tree = try sema.getAstTree(&block_scope);30790 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{
30765 const fields_src = enumFieldSrcLoc(decl, tree.*, 0, i);30791 .index = field_i,
30766 const msg = try sema.errMsg(&block_scope, fields_src, "packed structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});30792 .range = .type,
30793 });
30794 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "packed structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});
30767 errdefer msg.destroy(sema.gpa);30795 errdefer msg.destroy(sema.gpa);
3076830796
30769 try sema.explainWhyTypeIsNotPacked(msg, fields_src.toSrcLoc(decl), field.ty);30797 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field.ty);
3077030798
30771 try sema.addDeclaredHereNote(msg, field.ty);30799 try sema.addDeclaredHereNote(msg, field.ty);
30772 break :msg msg;30800 break :msg msg;
...@@ -30778,7 +30806,17 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -30778,7 +30806,17 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
30778 const body = zir.extra[extra_index..][0..zir_field.align_body_len];30806 const body = zir.extra[extra_index..][0..zir_field.align_body_len];
30779 extra_index += body.len;30807 extra_index += body.len;
30780 const align_ref = try sema.resolveBody(&block_scope, body, struct_obj.zir_index);30808 const align_ref = try sema.resolveBody(&block_scope, body, struct_obj.zir_index);
30781 field.abi_align = try sema.analyzeAsAlign(&block_scope, src, align_ref);30809 field.abi_align = sema.analyzeAsAlign(&block_scope, .unneeded, align_ref) catch |err| switch (err) {
30810 error.NeededSourceLocation => {
30811 const align_src = struct_obj.fieldSrcLoc(sema.mod, .{
30812 .index = field_i,
30813 .range = .alignment,
30814 }).lazy;
30815 _ = try sema.analyzeAsAlign(&block_scope, align_src, align_ref);
30816 unreachable;
30817 },
30818 else => |e| return e,
30819 };
30782 }30820 }
3078330821
30784 extra_index += zir_field.init_body_len;30822 extra_index += zir_field.init_body_len;
...@@ -31023,9 +31061,17 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -31023,9 +31061,17 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3102331061
31024 if (enum_value_map) |map| {31062 if (enum_value_map) |map| {
31025 const copied_val = if (tag_ref != .none) blk: {31063 const copied_val = if (tag_ref != .none) blk: {
31026 const tag_src = src; // TODO better source location31064 const val = sema.semaUnionFieldVal(&block_scope, .unneeded, int_tag_ty, tag_ref) catch |err| switch (err) {
31027 const coerced = try sema.coerce(&block_scope, int_tag_ty, tag_ref, tag_src);31065 error.NeededSourceLocation => {
31028 const val = try sema.resolveConstValue(&block_scope, tag_src, coerced, "enum tag value must be comptime-known");31066 const val_src = union_obj.fieldSrcLoc(sema.mod, .{
31067 .index = field_i,
31068 .range = .value,
31069 }).lazy;
31070 _ = try sema.semaUnionFieldVal(&block_scope, val_src, int_tag_ty, tag_ref);
31071 unreachable;
31072 },
31073 else => |e| return e,
31074 };
31029 last_tag_val = val;31075 last_tag_val = val;
3103031076
31031 // This puts the memory into the union arena, not the enum arena, but31077 // This puts the memory into the union arena, not the enum arena, but
...@@ -31045,9 +31091,14 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -31045,9 +31091,14 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
31045 .mod = mod,31091 .mod = mod,
31046 });31092 });
31047 if (gop.found_existing) {31093 if (gop.found_existing) {
31048 const tree = try sema.getAstTree(&block_scope);31094 const field_src = union_obj.fieldSrcLoc(sema.mod, .{
31049 const field_src = enumFieldSrcLoc(sema.mod.declPtr(block_scope.src_decl), tree.*, src.node_offset.x, field_i);31095 .index = field_i,
31050 const other_field_src = enumFieldSrcLoc(sema.mod.declPtr(block_scope.src_decl), tree.*, src.node_offset.x, gop.index);31096 .range = .name,
31097 }).lazy;
31098 const other_field_src = union_obj.fieldSrcLoc(sema.mod, .{
31099 .index = gop.index,
31100 .range = .name,
31101 }).lazy;
31051 const msg = msg: {31102 const msg = msg: {
31052 const msg = try sema.errMsg(&block_scope, field_src, "enum tag value {} already taken", .{copied_val.fmtValue(int_tag_ty, sema.mod)});31103 const msg = try sema.errMsg(&block_scope, field_src, "enum tag value {} already taken", .{copied_val.fmtValue(int_tag_ty, sema.mod)});
31053 errdefer msg.destroy(gpa);31104 errdefer msg.destroy(gpa);
...@@ -31069,10 +31120,17 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -31069,10 +31120,17 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
31069 else if (field_type_ref == .none)31120 else if (field_type_ref == .none)
31070 Type.initTag(.noreturn)31121 Type.initTag(.noreturn)
31071 else31122 else
31072 // TODO: if we need to report an error here, use a source location31123 sema.resolveType(&block_scope, .unneeded, field_type_ref) catch |err| switch (err) {
31073 // that points to this type expression rather than the union.31124 error.NeededSourceLocation => {
31074 // But only resolve the source location if we need to emit a compile error.31125 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{
31075 try sema.resolveType(&block_scope, src, field_type_ref);31126 .index = field_i,
31127 .range = .type,
31128 }).lazy;
31129 _ = try sema.resolveType(&block_scope, ty_src, field_type_ref);
31130 unreachable;
31131 },
31132 else => |e| return e,
31133 };
3107631134
31077 if (field_ty.tag() == .generic_poison) {31135 if (field_ty.tag() == .generic_poison) {
31078 return error.GenericPoison;31136 return error.GenericPoison;
...@@ -31081,13 +31139,18 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -31081,13 +31139,18 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
31081 const gop = union_obj.fields.getOrPutAssumeCapacity(field_name);31139 const gop = union_obj.fields.getOrPutAssumeCapacity(field_name);
31082 if (gop.found_existing) {31140 if (gop.found_existing) {
31083 const msg = msg: {31141 const msg = msg: {
31084 const tree = try sema.getAstTree(&block_scope);31142 const field_src = union_obj.fieldSrcLoc(sema.mod, .{
31085 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i);31143 .index = field_i,
31144 .range = .name,
31145 }).lazy;
31086 const msg = try sema.errMsg(&block_scope, field_src, "duplicate union field: '{s}'", .{field_name});31146 const msg = try sema.errMsg(&block_scope, field_src, "duplicate union field: '{s}'", .{field_name});
31087 errdefer msg.destroy(gpa);31147 errdefer msg.destroy(gpa);
3108831148
31089 const prev_field_index = union_obj.fields.getIndex(field_name).?;31149 const prev_field_index = union_obj.fields.getIndex(field_name).?;
31090 const prev_field_src = enumFieldSrcLoc(decl, tree.*, 0, prev_field_index);31150 const prev_field_src = union_obj.fieldSrcLoc(sema.mod, .{
31151 .index = prev_field_index,
31152 .range = .name,
31153 }).lazy;
31091 try sema.mod.errNoteNonLazy(prev_field_src.toSrcLoc(decl), msg, "other field here", .{});31154 try sema.mod.errNoteNonLazy(prev_field_src.toSrcLoc(decl), msg, "other field here", .{});
31092 try sema.errNote(&block_scope, src, msg, "union declared here", .{});31155 try sema.errNote(&block_scope, src, msg, "union declared here", .{});
31093 break :msg msg;31156 break :msg msg;
...@@ -31099,9 +31162,11 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -31099,9 +31162,11 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
31099 const enum_has_field = names.orderedRemove(field_name);31162 const enum_has_field = names.orderedRemove(field_name);
31100 if (!enum_has_field) {31163 if (!enum_has_field) {
31101 const msg = msg: {31164 const msg = msg: {
31102 const tree = try sema.getAstTree(&block_scope);31165 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{
31103 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i);31166 .index = field_i,
31104 const msg = try sema.errMsg(&block_scope, field_src, "no field named '{s}' in enum '{}'", .{ field_name, union_obj.tag_ty.fmt(sema.mod) });31167 .range = .type,
31168 }).lazy;
31169 const msg = try sema.errMsg(&block_scope, ty_src, "no field named '{s}' in enum '{}'", .{ field_name, union_obj.tag_ty.fmt(sema.mod) });
31105 errdefer msg.destroy(sema.gpa);31170 errdefer msg.destroy(sema.gpa);
31106 try sema.addDeclaredHereNote(msg, union_obj.tag_ty);31171 try sema.addDeclaredHereNote(msg, union_obj.tag_ty);
31107 break :msg msg;31172 break :msg msg;
...@@ -31112,9 +31177,11 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -31112,9 +31177,11 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3111231177
31113 if (field_ty.zigTypeTag() == .Opaque) {31178 if (field_ty.zigTypeTag() == .Opaque) {
31114 const msg = msg: {31179 const msg = msg: {
31115 const tree = try sema.getAstTree(&block_scope);31180 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{
31116 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i);31181 .index = field_i,
31117 const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{});31182 .range = .type,
31183 }).lazy;
31184 const msg = try sema.errMsg(&block_scope, ty_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{});
31118 errdefer msg.destroy(sema.gpa);31185 errdefer msg.destroy(sema.gpa);
3111931186
31120 try sema.addDeclaredHereNote(msg, field_ty);31187 try sema.addDeclaredHereNote(msg, field_ty);
...@@ -31124,12 +31191,14 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -31124,12 +31191,14 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
31124 }31191 }
31125 if (union_obj.layout == .Extern and !try sema.validateExternType(field_ty, .union_field)) {31192 if (union_obj.layout == .Extern and !try sema.validateExternType(field_ty, .union_field)) {
31126 const msg = msg: {31193 const msg = msg: {
31127 const tree = try sema.getAstTree(&block_scope);31194 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{
31128 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i);31195 .index = field_i,
31129 const msg = try sema.errMsg(&block_scope, field_src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});31196 .range = .type,
31197 });
31198 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
31130 errdefer msg.destroy(sema.gpa);31199 errdefer msg.destroy(sema.gpa);
3113131200
31132 try sema.explainWhyTypeIsNotExtern(msg, field_src.toSrcLoc(decl), field_ty, .union_field);31201 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field_ty, .union_field);
3113331202
31134 try sema.addDeclaredHereNote(msg, field_ty);31203 try sema.addDeclaredHereNote(msg, field_ty);
31135 break :msg msg;31204 break :msg msg;
...@@ -31137,12 +31206,14 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -31137,12 +31206,14 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
31137 return sema.failWithOwnedErrorMsg(msg);31206 return sema.failWithOwnedErrorMsg(msg);
31138 } else if (union_obj.layout == .Packed and !(validatePackedType(field_ty))) {31207 } else if (union_obj.layout == .Packed and !(validatePackedType(field_ty))) {
31139 const msg = msg: {31208 const msg = msg: {
31140 const tree = try sema.getAstTree(&block_scope);31209 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{
31141 const fields_src = enumFieldSrcLoc(decl, tree.*, 0, field_i);31210 .index = field_i,
31142 const msg = try sema.errMsg(&block_scope, fields_src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});31211 .range = .type,
31212 });
31213 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
31143 errdefer msg.destroy(sema.gpa);31214 errdefer msg.destroy(sema.gpa);
3114431215
31145 try sema.explainWhyTypeIsNotPacked(msg, fields_src.toSrcLoc(decl), field_ty);31216 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field_ty);
3114631217
31147 try sema.addDeclaredHereNote(msg, field_ty);31218 try sema.addDeclaredHereNote(msg, field_ty);
31148 break :msg msg;31219 break :msg msg;
...@@ -31156,10 +31227,17 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -31156,10 +31227,17 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
31156 };31227 };
3115731228
31158 if (align_ref != .none) {31229 if (align_ref != .none) {
31159 // TODO: if we need to report an error here, use a source location31230 gop.value_ptr.abi_align = sema.resolveAlign(&block_scope, .unneeded, align_ref) catch |err| switch (err) {
31160 // that points to this alignment expression rather than the struct.31231 error.NeededSourceLocation => {
31161 // But only resolve the source location if we need to emit a compile error.31232 const align_src = union_obj.fieldSrcLoc(sema.mod, .{
31162 gop.value_ptr.abi_align = try sema.resolveAlign(&block_scope, src, align_ref);31233 .index = field_i,
31234 .range = .alignment,
31235 }).lazy;
31236 _ = try sema.resolveAlign(&block_scope, align_src, align_ref);
31237 unreachable;
31238 },
31239 else => |e| return e,
31240 };
31163 } else {31241 } else {
31164 gop.value_ptr.abi_align = 0;31242 gop.value_ptr.abi_align = 0;
31165 }31243 }
...@@ -31184,6 +31262,11 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -31184,6 +31262,11 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
31184 }31262 }
31185}31263}
3118631264
31265fn semaUnionFieldVal(sema: *Sema, block: *Block, src: LazySrcLoc, int_tag_ty: Type, tag_ref: Air.Inst.Ref) CompileError!Value {
31266 const coerced = try sema.coerce(block, int_tag_ty, tag_ref, src);
31267 return sema.resolveConstValue(block, src, coerced, "enum tag value must be comptime-known");
31268}
31269
31187fn generateUnionTagTypeNumbered(31270fn generateUnionTagTypeNumbered(
31188 sema: *Sema,31271 sema: *Sema,
31189 block: *Block,31272 block: *Block,
test/cases/compile_errors/directly_embedding_opaque_type_in_struct_and_union.zig+2-2
...@@ -29,9 +29,9 @@ export fn d() void {...@@ -29,9 +29,9 @@ export fn d() void {
29// backend=stage229// backend=stage2
30// target=native30// target=native
31//31//
32// :3:5: error: opaque types have unknown size and therefore cannot be directly embedded in structs32// :3:8: error: opaque types have unknown size and therefore cannot be directly embedded in structs
33// :1:11: note: opaque declared here33// :1:11: note: opaque declared here
34// :7:5: error: opaque types have unknown size and therefore cannot be directly embedded in unions34// :7:10: error: opaque types have unknown size and therefore cannot be directly embedded in unions
35// :19:18: error: opaque types have unknown size and therefore cannot be directly embedded in structs35// :19:18: error: opaque types have unknown size and therefore cannot be directly embedded in structs
36// :18:22: note: opaque declared here36// :18:22: note: opaque declared here
37// :24:23: error: opaque types have unknown size and therefore cannot be directly embedded in structs37// :24:23: error: opaque types have unknown size and therefore cannot be directly embedded in structs
test/cases/compile_errors/extern_struct_with_extern-compatible_but_inferred_integer_tag_type.zig+3-3
...@@ -39,7 +39,7 @@ export fn entry() void {...@@ -39,7 +39,7 @@ export fn entry() void {
39// backend=stage239// backend=stage2
40// target=native40// target=native
41//41//
42// :31:5: error: extern structs cannot contain fields of type 'tmp.E'42// :31:8: error: extern structs cannot contain fields of type 'tmp.E'
43// :31:5: note: enum tag type 'u9' is not extern compatible43// :31:8: note: enum tag type 'u9' is not extern compatible
44// :31:5: note: only integers with power of two bits are extern compatible44// :31:8: note: only integers with power of two bits are extern compatible
45// :1:15: note: enum declared here45// :1:15: note: enum declared here
test/cases/compile_errors/extern_struct_with_non-extern-compatible_integer_tag_type.zig+3-3
...@@ -11,7 +11,7 @@ export fn entry() void {...@@ -11,7 +11,7 @@ export fn entry() void {
11// backend=stage211// backend=stage2
12// target=native12// target=native
13//13//
14// :3:5: error: extern structs cannot contain fields of type 'tmp.E'14// :3:8: error: extern structs cannot contain fields of type 'tmp.E'
15// :3:5: note: enum tag type 'u31' is not extern compatible15// :3:8: note: enum tag type 'u31' is not extern compatible
16// :3:5: note: only integers with power of two bits are extern compatible16// :3:8: note: only integers with power of two bits are extern compatible
17// :1:15: note: enum declared here17// :1:15: note: enum declared here
test/cases/compile_errors/file_level_struct_invalid_field_type.zig created+17
...@@ -0,0 +1,17 @@
1const Parser = @This();
2fn Chunk() type {
3 return struct {
4 const Self = @This();
5 };
6}
7parser_chunk: Chunk,
8
9comptime {
10 _ = @sizeOf(@This()) + 1;
11}
12
13// error
14// backend=stage2
15// target=native
16//
17// :7:15: error: expected type 'type', found 'fn() type'
test/cases/compile_errors/invalid_optional_type_in_extern_struct.zig+2-2
...@@ -7,5 +7,5 @@ export fn testf(fluff: *stroo) void { _ = fluff; }...@@ -7,5 +7,5 @@ export fn testf(fluff: *stroo) void { _ = fluff; }
7// backend=stage27// backend=stage2
8// target=native8// target=native
9//9//
10// :2:5: error: extern structs cannot contain fields of type '?[*c]u8'10// :2:10: error: extern structs cannot contain fields of type '?[*c]u8'
11// :2:5: note: only pointer like optionals are extern compatible11// :2:10: note: only pointer like optionals are extern compatible
test/cases/compile_errors/noreturn_struct_field.zig+1-1
...@@ -9,4 +9,4 @@ comptime {...@@ -9,4 +9,4 @@ comptime {
9// backend=stage29// backend=stage2
10// target=native10// target=native
11//11//
12// :2:5: error: struct fields cannot be 'noreturn'12// :2:8: error: struct fields cannot be 'noreturn'
test/cases/compile_errors/old_fn_ptr_in_extern_context.zig+3-3
...@@ -12,9 +12,9 @@ comptime {...@@ -12,9 +12,9 @@ comptime {
12// backend=stage212// backend=stage2
13// target=native13// target=native
14//14//
15// :2:5: error: extern structs cannot contain fields of type 'fn() callconv(.C) void'15// :2:8: error: extern structs cannot contain fields of type 'fn() callconv(.C) void'
16// :2:5: note: type has no guaranteed in-memory representation16// :2:8: note: type has no guaranteed in-memory representation
17// :2:5: note: use '*const ' to make a function pointer type17// :2:8: note: use '*const ' to make a function pointer type
18// :8:13: error: C pointers cannot point to non-C-ABI-compatible type '[4]fn() callconv(.C) void'18// :8:13: error: C pointers cannot point to non-C-ABI-compatible type '[4]fn() callconv(.C) void'
19// :8:13: note: type has no guaranteed in-memory representation19// :8:13: note: type has no guaranteed in-memory representation
20// :8:13: note: use '*const ' to make a function pointer type20// :8:13: note: use '*const ' to make a function pointer type
test/cases/compile_errors/packed_struct_with_fields_of_not_allowed_types.zig+17-17
...@@ -70,22 +70,22 @@ export fn entry12() void {...@@ -70,22 +70,22 @@ export fn entry12() void {
70// backend=llvm70// backend=llvm
71// target=native71// target=native
72//72//
73// :3:9: error: packed structs cannot contain fields of type 'anyerror'73// :3:12: error: packed structs cannot contain fields of type 'anyerror'
74// :3:9: note: type has no guaranteed in-memory representation74// :3:12: note: type has no guaranteed in-memory representation
75// :8:9: error: packed structs cannot contain fields of type '[2]u24'75// :8:12: error: packed structs cannot contain fields of type '[2]u24'
76// :8:9: note: type has no guaranteed in-memory representation76// :8:12: note: type has no guaranteed in-memory representation
77// :13:9: error: packed structs cannot contain fields of type 'anyerror!u32'77// :13:20: error: packed structs cannot contain fields of type 'anyerror!u32'
78// :13:9: note: type has no guaranteed in-memory representation78// :13:20: note: type has no guaranteed in-memory representation
79// :18:9: error: packed structs cannot contain fields of type 'tmp.S'79// :18:12: error: packed structs cannot contain fields of type 'tmp.S'
80// :18:9: note: only packed structs layout are allowed in packed types80// :18:12: note: only packed structs layout are allowed in packed types
81// :56:11: note: struct declared here81// :56:11: note: struct declared here
82// :23:9: error: packed structs cannot contain fields of type 'tmp.U'82// :23:12: error: packed structs cannot contain fields of type 'tmp.U'
83// :23:9: note: only packed unions layout are allowed in packed types83// :23:12: note: only packed unions layout are allowed in packed types
84// :59:18: note: union declared here84// :59:18: note: union declared here
85// :28:9: error: packed structs cannot contain fields of type '?anyerror'85// :28:12: error: packed structs cannot contain fields of type '?anyerror'
86// :28:9: note: type has no guaranteed in-memory representation86// :28:12: note: type has no guaranteed in-memory representation
87// :38:9: error: packed structs cannot contain fields of type 'fn() void'87// :38:12: error: packed structs cannot contain fields of type 'fn() void'
88// :38:9: note: type has no guaranteed in-memory representation88// :38:12: note: type has no guaranteed in-memory representation
89// :38:9: note: use '*const ' to make a function pointer type89// :38:12: note: use '*const ' to make a function pointer type
90// :65:28: error: packed structs cannot contain fields of type '[]u8'90// :65:31: error: packed structs cannot contain fields of type '[]u8'
91// :65:28: note: slices have no guaranteed in-memory representation91// :65:31: note: slices have no guaranteed in-memory representation
test/cases/compile_errors/packed_union_with_automatic_layout_field.zig+2-2
...@@ -15,6 +15,6 @@ export fn entry() void {...@@ -15,6 +15,6 @@ export fn entry() void {
15// backend=stage215// backend=stage2
16// target=native16// target=native
17//17//
18// :6:5: error: packed unions cannot contain fields of type 'tmp.Foo'18// :6:8: error: packed unions cannot contain fields of type 'tmp.Foo'
19// :6:5: note: only packed structs layout are allowed in packed types19// :6:8: note: only packed structs layout are allowed in packed types
20// :1:13: note: struct declared here20// :1:13: note: struct declared here
test/cases/compile_errors/union_enum_field_does_not_match_enum.zig+1-1
...@@ -18,5 +18,5 @@ export fn entry() void {...@@ -18,5 +18,5 @@ export fn entry() void {
18// backend=stage218// backend=stage2
19// target=native19// target=native
20//20//
21// :10:5: error: no field named 'D' in enum 'tmp.Letter'21// :10:8: error: no field named 'D' in enum 'tmp.Letter'
22// :1:16: note: enum declared here22// :1:16: note: enum declared here
test/cases/compile_errors/union_extra_field.zig+1-1
...@@ -16,5 +16,5 @@ export fn entry() usize {...@@ -16,5 +16,5 @@ export fn entry() usize {
16// error16// error
17// target=native17// target=native
18//18//
19// :10:5: error: no field named 'd' in enum 'tmp.E'19// :10:8: error: no field named 'd' in enum 'tmp.E'
20// :1:11: note: enum declared here20// :1:11: note: enum declared here