Commit 7d3c5f207a

LemonBoy <thatlemon@gmail.com>
2020-11-11 10:11:25
stage1: Avoid resolving type entry in [0]T
The logic was already there but this rule was only applied in some places, apply it in the remaining code paths. Closes #7058
1 parent 0405698
Changed files (3)
src
test
stage1
behavior
src/stage1/analyze.cpp
@@ -1453,7 +1453,12 @@ Error type_val_resolve_abi_align(CodeGen *g, AstNode *source_node, ZigValue *typ
         case LazyValueIdArrayType: {
             LazyValueArrayType *lazy_array_type =
                 reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
-            return type_val_resolve_abi_align(g, source_node, lazy_array_type->elem_type->value, abi_align);
+
+            if (lazy_array_type->length + (lazy_array_type->sentinel != nullptr) != 0)
+                return type_val_resolve_abi_align(g, source_node, lazy_array_type->elem_type->value, abi_align);
+
+            *abi_align = 0;
+            return ErrorNone;
         }
         case LazyValueIdErrUnionType: {
             LazyValueErrUnionType *lazy_err_union_type =
src/stage1/ir.cpp
@@ -32970,8 +32970,13 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) {
                     break;
             }
 
-            if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
-                return err;
+            // Avoid resolving the type if the total length is zero.
+            // Matches the logic in get_array_type and in the lazy alignment
+            // resolution routine.
+            if (lazy_array_type->length + (lazy_array_type->sentinel != nullptr) != 0) {
+                if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
+                    return err;
+            }
 
             ZigValue *sentinel_val = nullptr;
             if (lazy_array_type->sentinel != nullptr) {
test/stage1/behavior/array.zig
@@ -413,3 +413,21 @@ test "sentinel element count towards the ABI size calculation" {
     S.doTheTest();
     comptime S.doTheTest();
 }
+
+test "zero-sized array with recursive type definition" {
+    const U = struct {
+        fn foo(comptime T: type, comptime n: usize) type {
+            return struct {
+                s: [n]T,
+                x: usize = n,
+            };
+        }
+    };
+
+    const S = struct {
+        list: U.foo(@This(), 0),
+    };
+
+    var t: S = .{ .list = .{ .s = undefined } };
+    expectEqual(@as(usize, 0), t.list.x);
+}