diff options
| author | kcbanner <kcbanner@gmail.com> | 2023-10-21 16:49:30 -0400 |
|---|---|---|
| committer | mlugg <mlugg@mlugg.co.uk> | 2023-11-07 00:49:35 +0000 |
| commit | f10499be0a16ec58d98387b49189401f2af2094f (patch) | |
| tree | 1dee8acd698e9bb489a9926004d4cdf16f7ce72d /test/behavior/struct.zig | |
| parent | 234693bcbba6f55ff6e975ddbedf0fad4dfaa8f1 (diff) | |
| download | zig-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.zig | 57 |
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); +} |
