aboutsummaryrefslogtreecommitdiff
path: root/test/behavior/struct.zig
diff options
context:
space:
mode:
authorkcbanner <kcbanner@gmail.com>2023-10-21 16:49:30 -0400
committermlugg <mlugg@mlugg.co.uk>2023-11-07 00:49:35 +0000
commitf10499be0a16ec58d98387b49189401f2af2094f (patch)
tree1dee8acd698e9bb489a9926004d4cdf16f7ce72d /test/behavior/struct.zig
parent234693bcbba6f55ff6e975ddbedf0fad4dfaa8f1 (diff)
downloadzig-f10499be0a16ec58d98387b49189401f2af2094f.tar.gz
zig-f10499be0a16ec58d98387b49189401f2af2094f.zip
sema: analyze field init bodies in a second pass
This change allows struct field inits to use layout information of their own struct without causing a circular dependency. `semaStructFields` caches the ranges of the init bodies in the `StructType` trailing data. The init bodies are then resolved by `resolveStructFieldInits`, which is called before the inits are actually required. Within the init bodies, the struct decl's instruction is repurposed to refer to the field type itself. This is to allow us to easily rebuild the inst_map mapping required for the init body instructions to refer to the field type. Thanks to @mlugg for the guidance on this one!
Diffstat (limited to 'test/behavior/struct.zig')
-rw-r--r--test/behavior/struct.zig57
1 files changed, 57 insertions, 0 deletions
diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig
index e07b10054c..7b2587b3d6 100644
--- a/test/behavior/struct.zig
+++ b/test/behavior/struct.zig
@@ -1785,3 +1785,60 @@ test "comptimeness of optional and error union payload is analyzed properly" {
const x = (try c).?.x;
try std.testing.expectEqual(3, x);
}
+
+test "initializer uses own alignment" {
+ const S = struct {
+ x: u32 = @alignOf(@This()) + 1,
+ };
+
+ var s: S = .{};
+ try expectEqual(4, @alignOf(S));
+ try expectEqual(@as(usize, 5), s.x);
+}
+
+test "initializer uses own size" {
+ const S = struct {
+ x: u32 = @sizeOf(@This()) + 1,
+ };
+
+ var s: S = .{};
+ try expectEqual(4, @sizeOf(S));
+ try expectEqual(@as(usize, 5), s.x);
+}
+
+test "initializer takes a pointer to a variable inside its struct" {
+ const namespace = struct {
+ const S = struct {
+ s: *S = &S.instance,
+ var instance: S = undefined;
+ };
+
+ fn doTheTest() !void {
+ var foo: S = .{};
+ try expectEqual(&S.instance, foo.s);
+ }
+ };
+
+ try namespace.doTheTest();
+ comptime try namespace.doTheTest();
+}
+
+test "circular dependency through pointer field of a struct" {
+ const S = struct {
+ const StructInner = extern struct {
+ outer: StructOuter = std.mem.zeroes(StructOuter),
+ };
+
+ const StructMiddle = extern struct {
+ outer: ?*StructInner,
+ inner: ?*StructOuter,
+ };
+
+ const StructOuter = extern struct {
+ middle: StructMiddle = std.mem.zeroes(StructMiddle),
+ };
+ };
+ var outer: S.StructOuter = .{};
+ try expect(outer.middle.outer == null);
+ try expect(outer.middle.inner == null);
+}