@@ -5048,13 +5048,13 @@ pub fn analyzeExport(
5048
5048
try mod.ensureDeclAnalyzed(exported_decl_index);
5049
5049
const exported_decl = mod.declPtr(exported_decl_index);
5050
5050
5051
- if (!(try sema.validateExternType(exported_decl.ty, .other) )) {
5051
+ if (!sema.validateExternType(exported_decl.ty, .other)) {
5052
5052
const msg = msg: {
5053
5053
const msg = try sema.errMsg(block, src, "unable to export type '{}'", .{exported_decl.ty.fmt(sema.mod)});
5054
5054
errdefer msg.destroy(sema.gpa);
5055
5055
5056
5056
const src_decl = sema.mod.declPtr(block.src_decl);
5057
- try sema.explainWhyTypeIsNotExtern(block, src, msg, src.toSrcLoc(src_decl), exported_decl.ty, .other);
5057
+ try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), exported_decl.ty, .other);
5058
5058
5059
5059
try sema.addDeclaredHereNote(msg, exported_decl.ty);
5060
5060
break :msg msg;
@@ -7633,15 +7633,15 @@ fn funcCommon(
7633
7633
};
7634
7634
return sema.failWithOwnedErrorMsg(block, msg);
7635
7635
}
7636
- if (!Type.fnCallingConventionAllowsZigTypes(cc_workaround) and !(try sema.validateExternType(return_type, .ret_ty) )) {
7636
+ if (!Type.fnCallingConventionAllowsZigTypes(cc_workaround) and !sema.validateExternType(return_type, .ret_ty)) {
7637
7637
const msg = msg: {
7638
7638
const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{
7639
7639
return_type.fmt(sema.mod), @tagName(cc_workaround),
7640
7640
});
7641
7641
errdefer msg.destroy(sema.gpa);
7642
7642
7643
7643
const src_decl = sema.mod.declPtr(block.src_decl);
7644
- try sema.explainWhyTypeIsNotExtern(block, ret_ty_src, msg, ret_ty_src.toSrcLoc(src_decl), return_type, .ret_ty);
7644
+ try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src.toSrcLoc(src_decl), return_type, .ret_ty);
7645
7645
7646
7646
try sema.addDeclaredHereNote(msg, return_type);
7647
7647
break :msg msg;
@@ -7829,15 +7829,15 @@ fn analyzeParameter(
7829
7829
};
7830
7830
return sema.failWithOwnedErrorMsg(block, msg);
7831
7831
}
7832
- if (!Type.fnCallingConventionAllowsZigTypes(cc) and !(try sema.validateExternType(param.ty, .param_ty) )) {
7832
+ if (!Type.fnCallingConventionAllowsZigTypes(cc) and !sema.validateExternType(param.ty, .param_ty)) {
7833
7833
const msg = msg: {
7834
7834
const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{
7835
7835
param.ty.fmt(sema.mod), @tagName(cc),
7836
7836
});
7837
7837
errdefer msg.destroy(sema.gpa);
7838
7838
7839
7839
const src_decl = sema.mod.declPtr(block.src_decl);
7840
- try sema.explainWhyTypeIsNotExtern(block, param_src, msg, param_src.toSrcLoc(src_decl), param.ty, .param_ty);
7840
+ try sema.explainWhyTypeIsNotExtern(msg, param_src.toSrcLoc(src_decl), param.ty, .param_ty);
7841
7841
7842
7842
try sema.addDeclaredHereNote(msg, param.ty);
7843
7843
break :msg msg;
@@ -14574,13 +14574,13 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
14574
14574
} else if (inst_data.size == .Many and elem_ty.zigTypeTag() == .Opaque) {
14575
14575
return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{});
14576
14576
} else if (inst_data.size == .C) {
14577
- if (!(try sema.validateExternType(elem_ty, .other) )) {
14577
+ if (!sema.validateExternType(elem_ty, .other)) {
14578
14578
const msg = msg: {
14579
14579
const msg = try sema.errMsg(block, elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)});
14580
14580
errdefer msg.destroy(sema.gpa);
14581
14581
14582
14582
const src_decl = sema.mod.declPtr(block.src_decl);
14583
- try sema.explainWhyTypeIsNotExtern(block, elem_ty_src, msg, elem_ty_src.toSrcLoc(src_decl), elem_ty, .other);
14583
+ try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src.toSrcLoc(src_decl), elem_ty, .other);
14584
14584
14585
14585
try sema.addDeclaredHereNote(msg, elem_ty);
14586
14586
break :msg msg;
@@ -19233,7 +19233,7 @@ const ExternPosition = enum {
19233
19233
19234
19234
/// Returns true if `ty` is allowed in extern types.
19235
19235
/// Does *NOT* require `ty` to be resolved in any way.
19236
- fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) CompileError! bool {
19236
+ fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) bool {
19237
19237
switch (ty.zigTypeTag()) {
19238
19238
.Type,
19239
19239
.ComptimeFloat,
@@ -19278,8 +19278,6 @@ fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) CompileEr
19278
19278
19279
19279
fn explainWhyTypeIsNotExtern(
19280
19280
sema: *Sema,
19281
- block: *Block,
19282
- src: LazySrcLoc,
19283
19281
msg: *Module.ErrorMsg,
19284
19282
src_loc: Module.SrcLoc,
19285
19283
ty: Type,
@@ -19323,7 +19321,7 @@ fn explainWhyTypeIsNotExtern(
19323
19321
var buf: Type.Payload.Bits = undefined;
19324
19322
const tag_ty = ty.intTagType(&buf);
19325
19323
try mod.errNoteNonLazy(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)});
19326
- try sema.explainWhyTypeIsNotExtern(block, src, msg, src_loc, tag_ty, position);
19324
+ try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position);
19327
19325
},
19328
19326
.Struct => try mod.errNoteNonLazy(src_loc, msg, "only structs with packed or extern layout are extern compatible", .{}),
19329
19327
.Union => try mod.errNoteNonLazy(src_loc, msg, "only unions with packed or extern layout are extern compatible", .{}),
@@ -19333,13 +19331,87 @@ fn explainWhyTypeIsNotExtern(
19333
19331
} else if (position == .param_ty) {
19334
19332
return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a parameter type", .{});
19335
19333
}
19336
- try sema.explainWhyTypeIsNotExtern(block, src, msg, src_loc, ty.elemType2(), position);
19334
+ try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), position);
19337
19335
},
19338
- .Vector => try sema.explainWhyTypeIsNotExtern(block, src, msg, src_loc, ty.elemType2(), position),
19336
+ .Vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), position),
19339
19337
.Optional => try mod.errNoteNonLazy(src_loc, msg, "only pointer like optionals are extern compatible", .{}),
19340
19338
}
19341
19339
}
19342
19340
19341
+ /// Returns true if `ty` is allowed in packed types.
19342
+ /// Does *NOT* require `ty` to be resolved in any way.
19343
+ fn validatePackedType(ty: Type) bool {
19344
+ switch (ty.zigTypeTag()) {
19345
+ .Type,
19346
+ .ComptimeFloat,
19347
+ .ComptimeInt,
19348
+ .EnumLiteral,
19349
+ .Undefined,
19350
+ .Null,
19351
+ .ErrorUnion,
19352
+ .ErrorSet,
19353
+ .BoundFn,
19354
+ .Frame,
19355
+ .NoReturn,
19356
+ .Opaque,
19357
+ .AnyFrame,
19358
+ .Fn,
19359
+ .Array,
19360
+ .Optional,
19361
+ => return false,
19362
+ .Void,
19363
+ .Bool,
19364
+ .Float,
19365
+ .Pointer,
19366
+ .Int,
19367
+ .Vector,
19368
+ .Enum,
19369
+ => return true,
19370
+ .Struct, .Union => return ty.containerLayout() == .Packed,
19371
+ }
19372
+ }
19373
+
19374
+ fn explainWhyTypeIsNotPacked(
19375
+ sema: *Sema,
19376
+ msg: *Module.ErrorMsg,
19377
+ src_loc: Module.SrcLoc,
19378
+ ty: Type,
19379
+ ) CompileError!void {
19380
+ const mod = sema.mod;
19381
+ switch (ty.zigTypeTag()) {
19382
+ .Void,
19383
+ .Bool,
19384
+ .Float,
19385
+ .Pointer,
19386
+ .Int,
19387
+ .Vector,
19388
+ .Enum,
19389
+ => return,
19390
+ .Type,
19391
+ .ComptimeFloat,
19392
+ .ComptimeInt,
19393
+ .EnumLiteral,
19394
+ .Undefined,
19395
+ .Null,
19396
+ .BoundFn,
19397
+ .Frame,
19398
+ .NoReturn,
19399
+ .Opaque,
19400
+ .ErrorUnion,
19401
+ .ErrorSet,
19402
+ .AnyFrame,
19403
+ .Optional,
19404
+ .Array,
19405
+ => try mod.errNoteNonLazy(src_loc, msg, "type has no guaranteed in-memory representation", .{}),
19406
+ .Fn => {
19407
+ try mod.errNoteNonLazy(src_loc, msg, "type has no guaranteed in-memory representation", .{});
19408
+ try mod.errNoteNonLazy(src_loc, msg, "use '*const ' to make a function pointer type", .{});
19409
+ },
19410
+ .Struct => try mod.errNoteNonLazy(src_loc, msg, "only packed structs layout are allowed in packed types", .{}),
19411
+ .Union => try mod.errNoteNonLazy(src_loc, msg, "only packed unions layout are allowed in packed types", .{}),
19412
+ }
19413
+ }
19414
+
19343
19415
pub const PanicId = enum {
19344
19416
unreach,
19345
19417
unwrap_null,
@@ -26271,28 +26343,41 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
26271
26343
const field = &struct_obj.fields.values()[i];
26272
26344
field.ty = try field_ty.copy(decl_arena_allocator);
26273
26345
26274
- if (struct_obj.layout == .Extern and !(try sema.validateExternType(field.ty, .other))) {
26346
+ if (field_ty.zigTypeTag() == .Opaque) {
26347
+ const msg = msg: {
26348
+ const tree = try sema.getAstTree(&block_scope);
26349
+ const field_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i);
26350
+ const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
26351
+ errdefer msg.destroy(sema.gpa);
26352
+
26353
+ try sema.addDeclaredHereNote(msg, field_ty);
26354
+ break :msg msg;
26355
+ };
26356
+ return sema.failWithOwnedErrorMsg(&block_scope, msg);
26357
+ }
26358
+ if (struct_obj.layout == .Extern and !sema.validateExternType(field.ty, .other)) {
26275
26359
const msg = msg: {
26276
26360
const tree = try sema.getAstTree(&block_scope);
26277
26361
const fields_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i);
26278
26362
const msg = try sema.errMsg(&block_scope, fields_src, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});
26279
26363
errdefer msg.destroy(sema.gpa);
26280
26364
26281
- try sema.explainWhyTypeIsNotExtern(&block_scope, fields_src, msg, fields_src.toSrcLoc(decl), field.ty, .other);
26365
+ try sema.explainWhyTypeIsNotExtern(msg, fields_src.toSrcLoc(decl), field.ty, .other);
26282
26366
26283
26367
try sema.addDeclaredHereNote(msg, field.ty);
26284
26368
break :msg msg;
26285
26369
};
26286
26370
return sema.failWithOwnedErrorMsg(&block_scope, msg);
26287
- }
26288
- if (field_ty.zigTypeTag() == .Opaque) {
26371
+ } else if (struct_obj.layout == .Packed and !(validatePackedType(field.ty))) {
26289
26372
const msg = msg: {
26290
26373
const tree = try sema.getAstTree(&block_scope);
26291
- const field_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i);
26292
- const msg = try sema.errMsg(&block_scope, field_src , "opaque types have unknown size and therefore cannot be directly embedded in structs ", .{});
26374
+ const fields_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i);
26375
+ const msg = try sema.errMsg(&block_scope, fields_src , "packed structs cannot contain fields of type '{}' ", .{field.ty.fmt(sema.mod) });
26293
26376
errdefer msg.destroy(sema.gpa);
26294
26377
26295
- try sema.addDeclaredHereNote(msg, field_ty);
26378
+ try sema.explainWhyTypeIsNotPacked(msg, fields_src.toSrcLoc(decl), field.ty);
26379
+
26380
+ try sema.addDeclaredHereNote(msg, field.ty);
26296
26381
break :msg msg;
26297
26382
};
26298
26383
return sema.failWithOwnedErrorMsg(&block_scope, msg);
@@ -26595,27 +26680,40 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
26595
26680
}
26596
26681
}
26597
26682
26598
- if (union_obj.layout == .Extern and !(try sema.validateExternType(field_ty, .union_field)) ) {
26683
+ if (field_ty.zigTypeTag() == .Opaque ) {
26599
26684
const msg = msg: {
26600
26685
const tree = try sema.getAstTree(&block_scope);
26601
26686
const field_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i);
26602
- const msg = try sema.errMsg(&block_scope, field_src, "extern unions cannot contain fields of type '{}' ", .{field_ty.fmt(sema.mod) });
26687
+ const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in unions ", .{});
26603
26688
errdefer msg.destroy(sema.gpa);
26604
26689
26605
- try sema.explainWhyTypeIsNotExtern(&block_scope, field_src, msg, field_src.toSrcLoc(decl), field_ty, .union_field);
26606
-
26607
26690
try sema.addDeclaredHereNote(msg, field_ty);
26608
26691
break :msg msg;
26609
26692
};
26610
26693
return sema.failWithOwnedErrorMsg(&block_scope, msg);
26611
26694
}
26612
- if (field_ty.zigTypeTag() == .Opaque ) {
26695
+ if (union_obj.layout == .Extern and !sema.validateExternType(field_ty, .union_field) ) {
26613
26696
const msg = msg: {
26614
26697
const tree = try sema.getAstTree(&block_scope);
26615
26698
const field_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i);
26616
- const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in unions ", .{});
26699
+ const msg = try sema.errMsg(&block_scope, field_src, "extern unions cannot contain fields of type '{}' ", .{field_ty.fmt(sema.mod) });
26617
26700
errdefer msg.destroy(sema.gpa);
26618
26701
26702
+ try sema.explainWhyTypeIsNotExtern(msg, field_src.toSrcLoc(decl), field_ty, .union_field);
26703
+
26704
+ try sema.addDeclaredHereNote(msg, field_ty);
26705
+ break :msg msg;
26706
+ };
26707
+ return sema.failWithOwnedErrorMsg(&block_scope, msg);
26708
+ } else if (union_obj.layout == .Packed and !(validatePackedType(field_ty))) {
26709
+ const msg = msg: {
26710
+ const tree = try sema.getAstTree(&block_scope);
26711
+ const fields_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i);
26712
+ const msg = try sema.errMsg(&block_scope, fields_src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
26713
+ errdefer msg.destroy(sema.gpa);
26714
+
26715
+ try sema.explainWhyTypeIsNotPacked(msg, fields_src.toSrcLoc(decl), field_ty);
26716
+
26619
26717
try sema.addDeclaredHereNote(msg, field_ty);
26620
26718
break :msg msg;
26621
26719
};
0 commit comments