authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-11-16 01:11:12+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-11-16 01:13:35+02:00
log28cbe5e92a36c81177dbcd2f33fc792468c08304
tree4c75818b2b300ece49cc43947f7b850dfb483007
parentfe6249348f615c975a2db53bb0c93f83bd2a281b

Sema+llvm: improve handling of namespace-like unions

Closes #13557

3 files changed, 26 insertions(+), 5 deletions(-)

src/Sema.zig+2-3
...@@ -22476,13 +22476,12 @@ fn fieldVal(...@@ -22476,13 +22476,12 @@ fn fieldVal(
22476 );22476 );
22477 },22477 },
22478 .Union => {22478 .Union => {
22479 const union_ty = try sema.resolveTypeFields(child_type);22479 if (child_type.getNamespace()) |namespace| {
22480
22481 if (union_ty.getNamespace()) |namespace| {
22482 if (try sema.namespaceLookupVal(block, src, namespace, field_name)) |inst| {22480 if (try sema.namespaceLookupVal(block, src, namespace, field_name)) |inst| {
22483 return inst;22481 return inst;
22484 }22482 }
22485 }22483 }
22484 const union_ty = try sema.resolveTypeFields(child_type);
22486 if (union_ty.unionTagType()) |enum_ty| {22485 if (union_ty.unionTagType()) |enum_ty| {
22487 if (enum_ty.enumFieldIndex(field_name)) |field_index_usize| {22486 if (enum_ty.enumFieldIndex(field_name)) |field_index_usize| {
22488 const field_index = @intCast(u32, field_index_usize);22487 const field_index = @intCast(u32, field_index_usize);
src/codegen/llvm.zig+2-2
...@@ -2137,7 +2137,8 @@ pub const Object = struct {...@@ -2137,7 +2137,8 @@ pub const Object = struct {
2137 break :blk fwd_decl;2137 break :blk fwd_decl;
2138 };2138 };
21392139
2140 if (!ty.hasRuntimeBitsIgnoreComptime()) {2140 const union_obj = ty.cast(Type.Payload.Union).?.data;
2141 if (!union_obj.haveFieldTypes() or !ty.hasRuntimeBitsIgnoreComptime()) {
2141 const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);2142 const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
2142 dib.replaceTemporary(fwd_decl, union_di_ty);2143 dib.replaceTemporary(fwd_decl, union_di_ty);
2143 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`2144 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
...@@ -2147,7 +2148,6 @@ pub const Object = struct {...@@ -2147,7 +2148,6 @@ pub const Object = struct {
2147 }2148 }
21482149
2149 const layout = ty.unionGetLayout(target);2150 const layout = ty.unionGetLayout(target);
2150 const union_obj = ty.cast(Type.Payload.Union).?.data;
21512151
2152 if (layout.payload_size == 0) {2152 if (layout.payload_size == 0) {
2153 const tag_di_ty = try o.lowerDebugType(union_obj.tag_ty, .full);2153 const tag_di_ty = try o.lowerDebugType(union_obj.tag_ty, .full);
test/behavior/union.zig+22
...@@ -1388,3 +1388,25 @@ test "packed union in packed struct" {...@@ -1388,3 +1388,25 @@ test "packed union in packed struct" {
1388 const a: S = .{ .nested = .{ .foo = 123 }, .bar = 5 };1388 const a: S = .{ .nested = .{ .foo = 123 }, .bar = 5 };
1389 try expect(a.unpack() == 123);1389 try expect(a.unpack() == 123);
1390}1390}
1391
1392test "Namespace-like union" {
1393 const DepType = enum {
1394 git,
1395 http,
1396 const DepType = @This();
1397 const Version = union(DepType) {
1398 git: Git,
1399 http: void,
1400 const Git = enum {
1401 branch,
1402 tag,
1403 commit,
1404 fn frozen(self: Git) bool {
1405 return self == .tag;
1406 }
1407 };
1408 };
1409 };
1410 var a: DepType.Version.Git = .tag;
1411 try expect(a.frozen());
1412}