| ... | @@ -21232,6 +21232,8 @@ const ExternPosition = enum { | ... | @@ -21232,6 +21232,8 @@ const ExternPosition = enum { |
| 21232 | ret_ty, | 21232 | ret_ty, |
| 21233 | param_ty, | 21233 | param_ty, |
| 21234 | union_field, | 21234 | union_field, |
| | 21235 | struct_field, |
| | 21236 | element, |
| 21235 | other, | 21237 | other, |
| 21236 | }; | 21238 | }; |
| 21237 | | 21239 | |
| ... | @@ -21269,7 +21271,10 @@ fn validateExternType( | ... | @@ -21269,7 +21271,10 @@ fn validateExternType( |
| 21269 | 8, 16, 32, 64, 128 => return true, | 21271 | 8, 16, 32, 64, 128 => return true, |
| 21270 | else => return false, | 21272 | else => return false, |
| 21271 | }, | 21273 | }, |
| 21272 | .Fn => return !Type.fnCallingConventionAllowsZigTypes(ty.fnCallingConvention()), | 21274 | .Fn => { |
| | 21275 | if (position != .other) return false; |
| | 21276 | return !Type.fnCallingConventionAllowsZigTypes(ty.fnCallingConvention()); |
| | 21277 | }, |
| 21273 | .Enum => { | 21278 | .Enum => { |
| 21274 | var buf: Type.Payload.Bits = undefined; | 21279 | var buf: Type.Payload.Bits = undefined; |
| 21275 | return sema.validateExternType(block, src, ty.intTagType(&buf), position); | 21280 | return sema.validateExternType(block, src, ty.intTagType(&buf), position); |
| ... | @@ -21288,9 +21293,9 @@ fn validateExternType( | ... | @@ -21288,9 +21293,9 @@ fn validateExternType( |
| 21288 | }, | 21293 | }, |
| 21289 | .Array => { | 21294 | .Array => { |
| 21290 | if (position == .ret_ty or position == .param_ty) return false; | 21295 | if (position == .ret_ty or position == .param_ty) return false; |
| 21291 | return sema.validateExternType(block, src, ty.elemType2(), .other); | 21296 | return sema.validateExternType(block, src, ty.elemType2(), .element); |
| 21292 | }, | 21297 | }, |
| 21293 | .Vector => return sema.validateExternType(block, src, ty.elemType2(), .other), | 21298 | .Vector => return sema.validateExternType(block, src, ty.elemType2(), .element), |
| 21294 | .Optional => return ty.isPtrLikeOptional(), | 21299 | .Optional => return ty.isPtrLikeOptional(), |
| 21295 | } | 21300 | } |
| 21296 | } | 21301 | } |
| ... | @@ -21330,11 +21335,18 @@ fn explainWhyTypeIsNotExtern( | ... | @@ -21330,11 +21335,18 @@ fn explainWhyTypeIsNotExtern( |
| 21330 | } else { | 21335 | } else { |
| 21331 | try mod.errNoteNonLazy(src_loc, msg, "only integers with power of two bits are extern compatible", .{}); | 21336 | try mod.errNoteNonLazy(src_loc, msg, "only integers with power of two bits are extern compatible", .{}); |
| 21332 | }, | 21337 | }, |
| 21333 | .Fn => switch (ty.fnCallingConvention()) { | 21338 | .Fn => { |
| 21334 | .Unspecified => try mod.errNoteNonLazy(src_loc, msg, "extern function must specify calling convention", .{}), | 21339 | if (position != .other) { |
| 21335 | .Async => try mod.errNoteNonLazy(src_loc, msg, "async function cannot be extern", .{}), | 21340 | try mod.errNoteNonLazy(src_loc, msg, "type has no guaranteed in-memory representation", .{}); |
| 21336 | .Inline => try mod.errNoteNonLazy(src_loc, msg, "inline function cannot be extern", .{}), | 21341 | try mod.errNoteNonLazy(src_loc, msg, "use '*const ' to make a function pointer type", .{}); |
| 21337 | else => return, | 21342 | return; |
| | 21343 | } |
| | 21344 | switch (ty.fnCallingConvention()) { |
| | 21345 | .Unspecified => try mod.errNoteNonLazy(src_loc, msg, "extern function must specify calling convention", .{}), |
| | 21346 | .Async => try mod.errNoteNonLazy(src_loc, msg, "async function cannot be extern", .{}), |
| | 21347 | .Inline => try mod.errNoteNonLazy(src_loc, msg, "inline function cannot be extern", .{}), |
| | 21348 | else => return, |
| | 21349 | } |
| 21338 | }, | 21350 | }, |
| 21339 | .Enum => { | 21351 | .Enum => { |
| 21340 | var buf: Type.Payload.Bits = undefined; | 21352 | var buf: Type.Payload.Bits = undefined; |
| ... | @@ -21350,9 +21362,9 @@ fn explainWhyTypeIsNotExtern( | ... | @@ -21350,9 +21362,9 @@ fn explainWhyTypeIsNotExtern( |
| 21350 | } else if (position == .param_ty) { | 21362 | } else if (position == .param_ty) { |
| 21351 | return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a parameter type", .{}); | 21363 | return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a parameter type", .{}); |
| 21352 | } | 21364 | } |
| 21353 | try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), position); | 21365 | try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), .element); |
| 21354 | }, | 21366 | }, |
| 21355 | .Vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), position), | 21367 | .Vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), .element), |
| 21356 | .Optional => try mod.errNoteNonLazy(src_loc, msg, "only pointer like optionals are extern compatible", .{}), | 21368 | .Optional => try mod.errNoteNonLazy(src_loc, msg, "only pointer like optionals are extern compatible", .{}), |
| 21357 | } | 21369 | } |
| 21358 | } | 21370 | } |
| ... | @@ -24849,13 +24861,13 @@ fn coerceVarArgParam( | ... | @@ -24849,13 +24861,13 @@ fn coerceVarArgParam( |
| 24849 | }; | 24861 | }; |
| 24850 | | 24862 | |
| 24851 | const coerced_ty = sema.typeOf(coerced); | 24863 | const coerced_ty = sema.typeOf(coerced); |
| 24852 | if (!try sema.validateExternType(block, inst_src, coerced_ty, .other)) { | 24864 | if (!try sema.validateExternType(block, inst_src, coerced_ty, .param_ty)) { |
| 24853 | const msg = msg: { | 24865 | const msg = msg: { |
| 24854 | const msg = try sema.errMsg(block, inst_src, "cannot pass '{}' to variadic function", .{coerced_ty.fmt(sema.mod)}); | 24866 | const msg = try sema.errMsg(block, inst_src, "cannot pass '{}' to variadic function", .{coerced_ty.fmt(sema.mod)}); |
| 24855 | errdefer msg.destroy(sema.gpa); | 24867 | errdefer msg.destroy(sema.gpa); |
| 24856 | | 24868 | |
| 24857 | const src_decl = sema.mod.declPtr(block.src_decl); | 24869 | const src_decl = sema.mod.declPtr(block.src_decl); |
| 24858 | try sema.explainWhyTypeIsNotExtern(msg, inst_src.toSrcLoc(src_decl), coerced_ty, .other); | 24870 | try sema.explainWhyTypeIsNotExtern(msg, inst_src.toSrcLoc(src_decl), coerced_ty, .param_ty); |
| 24859 | | 24871 | |
| 24860 | try sema.addDeclaredHereNote(msg, coerced_ty); | 24872 | try sema.addDeclaredHereNote(msg, coerced_ty); |
| 24861 | break :msg msg; | 24873 | break :msg msg; |
| ... | @@ -29144,14 +29156,14 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void | ... | @@ -29144,14 +29156,14 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 29144 | }; | 29156 | }; |
| 29145 | return sema.failWithOwnedErrorMsg(msg); | 29157 | return sema.failWithOwnedErrorMsg(msg); |
| 29146 | } | 29158 | } |
| 29147 | if (struct_obj.layout == .Extern and !try sema.validateExternType(&block_scope, src, field.ty, .other)) { | 29159 | if (struct_obj.layout == .Extern and !try sema.validateExternType(&block_scope, src, field.ty, .struct_field)) { |
| 29148 | const msg = msg: { | 29160 | const msg = msg: { |
| 29149 | const tree = try sema.getAstTree(&block_scope); | 29161 | const tree = try sema.getAstTree(&block_scope); |
| 29150 | const fields_src = enumFieldSrcLoc(decl, tree.*, 0, i); | 29162 | const fields_src = enumFieldSrcLoc(decl, tree.*, 0, i); |
| 29151 | const msg = try sema.errMsg(&block_scope, fields_src, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)}); | 29163 | const msg = try sema.errMsg(&block_scope, fields_src, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)}); |
| 29152 | errdefer msg.destroy(sema.gpa); | 29164 | errdefer msg.destroy(sema.gpa); |
| 29153 | | 29165 | |
| 29154 | try sema.explainWhyTypeIsNotExtern(msg, fields_src.toSrcLoc(decl), field.ty, .other); | 29166 | try sema.explainWhyTypeIsNotExtern(msg, fields_src.toSrcLoc(decl), field.ty, .struct_field); |
| 29155 | | 29167 | |
| 29156 | try sema.addDeclaredHereNote(msg, field.ty); | 29168 | try sema.addDeclaredHereNote(msg, field.ty); |
| 29157 | break :msg msg; | 29169 | break :msg msg; |