diff --git a/src/Sema.zig b/src/Sema.zig index 21cbd0cf35..dd5264c6e8 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -24590,7 +24590,7 @@ fn validateExternType( .ErrorSet, .Frame, => return false, - .Void => return position == .union_field or position == .ret_ty, + .Void => return position == .union_field or position == .ret_ty or position == .struct_field or position == .element, .NoReturn => return position == .ret_ty, .Opaque, .Bool, @@ -24599,7 +24599,7 @@ fn validateExternType( => return true, .Pointer => return !(ty.isSlice(mod) or try sema.typeRequiresComptime(ty)), .Int => switch (ty.intInfo(mod).bits) { - 8, 16, 32, 64, 128 => return true, + 0, 8, 16, 32, 64, 128 => return true, else => return false, }, .Fn => { @@ -24620,11 +24620,11 @@ fn validateExternType( .Packed => { const bit_size = try ty.bitSizeAdvanced(mod, sema); switch (bit_size) { - 8, 16, 32, 64, 128 => return true, + 0, 8, 16, 32, 64, 128 => return true, else => return false, } }, - .Auto => return false, + .Auto => return !(try sema.typeHasRuntimeBits(ty)), }, .Array => { if (position == .ret_ty or position == .param_ty) return false; @@ -24673,9 +24673,9 @@ fn explainWhyTypeIsNotExtern( .Void => try mod.errNoteNonLazy(src_loc, msg, "'void' is a zero bit type; for C 'void' use 'anyopaque'", .{}), .NoReturn => try mod.errNoteNonLazy(src_loc, msg, "'noreturn' is only allowed as a return type", .{}), .Int => if (!std.math.isPowerOfTwo(ty.intInfo(mod).bits)) { - try mod.errNoteNonLazy(src_loc, msg, "only integers with power of two bits are extern compatible", .{}); + try mod.errNoteNonLazy(src_loc, msg, "only integers with 0 or power of two bits are extern compatible", .{}); } else { - try mod.errNoteNonLazy(src_loc, msg, "only integers with 8, 16, 32, 64 and 128 bits are extern compatible", .{}); + try mod.errNoteNonLazy(src_loc, msg, "only integers with 0, 8, 16, 32, 64 and 128 bits are extern compatible", .{}); }, .Fn => { if (position != .other) { diff --git a/test/behavior/extern_struct_zero_size_fields.zig b/test/behavior/extern_struct_zero_size_fields.zig new file mode 100644 index 0000000000..1b13532f11 --- /dev/null +++ b/test/behavior/extern_struct_zero_size_fields.zig @@ -0,0 +1,21 @@ +const E = enum(u0) { + the_only_possible_value, +}; + +const S = struct {}; + +const T = extern struct { + foo: u0 = 0, + bar: void = {}, + baz: struct {} = .{}, + ayy: E = .the_only_possible_value, + arr: [0]u0 = .{}, + matey: [128]void = [_]void{{}} ** 128, + running_out_of_ideas: packed struct {} = .{}, + one_more: [256]S = [_]S{.{}} ** 256, +}; + +test { + var t: T = .{}; + _ = t; +} diff --git a/test/cases/compile_errors/exported_enum_without_explicit_integer_tag_type.zig b/test/cases/compile_errors/exported_enum_without_explicit_integer_tag_type.zig index 98a98f7e13..534f674fb2 100644 --- a/test/cases/compile_errors/exported_enum_without_explicit_integer_tag_type.zig +++ b/test/cases/compile_errors/exported_enum_without_explicit_integer_tag_type.zig @@ -14,5 +14,5 @@ comptime { // :3:5: error: unable to export type 'type' // :7:5: error: unable to export type 'tmp.E' // :7:5: note: enum tag type 'u1' is not extern compatible -// :7:5: note: only integers with 8, 16, 32, 64 and 128 bits are extern compatible +// :7:5: note: only integers with 0, 8, 16, 32, 64 and 128 bits are extern compatible // :1:11: note: enum declared here diff --git a/test/cases/compile_errors/extern_struct_with_extern-compatible_but_inferred_integer_tag_type.zig b/test/cases/compile_errors/extern_struct_with_extern-compatible_but_inferred_integer_tag_type.zig index 2faa7c8713..beee31721c 100644 --- a/test/cases/compile_errors/extern_struct_with_extern-compatible_but_inferred_integer_tag_type.zig +++ b/test/cases/compile_errors/extern_struct_with_extern-compatible_but_inferred_integer_tag_type.zig @@ -43,5 +43,5 @@ export fn entry() void { // // :33:8: error: extern structs cannot contain fields of type 'tmp.E' // :33:8: note: enum tag type 'u9' is not extern compatible -// :33:8: note: only integers with power of two bits are extern compatible +// :33:8: note: only integers with 0 or power of two bits are extern compatible // :2:15: note: enum declared here diff --git a/test/cases/compile_errors/extern_struct_with_non-extern-compatible_integer_tag_type.zig b/test/cases/compile_errors/extern_struct_with_non-extern-compatible_integer_tag_type.zig index a83edb6289..fd418566bc 100644 --- a/test/cases/compile_errors/extern_struct_with_non-extern-compatible_integer_tag_type.zig +++ b/test/cases/compile_errors/extern_struct_with_non-extern-compatible_integer_tag_type.zig @@ -13,5 +13,5 @@ export fn entry() void { // // :3:8: error: extern structs cannot contain fields of type 'tmp.E' // :3:8: note: enum tag type 'u31' is not extern compatible -// :3:8: note: only integers with power of two bits are extern compatible +// :3:8: note: only integers with 0 or power of two bits are extern compatible // :1:15: note: enum declared here diff --git a/test/cases/compile_errors/extern_variable_has_non_extern_type.zig b/test/cases/compile_errors/extern_variable_has_non_extern_type.zig index a572e77c28..ab460934e0 100644 --- a/test/cases/compile_errors/extern_variable_has_non_extern_type.zig +++ b/test/cases/compile_errors/extern_variable_has_non_extern_type.zig @@ -8,4 +8,4 @@ pub export fn entry() void { // target=native // // :1:17: error: extern variable cannot have type 'u3' -// :1:17: note: only integers with power of two bits are extern compatible +// :1:17: note: only integers with 0 or power of two bits are extern compatible diff --git a/test/cases/compile_errors/function_with_non-extern_non-packed_enum_parameter.zig b/test/cases/compile_errors/function_with_non-extern_non-packed_enum_parameter.zig index ae347470f2..ab257ead71 100644 --- a/test/cases/compile_errors/function_with_non-extern_non-packed_enum_parameter.zig +++ b/test/cases/compile_errors/function_with_non-extern_non-packed_enum_parameter.zig @@ -9,5 +9,5 @@ export fn entry(foo: Foo) void { // // :2:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C' // :2:17: note: enum tag type 'u2' is not extern compatible -// :2:17: note: only integers with 8, 16, 32, 64 and 128 bits are extern compatible +// :2:17: note: only integers with 0, 8, 16, 32, 64 and 128 bits are extern compatible // :1:13: note: enum declared here diff --git a/test/cases/compile_errors/variadic_arg_validation.zig b/test/cases/compile_errors/variadic_arg_validation.zig index bddcef92f6..2e47a4fc1e 100644 --- a/test/cases/compile_errors/variadic_arg_validation.zig +++ b/test/cases/compile_errors/variadic_arg_validation.zig @@ -24,6 +24,6 @@ pub export fn entry3() void { // :4:33: error: integer and float literals passed to variadic function must be casted to a fixed-size number type // :9:24: error: arrays must be passed by reference to variadic function // :13:24: error: cannot pass 'u48' to variadic function -// :13:24: note: only integers with power of two bits are extern compatible +// :13:24: note: only integers with 0 or power of two bits are extern compatible // :17:24: error: cannot pass 'void' to variadic function // :17:24: note: 'void' is a zero bit type; for C 'void' use 'anyopaque'