Commit 28cbe5e92a

Veikka Tuominen <git@vexu.eu>
2022-11-16 00:11:12
Sema+llvm: improve handling of namespace-like unions
Closes #13557
1 parent fe62493
Changed files (3)
src
test
behavior
src/codegen/llvm.zig
@@ -2137,7 +2137,8 @@ pub const Object = struct {
                     break :blk fwd_decl;
                 };
 
-                if (!ty.hasRuntimeBitsIgnoreComptime()) {
+                const union_obj = ty.cast(Type.Payload.Union).?.data;
+                if (!union_obj.haveFieldTypes() or !ty.hasRuntimeBitsIgnoreComptime()) {
                     const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
                     dib.replaceTemporary(fwd_decl, union_di_ty);
                     // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
@@ -2147,7 +2148,6 @@ pub const Object = struct {
                 }
 
                 const layout = ty.unionGetLayout(target);
-                const union_obj = ty.cast(Type.Payload.Union).?.data;
 
                 if (layout.payload_size == 0) {
                     const tag_di_ty = try o.lowerDebugType(union_obj.tag_ty, .full);
src/Sema.zig
@@ -22476,13 +22476,12 @@ fn fieldVal(
                     );
                 },
                 .Union => {
-                    const union_ty = try sema.resolveTypeFields(child_type);
-
-                    if (union_ty.getNamespace()) |namespace| {
+                    if (child_type.getNamespace()) |namespace| {
                         if (try sema.namespaceLookupVal(block, src, namespace, field_name)) |inst| {
                             return inst;
                         }
                     }
+                    const union_ty = try sema.resolveTypeFields(child_type);
                     if (union_ty.unionTagType()) |enum_ty| {
                         if (enum_ty.enumFieldIndex(field_name)) |field_index_usize| {
                             const field_index = @intCast(u32, field_index_usize);
test/behavior/union.zig
@@ -1388,3 +1388,25 @@ test "packed union in packed struct" {
     const a: S = .{ .nested = .{ .foo = 123 }, .bar = 5 };
     try expect(a.unpack() == 123);
 }
+
+test "Namespace-like union" {
+    const DepType = enum {
+        git,
+        http,
+        const DepType = @This();
+        const Version = union(DepType) {
+            git: Git,
+            http: void,
+            const Git = enum {
+                branch,
+                tag,
+                commit,
+                fn frozen(self: Git) bool {
+                    return self == .tag;
+                }
+            };
+        };
+    };
+    var a: DepType.Version.Git = .tag;
+    try expect(a.frozen());
+}