authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-09 19:23:36-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-09 19:23:36-07:00
log32c90cb5539c3b340ae1b0b13d2b1521ebb6b1b0
tree149e21f6afdce496a95d29d97a1d6e3ccd6d0f4d
parentf1cff4fa4a28d42ac9055f94ee9a8f7fd2831cd7

stage2: fix handling of aggregates with mixed comptime-only fields


4 files changed, 37 insertions(+), 16 deletions(-)

src/Sema.zig+1-3
...@@ -25048,9 +25048,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ...@@ -25048,9 +25048,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ
25048}25048}
2504925049
25050pub fn typeHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool {25050pub fn typeHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool {
25051 if ((try sema.typeHasOnePossibleValue(block, src, ty)) != null) return false;25051 return ty.hasRuntimeBitsAdvanced(false, sema.kit(block, src));
25052 if (try sema.typeRequiresComptime(block, src, ty)) return false;
25053 return true;
25054}25052}
2505525053
25056fn typeAbiSize(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !u64 {25054fn typeAbiSize(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !u64 {
src/codegen/llvm.zig+3-3
...@@ -9185,7 +9185,7 @@ fn isByRef(ty: Type) bool {...@@ -9185,7 +9185,7 @@ fn isByRef(ty: Type) bool {
9185 .AnyFrame,9185 .AnyFrame,
9186 => return false,9186 => return false,
91879187
9188 .Array, .Frame => return ty.hasRuntimeBitsIgnoreComptime(),9188 .Array, .Frame => return ty.hasRuntimeBits(),
9189 .Struct => {9189 .Struct => {
9190 // Packed structs are represented to LLVM as integers.9190 // Packed structs are represented to LLVM as integers.
9191 if (ty.containerLayout() == .Packed) return false;9191 if (ty.containerLayout() == .Packed) return false;
...@@ -9204,7 +9204,7 @@ fn isByRef(ty: Type) bool {...@@ -9204,7 +9204,7 @@ fn isByRef(ty: Type) bool {
9204 var count: usize = 0;9204 var count: usize = 0;
9205 const fields = ty.structFields();9205 const fields = ty.structFields();
9206 for (fields.values()) |field| {9206 for (fields.values()) |field| {
9207 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;9207 if (field.is_comptime or !field.ty.hasRuntimeBits()) continue;
92089208
9209 count += 1;9209 count += 1;
9210 if (count > max_fields_byval) return true;9210 if (count > max_fields_byval) return true;
...@@ -9212,7 +9212,7 @@ fn isByRef(ty: Type) bool {...@@ -9212,7 +9212,7 @@ fn isByRef(ty: Type) bool {
9212 }9212 }
9213 return false;9213 return false;
9214 },9214 },
9215 .Union => return ty.hasRuntimeBitsIgnoreComptime(),9215 .Union => return ty.hasRuntimeBits(),
9216 .ErrorUnion => return isByRef(ty.errorUnionPayload()),9216 .ErrorUnion => return isByRef(ty.errorUnionPayload()),
9217 .Optional => {9217 .Optional => {
9218 var buf: Type.Payload.ElemType = undefined;9218 var buf: Type.Payload.ElemType = undefined;
src/type.zig+1-9
...@@ -2365,6 +2365,7 @@ pub const Type = extern union {...@@ -2365,6 +2365,7 @@ pub const Type = extern union {
2365 .@"anyframe",2365 .@"anyframe",
2366 .anyopaque,2366 .anyopaque,
2367 .@"opaque",2367 .@"opaque",
2368 .type_info,
2368 => return true,2369 => return true,
23692370
2370 // These are false because they are comptime-only types.2371 // These are false because they are comptime-only types.
...@@ -2379,7 +2380,6 @@ pub const Type = extern union {...@@ -2379,7 +2380,6 @@ pub const Type = extern union {
2379 .enum_literal,2380 .enum_literal,
2380 .empty_struct,2381 .empty_struct,
2381 .empty_struct_literal,2382 .empty_struct_literal,
2382 .type_info,
2383 .bound_fn,2383 .bound_fn,
2384 // These are function *bodies*, not pointers.2384 // These are function *bodies*, not pointers.
2385 // Special exceptions have to be made when emitting functions due to2385 // Special exceptions have to be made when emitting functions due to
...@@ -2464,14 +2464,6 @@ pub const Type = extern union {...@@ -2464,14 +2464,6 @@ pub const Type = extern union {
24642464
2465 .@"struct" => {2465 .@"struct" => {
2466 const struct_obj = ty.castTag(.@"struct").?.data;2466 const struct_obj = ty.castTag(.@"struct").?.data;
2467 if (sema_kit) |sk| {
2468 _ = try sk.sema.typeRequiresComptime(sk.block, sk.src, ty);
2469 }
2470 switch (struct_obj.requires_comptime) {
2471 .yes => return false,
2472 .wip, .no => if (struct_obj.known_non_opv) return true,
2473 .unknown => {},
2474 }
2475 if (struct_obj.status == .field_types_wip) {2467 if (struct_obj.status == .field_types_wip) {
2476 // In this case, we guess that hasRuntimeBits() for this type is true,2468 // In this case, we guess that hasRuntimeBits() for this type is true,
2477 // and then later if our guess was incorrect, we emit a compile error.2469 // and then later if our guess was incorrect, we emit a compile error.
test/behavior/eval.zig+32-1
...@@ -1196,7 +1196,9 @@ test "equality of pointers to comptime const" {...@@ -1196,7 +1196,9 @@ test "equality of pointers to comptime const" {
1196}1196}
11971197
1198test "storing an array of type in a field" {1198test "storing an array of type in a field" {
1199 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO1199 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1200 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1201 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12001202
1201 const S = struct {1203 const S = struct {
1202 fn doTheTest() void {1204 fn doTheTest() void {
...@@ -1221,3 +1223,32 @@ test "storing an array of type in a field" {...@@ -1221,3 +1223,32 @@ test "storing an array of type in a field" {
12211223
1222 S.doTheTest();1224 S.doTheTest();
1223}1225}
1226
1227test "pass pointer to field of comptime-only type as a runtime parameter" {
1228 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1229 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1230 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1231
1232 const S = struct {
1233 const Mixed = struct {
1234 T: type,
1235 x: i32,
1236 };
1237 const bag: Mixed = .{
1238 .T = bool,
1239 .x = 1234,
1240 };
1241
1242 var ok = false;
1243
1244 fn doTheTest() !void {
1245 foo(&bag.x);
1246 try expect(ok);
1247 }
1248
1249 fn foo(ptr: *const i32) void {
1250 ok = ptr.* == 1234;
1251 }
1252 };
1253 try S.doTheTest();
1254}