| author | |
| committer | |
| log | 796927b900ad4b774c30d1cb545d606f23040d2f |
| tree | 7fd53185ae5dfadce29a8ab95f27d5bade0ae05c |
| parent | 8d1805f81c97a0b773772e86aa39f26c894b7985 |
| signature |
This change allows the following types to appear in extern structs:
* Zero-bit integers
* void
* zero-sized structs and packed structs
* enums with zero-bit backing integers
* arrays of any length with zero-size elements8 files changed, 33 insertions(+), 12 deletions(-)
src/Sema.zig+6-6| ... | ... | @@ -24590,7 +24590,7 @@ fn validateExternType( |
| 24590 | 24590 | .ErrorSet, |
| 24591 | 24591 | .Frame, |
| 24592 | 24592 | => return false, |
| 24593 | .Void => return position == .union_field or position == .ret_ty, | |
| 24593 | .Void => return position == .union_field or position == .ret_ty or position == .struct_field or position == .element, | |
| 24594 | 24594 | .NoReturn => return position == .ret_ty, |
| 24595 | 24595 | .Opaque, |
| 24596 | 24596 | .Bool, |
| ... | ... | @@ -24599,7 +24599,7 @@ fn validateExternType( |
| 24599 | 24599 | => return true, |
| 24600 | 24600 | .Pointer => return !(ty.isSlice(mod) or try sema.typeRequiresComptime(ty)), |
| 24601 | 24601 | .Int => switch (ty.intInfo(mod).bits) { |
| 24602 | 8, 16, 32, 64, 128 => return true, | |
| 24602 | 0, 8, 16, 32, 64, 128 => return true, | |
| 24603 | 24603 | else => return false, |
| 24604 | 24604 | }, |
| 24605 | 24605 | .Fn => { |
| ... | ... | @@ -24620,11 +24620,11 @@ fn validateExternType( |
| 24620 | 24620 | .Packed => { |
| 24621 | 24621 | const bit_size = try ty.bitSizeAdvanced(mod, sema); |
| 24622 | 24622 | switch (bit_size) { |
| 24623 | 8, 16, 32, 64, 128 => return true, | |
| 24623 | 0, 8, 16, 32, 64, 128 => return true, | |
| 24624 | 24624 | else => return false, |
| 24625 | 24625 | } |
| 24626 | 24626 | }, |
| 24627 | .Auto => return false, | |
| 24627 | .Auto => return !(try sema.typeHasRuntimeBits(ty)), | |
| 24628 | 24628 | }, |
| 24629 | 24629 | .Array => { |
| 24630 | 24630 | if (position == .ret_ty or position == .param_ty) return false; |
| ... | ... | @@ -24673,9 +24673,9 @@ fn explainWhyTypeIsNotExtern( |
| 24673 | 24673 | .Void => try mod.errNoteNonLazy(src_loc, msg, "'void' is a zero bit type; for C 'void' use 'anyopaque'", .{}), |
| 24674 | 24674 | .NoReturn => try mod.errNoteNonLazy(src_loc, msg, "'noreturn' is only allowed as a return type", .{}), |
| 24675 | 24675 | .Int => if (!std.math.isPowerOfTwo(ty.intInfo(mod).bits)) { |
| 24676 | try mod.errNoteNonLazy(src_loc, msg, "only integers with power of two bits are extern compatible", .{}); | |
| 24676 | try mod.errNoteNonLazy(src_loc, msg, "only integers with 0 or power of two bits are extern compatible", .{}); | |
| 24677 | 24677 | } else { |
| 24678 | try mod.errNoteNonLazy(src_loc, msg, "only integers with 8, 16, 32, 64 and 128 bits are extern compatible", .{}); | |
| 24678 | try mod.errNoteNonLazy(src_loc, msg, "only integers with 0, 8, 16, 32, 64 and 128 bits are extern compatible", .{}); | |
| 24679 | 24679 | }, |
| 24680 | 24680 | .Fn => { |
| 24681 | 24681 | if (position != .other) { |
test/behavior/extern_struct_zero_size_fields.zig created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | const E = enum(u0) { | |
| 2 | the_only_possible_value, | |
| 3 | }; | |
| 4 | ||
| 5 | const S = struct {}; | |
| 6 | ||
| 7 | const T = extern struct { | |
| 8 | foo: u0 = 0, | |
| 9 | bar: void = {}, | |
| 10 | baz: struct {} = .{}, | |
| 11 | ayy: E = .the_only_possible_value, | |
| 12 | arr: [0]u0 = .{}, | |
| 13 | matey: [128]void = [_]void{{}} ** 128, | |
| 14 | running_out_of_ideas: packed struct {} = .{}, | |
| 15 | one_more: [256]S = [_]S{.{}} ** 256, | |
| 16 | }; | |
| 17 | ||
| 18 | test { | |
| 19 | var t: T = .{}; | |
| 20 | _ = t; | |
| 21 | } |
test/cases/compile_errors/exported_enum_without_explicit_integer_tag_type.zig+1-1| ... | ... | @@ -14,5 +14,5 @@ comptime { |
| 14 | 14 | // :3:5: error: unable to export type 'type' |
| 15 | 15 | // :7:5: error: unable to export type 'tmp.E' |
| 16 | 16 | // :7:5: note: enum tag type 'u1' is not extern compatible |
| 17 | // :7:5: note: only integers with 8, 16, 32, 64 and 128 bits are extern compatible | |
| 17 | // :7:5: note: only integers with 0, 8, 16, 32, 64 and 128 bits are extern compatible | |
| 18 | 18 | // :1:11: note: enum declared here |
test/cases/compile_errors/extern_struct_with_extern-compatible_but_inferred_integer_tag_type.zig+1-1| ... | ... | @@ -43,5 +43,5 @@ export fn entry() void { |
| 43 | 43 | // |
| 44 | 44 | // :33:8: error: extern structs cannot contain fields of type 'tmp.E' |
| 45 | 45 | // :33:8: note: enum tag type 'u9' is not extern compatible |
| 46 | // :33:8: note: only integers with power of two bits are extern compatible | |
| 46 | // :33:8: note: only integers with 0 or power of two bits are extern compatible | |
| 47 | 47 | // :2:15: note: enum declared here |
test/cases/compile_errors/extern_struct_with_non-extern-compatible_integer_tag_type.zig+1-1| ... | ... | @@ -13,5 +13,5 @@ export fn entry() void { |
| 13 | 13 | // |
| 14 | 14 | // :3:8: error: extern structs cannot contain fields of type 'tmp.E' |
| 15 | 15 | // :3:8: note: enum tag type 'u31' is not extern compatible |
| 16 | // :3:8: note: only integers with power of two bits are extern compatible | |
| 16 | // :3:8: note: only integers with 0 or power of two bits are extern compatible | |
| 17 | 17 | // :1:15: note: enum declared here |
test/cases/compile_errors/extern_variable_has_non_extern_type.zig+1-1| ... | ... | @@ -8,4 +8,4 @@ pub export fn entry() void { |
| 8 | 8 | // target=native |
| 9 | 9 | // |
| 10 | 10 | // :1:17: error: extern variable cannot have type 'u3' |
| 11 | // :1:17: note: only integers with power of two bits are extern compatible | |
| 11 | // :1:17: note: only integers with 0 or power of two bits are extern compatible |
test/cases/compile_errors/function_with_non-extern_non-packed_enum_parameter.zig+1-1| ... | ... | @@ -9,5 +9,5 @@ export fn entry(foo: Foo) void { |
| 9 | 9 | // |
| 10 | 10 | // :2:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C' |
| 11 | 11 | // :2:17: note: enum tag type 'u2' is not extern compatible |
| 12 | // :2:17: note: only integers with 8, 16, 32, 64 and 128 bits are extern compatible | |
| 12 | // :2:17: note: only integers with 0, 8, 16, 32, 64 and 128 bits are extern compatible | |
| 13 | 13 | // :1:13: note: enum declared here |
test/cases/compile_errors/variadic_arg_validation.zig+1-1| ... | ... | @@ -24,6 +24,6 @@ pub export fn entry3() void { |
| 24 | 24 | // :4:33: error: integer and float literals passed to variadic function must be casted to a fixed-size number type |
| 25 | 25 | // :9:24: error: arrays must be passed by reference to variadic function |
| 26 | 26 | // :13:24: error: cannot pass 'u48' to variadic function |
| 27 | // :13:24: note: only integers with power of two bits are extern compatible | |
| 27 | // :13:24: note: only integers with 0 or power of two bits are extern compatible | |
| 28 | 28 | // :17:24: error: cannot pass 'void' to variadic function |
| 29 | 29 | // :17:24: note: 'void' is a zero bit type; for C 'void' use 'anyopaque' |