Skip to content

Commit 60be67d

Browse files
xdBronchmlugg
authored andcommitted
don't make OPV tuple fields comptime
1 parent 60a3324 commit 60be67d

File tree

4 files changed

+85
-46
lines changed

4 files changed

+85
-46
lines changed

src/Sema.zig

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2824,9 +2824,6 @@ fn zirTupleDecl(
28242824
}
28252825
break :init field_init_val.toIntern();
28262826
}
2827-
if (try sema.typeHasOnePossibleValue(field_type)) |opv| {
2828-
break :init opv.toIntern();
2829-
}
28302827
break :init .none;
28312828
};
28322829
}
@@ -21479,18 +21476,8 @@ fn reifyTuple(
2147921476
return sema.fail(block, src, "non-comptime tuple fields cannot specify default initialization value", .{});
2148021477
}
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-
2149221479
field_ty.* = field_type.toIntern();
21493-
field_init.* = default_or_opv;
21480+
field_init.* = field_default_value;
2149421481
}
2149521482

2149621483
return Air.internedToRef(try zcu.intern_pool.getTupleType(gpa, pt.tid, .{
@@ -36282,13 +36269,31 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3628236269
},
3628336270

3628436271
.tuple_type => |tuple| {
36285-
for (tuple.values.get(ip)) |val| {
36286-
if (val == .none) return null;
36272+
try ty.resolveLayout(pt);
36273+
36274+
if (tuple.types.len == 0) {
36275+
return try pt.aggregateValue(ty, &.{});
3628736276
}
36288-
// In this case the struct has all comptime-known fields and
36289-
// therefore has one possible value.
36290-
// TODO: write something like getCoercedInts to avoid needing to dupe
36291-
return try pt.aggregateValue(ty, try sema.arena.dupe(InternPool.Index, tuple.values.get(ip)));
36277+
36278+
const field_vals = try sema.arena.alloc(
36279+
InternPool.Index,
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);
3629236297
},
3629336298

3629436299
.union_type => {

src/Type.zig

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2581,15 +2581,30 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value {
25812581
},
25822582

25832583
.tuple_type => |tuple| {
2584-
for (tuple.values.get(ip)) |val| {
2585-
if (val == .none) return null;
2584+
if (tuple.types.len == 0) {
2585+
return try pt.aggregateValue(ty, &.{});
25862586
}
2587-
// In this case the struct has all comptime-known fields and
2588-
// therefore has one possible value.
2589-
// TODO: write something like getCoercedInts to avoid needing to dupe
2590-
const duped_values = try zcu.gpa.dupe(InternPool.Index, tuple.values.get(ip));
2591-
defer zcu.gpa.free(duped_values);
2592-
return try pt.aggregateValue(ty, duped_values);
2587+
2588+
const field_vals = try zcu.gpa.alloc(
2589+
InternPool.Index,
2590+
tuple.types.len,
2591+
);
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);
25932608
},
25942609

25952610
.union_type => {
@@ -2630,24 +2645,22 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value {
26302645
.auto, .explicit => {
26312646
if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(zcu)) return null;
26322647

2633-
switch (enum_type.names.len) {
2634-
0 => {
2635-
const only = try pt.intern(.{ .empty_enum_value = ty.toIntern() });
2636-
return Value.fromInterned(only);
2637-
},
2638-
1 => {
2639-
if (enum_type.values.len == 0) {
2640-
const only = try pt.intern(.{ .enum_tag = .{
2641-
.ty = ty.toIntern(),
2642-
.int = (try pt.intValue(.fromInterned(enum_type.tag_ty), 0)).toIntern(),
2643-
} });
2644-
return Value.fromInterned(only);
2645-
} else {
2646-
return Value.fromInterned(enum_type.values.get(ip)[0]);
2647-
}
2648-
},
2648+
return Value.fromInterned(switch (enum_type.names.len) {
2649+
0 => try pt.intern(.{ .empty_enum_value = ty.toIntern() }),
2650+
1 => try pt.intern(.{ .enum_tag = .{
2651+
.ty = ty.toIntern(),
2652+
.int = if (enum_type.values.len == 0)
2653+
(try pt.intValue(.fromInterned(enum_type.tag_ty), 0)).toIntern()
2654+
else
2655+
try ip.getCoercedInts(
2656+
zcu.gpa,
2657+
pt.tid,
2658+
ip.indexToKey(enum_type.values.get(ip)[0]).int,
2659+
enum_type.tag_ty,
2660+
),
2661+
} }),
26492662
else => return null,
2650-
}
2663+
});
26512664
},
26522665
}
26532666
},

test/behavior/tuple.zig

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,3 +611,24 @@ test "field pointer of underaligned tuple" {
611611
try S.doTheTest();
612612
try comptime S.doTheTest();
613613
}
614+
615+
test "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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ export fn entry() void {
88

99
// error
1010
//
11-
// :6:31: error: expected type 'tmp.S', found 'struct { comptime void = {} }'
11+
// :6:31: error: expected type 'tmp.S', found 'struct { void }'
1212
// :1:11: note: struct declared here

0 commit comments

Comments
 (0)