authorgravatar for 51252236+xdBronch@users.noreply.github.comxdBronch <51252236+xdBronch@users.noreply.github.com> 2025-10-04 00:12:26-04:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-10-08 18:04:25+01:00
log60be67d3c0ba6ae15fa7115596734ab1e74fbcd3
tree4679e250207c5215d5df51d79a307d41443fd4eb
parent60a332406c10be922568e11dcc5144bb0f2d7a85

don't make OPV tuple fields `comptime`


4 files changed, 85 insertions(+), 46 deletions(-)

src/Sema.zig+25-20
...@@ -2824,9 +2824,6 @@ fn zirTupleDecl(...@@ -2824,9 +2824,6 @@ fn zirTupleDecl(
2824 }2824 }
2825 break :init field_init_val.toIntern();2825 break :init field_init_val.toIntern();
2826 }2826 }
2827 if (try sema.typeHasOnePossibleValue(field_type)) |opv| {
2828 break :init opv.toIntern();
2829 }
2830 break :init .none;2827 break :init .none;
2831 };2828 };
2832 }2829 }
...@@ -21479,18 +21476,8 @@ fn reifyTuple(...@@ -21479,18 +21476,8 @@ fn reifyTuple(
21479 return sema.fail(block, src, "non-comptime tuple fields cannot specify default initialization value", .{});21476 return sema.fail(block, src, "non-comptime tuple fields cannot specify default initialization value", .{});
21480 }21477 }
2148121478
21482 const default_or_opv: InternPool.Index = default: {
21483 if (field_default_value != .none) {
21484 break :default field_default_value;
21485 }
21486 if (try sema.typeHasOnePossibleValue(field_type)) |opv| {
21487 break :default opv.toIntern();
21488 }
21489 break :default .none;
21490 };
21491
21492 field_ty.* = field_type.toIntern();21479 field_ty.* = field_type.toIntern();
21493 field_init.* = default_or_opv;21480 field_init.* = field_default_value;
21494 }21481 }
2149521482
21496 return Air.internedToRef(try zcu.intern_pool.getTupleType(gpa, pt.tid, .{21483 return Air.internedToRef(try zcu.intern_pool.getTupleType(gpa, pt.tid, .{
...@@ -36282,13 +36269,31 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -36282,13 +36269,31 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
36282 },36269 },
3628336270
36284 .tuple_type => |tuple| {36271 .tuple_type => |tuple| {
36285 for (tuple.values.get(ip)) |val| {36272 try ty.resolveLayout(pt);
36286 if (val == .none) return null;36273
36274 if (tuple.types.len == 0) {
36275 return try pt.aggregateValue(ty, &.{});
36287 }36276 }
36288 // In this case the struct has all comptime-known fields and36277
36289 // therefore has one possible value.36278 const field_vals = try sema.arena.alloc(
36290 // TODO: write something like getCoercedInts to avoid needing to dupe36279 InternPool.Index,
36291 return try pt.aggregateValue(ty, try sema.arena.dupe(InternPool.Index, tuple.values.get(ip)));36280 tuple.types.len,
36281 );
36282 for (
36283 field_vals,
36284 tuple.types.get(ip),
36285 tuple.values.get(ip),
36286 ) |*field_val, field_ty, field_comptime_val| {
36287 if (field_comptime_val != .none) {
36288 field_val.* = field_comptime_val;
36289 continue;
36290 }
36291 if (try sema.typeHasOnePossibleValue(.fromInterned(field_ty))) |opv| {
36292 field_val.* = opv.toIntern();
36293 } else return null;
36294 }
36295
36296 return try pt.aggregateValue(ty, field_vals);
36292 },36297 },
3629336298
36294 .union_type => {36299 .union_type => {
src/Type.zig+38-25
...@@ -2581,15 +2581,30 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value {...@@ -2581,15 +2581,30 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value {
2581 },2581 },
25822582
2583 .tuple_type => |tuple| {2583 .tuple_type => |tuple| {
2584 for (tuple.values.get(ip)) |val| {2584 if (tuple.types.len == 0) {
2585 if (val == .none) return null;2585 return try pt.aggregateValue(ty, &.{});
2586 }2586 }
2587 // In this case the struct has all comptime-known fields and2587
2588 // therefore has one possible value.2588 const field_vals = try zcu.gpa.alloc(
2589 // TODO: write something like getCoercedInts to avoid needing to dupe2589 InternPool.Index,
2590 const duped_values = try zcu.gpa.dupe(InternPool.Index, tuple.values.get(ip));2590 tuple.types.len,
2591 defer zcu.gpa.free(duped_values);2591 );
2592 return try pt.aggregateValue(ty, duped_values);2592 defer zcu.gpa.free(field_vals);
2593 for (
2594 field_vals,
2595 tuple.types.get(ip),
2596 tuple.values.get(ip),
2597 ) |*field_val, field_ty, field_comptime_val| {
2598 if (field_comptime_val != .none) {
2599 field_val.* = field_comptime_val;
2600 continue;
2601 }
2602 if (try Type.fromInterned(field_ty).onePossibleValue(pt)) |opv| {
2603 field_val.* = opv.toIntern();
2604 } else return null;
2605 }
2606
2607 return try pt.aggregateValue(ty, field_vals);
2593 },2608 },
25942609
2595 .union_type => {2610 .union_type => {
...@@ -2630,24 +2645,22 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value {...@@ -2630,24 +2645,22 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value {
2630 .auto, .explicit => {2645 .auto, .explicit => {
2631 if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(zcu)) return null;2646 if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(zcu)) return null;
26322647
2633 switch (enum_type.names.len) {2648 return Value.fromInterned(switch (enum_type.names.len) {
2634 0 => {2649 0 => try pt.intern(.{ .empty_enum_value = ty.toIntern() }),
2635 const only = try pt.intern(.{ .empty_enum_value = ty.toIntern() });2650 1 => try pt.intern(.{ .enum_tag = .{
2636 return Value.fromInterned(only);2651 .ty = ty.toIntern(),
2637 },2652 .int = if (enum_type.values.len == 0)
2638 1 => {2653 (try pt.intValue(.fromInterned(enum_type.tag_ty), 0)).toIntern()
2639 if (enum_type.values.len == 0) {2654 else
2640 const only = try pt.intern(.{ .enum_tag = .{2655 try ip.getCoercedInts(
2641 .ty = ty.toIntern(),2656 zcu.gpa,
2642 .int = (try pt.intValue(.fromInterned(enum_type.tag_ty), 0)).toIntern(),2657 pt.tid,
2643 } });2658 ip.indexToKey(enum_type.values.get(ip)[0]).int,
2644 return Value.fromInterned(only);2659 enum_type.tag_ty,
2645 } else {2660 ),
2646 return Value.fromInterned(enum_type.values.get(ip)[0]);2661 } }),
2647 }
2648 },
2649 else => return null,2662 else => return null,
2650 }2663 });
2651 },2664 },
2652 }2665 }
2653 },2666 },
test/behavior/tuple.zig+21
...@@ -611,3 +611,24 @@ test "field pointer of underaligned tuple" {...@@ -611,3 +611,24 @@ test "field pointer of underaligned tuple" {
611 try S.doTheTest();611 try S.doTheTest();
612 try comptime S.doTheTest();612 try comptime S.doTheTest();
613}613}
614
615test "OPV tuple fields aren't comptime" {
616 const T = struct { void };
617 const t_info = @typeInfo(T);
618 try expect(!t_info.@"struct".fields[0].is_comptime);
619
620 const T2 = @Type(.{ .@"struct" = .{
621 .layout = .auto,
622 .fields = &.{.{
623 .name = "0",
624 .type = void,
625 .default_value_ptr = null,
626 .is_comptime = false,
627 .alignment = @alignOf(void),
628 }},
629 .decls = &.{},
630 .is_tuple = true,
631 } });
632 const t2_info = @typeInfo(T2);
633 try expect(!t2_info.@"struct".fields[0].is_comptime);
634}
test/cases/compile_errors/invalid_tuple_to_struct_coercion.zig+1-1
...@@ -8,5 +8,5 @@ export fn entry() void {...@@ -8,5 +8,5 @@ export fn entry() void {
88
9// error9// error
10//10//
11// :6:31: error: expected type 'tmp.S', found 'struct { comptime void = {} }'11// :6:31: error: expected type 'tmp.S', found 'struct { void }'
12// :1:11: note: struct declared here12// :1:11: note: struct declared here