| ... | ... | @@ -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,7 +7634,7 @@ 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), |
| ... | ... | @@ -7642,7 +7642,7 @@ fn funcCommon( |
| 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,7 +7830,7 @@ 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), |
| ... | ... | @@ -7838,7 +7838,7 @@ fn analyzeParameter( |
| 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; |
| ... | ... | @@ -15950,13 +15950,13 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 15950 | 15950 | } else if (ptr_size == .Many and elem_ty.zigTypeTag() == .Opaque) { |
| 15951 | 15951 | return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{}); |
| 15952 | 15952 | } else if (ptr_size == .C) { |
| 15953 | | if (!(try sema.validateExternType(elem_ty, .other))) { |
| 15953 | if (!sema.validateExternType(elem_ty, .other)) { |
| 15954 | 15954 | const msg = msg: { |
| 15955 | 15955 | const msg = try sema.errMsg(block, src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)}); |
| 15956 | 15956 | errdefer msg.destroy(sema.gpa); |
| 15957 | 15957 | |
| 15958 | 15958 | const src_decl = sema.mod.declPtr(block.src_decl); |
| 15959 | | try sema.explainWhyTypeIsNotExtern(block, src, msg, src.toSrcLoc(src_decl), elem_ty, .other); |
| 15959 | try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), elem_ty, .other); |
| 15960 | 15960 | |
| 15961 | 15961 | try sema.addDeclaredHereNote(msg, elem_ty); |
| 15962 | 15962 | 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 | }; |