@@ -5049,13 +5049,13 @@ pub fn analyzeExport(
5049
5049
try mod.ensureDeclAnalyzed(exported_decl_index);
5050
5050
const exported_decl = mod.declPtr(exported_decl_index);
5051
5051
5052
- if (!(try sema.validateExternType(exported_decl.ty, .other) )) {
5052
+ if (!sema.validateExternType(exported_decl.ty, .other)) {
5053
5053
const msg = msg: {
5054
5054
const msg = try sema.errMsg(block, src, "unable to export type '{}'", .{exported_decl.ty.fmt(sema.mod)});
5055
5055
errdefer msg.destroy(sema.gpa);
5056
5056
5057
5057
const src_decl = sema.mod.declPtr(block.src_decl);
5058
- try sema.explainWhyTypeIsNotExtern(block, src, msg, src.toSrcLoc(src_decl), exported_decl.ty, .other);
5058
+ try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), exported_decl.ty, .other);
5059
5059
5060
5060
try sema.addDeclaredHereNote(msg, exported_decl.ty);
5061
5061
break :msg msg;
@@ -7634,15 +7634,15 @@ fn funcCommon(
7634
7634
};
7635
7635
return sema.failWithOwnedErrorMsg(block, msg);
7636
7636
}
7637
- if (!Type.fnCallingConventionAllowsZigTypes(cc_workaround) and !(try sema.validateExternType(return_type, .ret_ty) )) {
7637
+ if (!Type.fnCallingConventionAllowsZigTypes(cc_workaround) and !sema.validateExternType(return_type, .ret_ty)) {
7638
7638
const msg = msg: {
7639
7639
const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{
7640
7640
return_type.fmt(sema.mod), @tagName(cc_workaround),
7641
7641
});
7642
7642
errdefer msg.destroy(sema.gpa);
7643
7643
7644
7644
const src_decl = sema.mod.declPtr(block.src_decl);
7645
- try sema.explainWhyTypeIsNotExtern(block, ret_ty_src, msg, ret_ty_src.toSrcLoc(src_decl), return_type, .ret_ty);
7645
+ try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src.toSrcLoc(src_decl), return_type, .ret_ty);
7646
7646
7647
7647
try sema.addDeclaredHereNote(msg, return_type);
7648
7648
break :msg msg;
@@ -7830,15 +7830,15 @@ fn analyzeParameter(
7830
7830
};
7831
7831
return sema.failWithOwnedErrorMsg(block, msg);
7832
7832
}
7833
- if (!Type.fnCallingConventionAllowsZigTypes(cc) and !(try sema.validateExternType(param.ty, .param_ty) )) {
7833
+ if (!Type.fnCallingConventionAllowsZigTypes(cc) and !sema.validateExternType(param.ty, .param_ty)) {
7834
7834
const msg = msg: {
7835
7835
const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{
7836
7836
param.ty.fmt(sema.mod), @tagName(cc),
7837
7837
});
7838
7838
errdefer msg.destroy(sema.gpa);
7839
7839
7840
7840
const src_decl = sema.mod.declPtr(block.src_decl);
7841
- try sema.explainWhyTypeIsNotExtern(block, param_src, msg, param_src.toSrcLoc(src_decl), param.ty, .param_ty);
7841
+ try sema.explainWhyTypeIsNotExtern(msg, param_src.toSrcLoc(src_decl), param.ty, .param_ty);
7842
7842
7843
7843
try sema.addDeclaredHereNote(msg, param.ty);
7844
7844
break :msg msg;
@@ -14866,13 +14866,13 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
14866
14866
} else if (inst_data.size == .Many and elem_ty.zigTypeTag() == .Opaque) {
14867
14867
return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{});
14868
14868
} else if (inst_data.size == .C) {
14869
- if (!(try sema.validateExternType(elem_ty, .other) )) {
14869
+ if (!sema.validateExternType(elem_ty, .other)) {
14870
14870
const msg = msg: {
14871
14871
const msg = try sema.errMsg(block, elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)});
14872
14872
errdefer msg.destroy(sema.gpa);
14873
14873
14874
14874
const src_decl = sema.mod.declPtr(block.src_decl);
14875
- try sema.explainWhyTypeIsNotExtern(block, elem_ty_src, msg, elem_ty_src.toSrcLoc(src_decl), elem_ty, .other);
14875
+ try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src.toSrcLoc(src_decl), elem_ty, .other);
14876
14876
14877
14877
try sema.addDeclaredHereNote(msg, elem_ty);
14878
14878
break :msg msg;
@@ -19736,7 +19736,7 @@ const ExternPosition = enum {
19736
19736
19737
19737
/// Returns true if `ty` is allowed in extern types.
19738
19738
/// Does *NOT* require `ty` to be resolved in any way.
19739
- fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) CompileError! bool {
19739
+ fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) bool {
19740
19740
switch (ty.zigTypeTag()) {
19741
19741
.Type,
19742
19742
.ComptimeFloat,
@@ -19781,8 +19781,6 @@ fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) CompileEr
19781
19781
19782
19782
fn explainWhyTypeIsNotExtern(
19783
19783
sema: *Sema,
19784
- block: *Block,
19785
- src: LazySrcLoc,
19786
19784
msg: *Module.ErrorMsg,
19787
19785
src_loc: Module.SrcLoc,
19788
19786
ty: Type,
@@ -19826,7 +19824,7 @@ fn explainWhyTypeIsNotExtern(
19826
19824
var buf: Type.Payload.Bits = undefined;
19827
19825
const tag_ty = ty.intTagType(&buf);
19828
19826
try mod.errNoteNonLazy(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)});
19829
- try sema.explainWhyTypeIsNotExtern(block, src, msg, src_loc, tag_ty, position);
19827
+ try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position);
19830
19828
},
19831
19829
.Struct => try mod.errNoteNonLazy(src_loc, msg, "only structs with packed or extern layout are extern compatible", .{}),
19832
19830
.Union => try mod.errNoteNonLazy(src_loc, msg, "only unions with packed or extern layout are extern compatible", .{}),
@@ -19836,13 +19834,87 @@ fn explainWhyTypeIsNotExtern(
19836
19834
} else if (position == .param_ty) {
19837
19835
return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a parameter type", .{});
19838
19836
}
19839
- try sema.explainWhyTypeIsNotExtern(block, src, msg, src_loc, ty.elemType2(), position);
19837
+ try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), position);
19840
19838
},
19841
- .Vector => try sema.explainWhyTypeIsNotExtern(block, src, msg, src_loc, ty.elemType2(), position),
19839
+ .Vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), position),
19842
19840
.Optional => try mod.errNoteNonLazy(src_loc, msg, "only pointer like optionals are extern compatible", .{}),
19843
19841
}
19844
19842
}
19845
19843
19844
+ /// Returns true if `ty` is allowed in packed types.
19845
+ /// Does *NOT* require `ty` to be resolved in any way.
19846
+ fn validatePackedType(ty: Type) bool {
19847
+ switch (ty.zigTypeTag()) {
19848
+ .Type,
19849
+ .ComptimeFloat,
19850
+ .ComptimeInt,
19851
+ .EnumLiteral,
19852
+ .Undefined,
19853
+ .Null,
19854
+ .ErrorUnion,
19855
+ .ErrorSet,
19856
+ .BoundFn,
19857
+ .Frame,
19858
+ .NoReturn,
19859
+ .Opaque,
19860
+ .AnyFrame,
19861
+ .Fn,
19862
+ .Array,
19863
+ .Optional,
19864
+ => return false,
19865
+ .Void,
19866
+ .Bool,
19867
+ .Float,
19868
+ .Pointer,
19869
+ .Int,
19870
+ .Vector,
19871
+ .Enum,
19872
+ => return true,
19873
+ .Struct, .Union => return ty.containerLayout() == .Packed,
19874
+ }
19875
+ }
19876
+
19877
+ fn explainWhyTypeIsNotPacked(
19878
+ sema: *Sema,
19879
+ msg: *Module.ErrorMsg,
19880
+ src_loc: Module.SrcLoc,
19881
+ ty: Type,
19882
+ ) CompileError!void {
19883
+ const mod = sema.mod;
19884
+ switch (ty.zigTypeTag()) {
19885
+ .Void,
19886
+ .Bool,
19887
+ .Float,
19888
+ .Pointer,
19889
+ .Int,
19890
+ .Vector,
19891
+ .Enum,
19892
+ => return,
19893
+ .Type,
19894
+ .ComptimeFloat,
19895
+ .ComptimeInt,
19896
+ .EnumLiteral,
19897
+ .Undefined,
19898
+ .Null,
19899
+ .BoundFn,
19900
+ .Frame,
19901
+ .NoReturn,
19902
+ .Opaque,
19903
+ .ErrorUnion,
19904
+ .ErrorSet,
19905
+ .AnyFrame,
19906
+ .Optional,
19907
+ .Array,
19908
+ => try mod.errNoteNonLazy(src_loc, msg, "type has no guaranteed in-memory representation", .{}),
19909
+ .Fn => {
19910
+ try mod.errNoteNonLazy(src_loc, msg, "type has no guaranteed in-memory representation", .{});
19911
+ try mod.errNoteNonLazy(src_loc, msg, "use '*const ' to make a function pointer type", .{});
19912
+ },
19913
+ .Struct => try mod.errNoteNonLazy(src_loc, msg, "only packed structs layout are allowed in packed types", .{}),
19914
+ .Union => try mod.errNoteNonLazy(src_loc, msg, "only packed unions layout are allowed in packed types", .{}),
19915
+ }
19916
+ }
19917
+
19846
19918
pub const PanicId = enum {
19847
19919
unreach,
19848
19920
unwrap_null,
@@ -26919,28 +26991,41 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
26919
26991
const field = &struct_obj.fields.values()[i];
26920
26992
field.ty = try field_ty.copy(decl_arena_allocator);
26921
26993
26922
- if (struct_obj.layout == .Extern and !(try sema.validateExternType(field.ty, .other))) {
26994
+ if (field_ty.zigTypeTag() == .Opaque) {
26995
+ const msg = msg: {
26996
+ const tree = try sema.getAstTree(&block_scope);
26997
+ const field_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i);
26998
+ const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
26999
+ errdefer msg.destroy(sema.gpa);
27000
+
27001
+ try sema.addDeclaredHereNote(msg, field_ty);
27002
+ break :msg msg;
27003
+ };
27004
+ return sema.failWithOwnedErrorMsg(&block_scope, msg);
27005
+ }
27006
+ if (struct_obj.layout == .Extern and !sema.validateExternType(field.ty, .other)) {
26923
27007
const msg = msg: {
26924
27008
const tree = try sema.getAstTree(&block_scope);
26925
27009
const fields_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i);
26926
27010
const msg = try sema.errMsg(&block_scope, fields_src, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});
26927
27011
errdefer msg.destroy(sema.gpa);
26928
27012
26929
- try sema.explainWhyTypeIsNotExtern(&block_scope, fields_src, msg, fields_src.toSrcLoc(decl), field.ty, .other);
27013
+ try sema.explainWhyTypeIsNotExtern(msg, fields_src.toSrcLoc(decl), field.ty, .other);
26930
27014
26931
27015
try sema.addDeclaredHereNote(msg, field.ty);
26932
27016
break :msg msg;
26933
27017
};
26934
27018
return sema.failWithOwnedErrorMsg(&block_scope, msg);
26935
- }
26936
- if (field_ty.zigTypeTag() == .Opaque) {
27019
+ } else if (struct_obj.layout == .Packed and !(validatePackedType(field.ty))) {
26937
27020
const msg = msg: {
26938
27021
const tree = try sema.getAstTree(&block_scope);
26939
- const field_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i);
26940
- const msg = try sema.errMsg(&block_scope, field_src , "opaque types have unknown size and therefore cannot be directly embedded in structs ", .{});
27022
+ const fields_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i);
27023
+ const msg = try sema.errMsg(&block_scope, fields_src , "packed structs cannot contain fields of type '{}' ", .{field.ty.fmt(sema.mod) });
26941
27024
errdefer msg.destroy(sema.gpa);
26942
27025
26943
- try sema.addDeclaredHereNote(msg, field_ty);
27026
+ try sema.explainWhyTypeIsNotPacked(msg, fields_src.toSrcLoc(decl), field.ty);
27027
+
27028
+ try sema.addDeclaredHereNote(msg, field.ty);
26944
27029
break :msg msg;
26945
27030
};
26946
27031
return sema.failWithOwnedErrorMsg(&block_scope, msg);
@@ -27243,27 +27328,40 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
27243
27328
}
27244
27329
}
27245
27330
27246
- if (union_obj.layout == .Extern and !(try sema.validateExternType(field_ty, .union_field)) ) {
27331
+ if (field_ty.zigTypeTag() == .Opaque ) {
27247
27332
const msg = msg: {
27248
27333
const tree = try sema.getAstTree(&block_scope);
27249
27334
const field_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i);
27250
- const msg = try sema.errMsg(&block_scope, field_src, "extern unions cannot contain fields of type '{}' ", .{field_ty.fmt(sema.mod) });
27335
+ const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in unions ", .{});
27251
27336
errdefer msg.destroy(sema.gpa);
27252
27337
27253
- try sema.explainWhyTypeIsNotExtern(&block_scope, field_src, msg, field_src.toSrcLoc(decl), field_ty, .union_field);
27254
-
27255
27338
try sema.addDeclaredHereNote(msg, field_ty);
27256
27339
break :msg msg;
27257
27340
};
27258
27341
return sema.failWithOwnedErrorMsg(&block_scope, msg);
27259
27342
}
27260
- if (field_ty.zigTypeTag() == .Opaque ) {
27343
+ if (union_obj.layout == .Extern and !sema.validateExternType(field_ty, .union_field) ) {
27261
27344
const msg = msg: {
27262
27345
const tree = try sema.getAstTree(&block_scope);
27263
27346
const field_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i);
27264
- const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in unions ", .{});
27347
+ const msg = try sema.errMsg(&block_scope, field_src, "extern unions cannot contain fields of type '{}' ", .{field_ty.fmt(sema.mod) });
27265
27348
errdefer msg.destroy(sema.gpa);
27266
27349
27350
+ try sema.explainWhyTypeIsNotExtern(msg, field_src.toSrcLoc(decl), field_ty, .union_field);
27351
+
27352
+ try sema.addDeclaredHereNote(msg, field_ty);
27353
+ break :msg msg;
27354
+ };
27355
+ return sema.failWithOwnedErrorMsg(&block_scope, msg);
27356
+ } else if (union_obj.layout == .Packed and !(validatePackedType(field_ty))) {
27357
+ const msg = msg: {
27358
+ const tree = try sema.getAstTree(&block_scope);
27359
+ const fields_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i);
27360
+ const msg = try sema.errMsg(&block_scope, fields_src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
27361
+ errdefer msg.destroy(sema.gpa);
27362
+
27363
+ try sema.explainWhyTypeIsNotPacked(msg, fields_src.toSrcLoc(decl), field_ty);
27364
+
27267
27365
try sema.addDeclaredHereNote(msg, field_ty);
27268
27366
break :msg msg;
27269
27367
};
0 commit comments