Commit 32c90cb553

Andrew Kelley <andrew@ziglang.org>
2022-06-10 04:23:36
stage2: fix handling of aggregates with mixed comptime-only fields
1 parent f1cff4f
Changed files (4)
src
test
behavior
src/codegen/llvm.zig
@@ -9185,7 +9185,7 @@ fn isByRef(ty: Type) bool {
         .AnyFrame,
         => return false,
 
-        .Array, .Frame => return ty.hasRuntimeBitsIgnoreComptime(),
+        .Array, .Frame => return ty.hasRuntimeBits(),
         .Struct => {
             // Packed structs are represented to LLVM as integers.
             if (ty.containerLayout() == .Packed) return false;
@@ -9204,7 +9204,7 @@ fn isByRef(ty: Type) bool {
             var count: usize = 0;
             const fields = ty.structFields();
             for (fields.values()) |field| {
-                if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;
+                if (field.is_comptime or !field.ty.hasRuntimeBits()) continue;
 
                 count += 1;
                 if (count > max_fields_byval) return true;
@@ -9212,7 +9212,7 @@ fn isByRef(ty: Type) bool {
             }
             return false;
         },
-        .Union => return ty.hasRuntimeBitsIgnoreComptime(),
+        .Union => return ty.hasRuntimeBits(),
         .ErrorUnion => return isByRef(ty.errorUnionPayload()),
         .Optional => {
             var buf: Type.Payload.ElemType = undefined;
src/Sema.zig
@@ -25048,9 +25048,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ
 }
 
 pub fn typeHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool {
-    if ((try sema.typeHasOnePossibleValue(block, src, ty)) != null) return false;
-    if (try sema.typeRequiresComptime(block, src, ty)) return false;
-    return true;
+    return ty.hasRuntimeBitsAdvanced(false, sema.kit(block, src));
 }
 
 fn typeAbiSize(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !u64 {
src/type.zig
@@ -2365,6 +2365,7 @@ pub const Type = extern union {
             .@"anyframe",
             .anyopaque,
             .@"opaque",
+            .type_info,
             => return true,
 
             // These are false because they are comptime-only types.
@@ -2379,7 +2380,6 @@ pub const Type = extern union {
             .enum_literal,
             .empty_struct,
             .empty_struct_literal,
-            .type_info,
             .bound_fn,
             // These are function *bodies*, not pointers.
             // Special exceptions have to be made when emitting functions due to
@@ -2464,14 +2464,6 @@ pub const Type = extern union {
 
             .@"struct" => {
                 const struct_obj = ty.castTag(.@"struct").?.data;
-                if (sema_kit) |sk| {
-                    _ = try sk.sema.typeRequiresComptime(sk.block, sk.src, ty);
-                }
-                switch (struct_obj.requires_comptime) {
-                    .yes => return false,
-                    .wip, .no => if (struct_obj.known_non_opv) return true,
-                    .unknown => {},
-                }
                 if (struct_obj.status == .field_types_wip) {
                     // In this case, we guess that hasRuntimeBits() for this type is true,
                     // and then later if our guess was incorrect, we emit a compile error.
test/behavior/eval.zig
@@ -1196,7 +1196,9 @@ test "equality of pointers to comptime const" {
 }
 
 test "storing an array of type in a field" {
-    if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 
     const S = struct {
         fn doTheTest() void {
@@ -1221,3 +1223,32 @@ test "storing an array of type in a field" {
 
     S.doTheTest();
 }
+
+test "pass pointer to field of comptime-only type as a runtime parameter" {
+    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+
+    const S = struct {
+        const Mixed = struct {
+            T: type,
+            x: i32,
+        };
+        const bag: Mixed = .{
+            .T = bool,
+            .x = 1234,
+        };
+
+        var ok = false;
+
+        fn doTheTest() !void {
+            foo(&bag.x);
+            try expect(ok);
+        }
+
+        fn foo(ptr: *const i32) void {
+            ok = ptr.* == 1234;
+        }
+    };
+    try S.doTheTest();
+}