Fix tuple default values

- Add default values to the list of comptime-known elements in
  `zirValidatePtrArrayInit`
- In `structFieldValueComptime`, only assert `haveFieldInits` if we
  enter the`fieldIsComptime` branch (otherwise they are not needed).
This commit is contained in:
John Schmidt 2024-02-11 22:55:13 +01:00 committed by Andrew Kelley
parent 7a045ede7c
commit f803761e13
3 changed files with 28 additions and 9 deletions

View File

@ -5043,22 +5043,33 @@ fn zirValidatePtrArrayInit(
const array_ty = sema.typeOf(array_ptr).childType(mod).optEuBaseType(mod); const array_ty = sema.typeOf(array_ptr).childType(mod).optEuBaseType(mod);
const array_len = array_ty.arrayLen(mod); const array_len = array_ty.arrayLen(mod);
// Collect the comptime element values in case the array literal ends up
// being comptime-known.
const element_vals = try sema.arena.alloc(
InternPool.Index,
try sema.usizeCast(block, init_src, array_len),
);
if (instrs.len != array_len) switch (array_ty.zigTypeTag(mod)) { if (instrs.len != array_len) switch (array_ty.zigTypeTag(mod)) {
.Struct => { .Struct => {
var root_msg: ?*Module.ErrorMsg = null; var root_msg: ?*Module.ErrorMsg = null;
errdefer if (root_msg) |msg| msg.destroy(sema.gpa); errdefer if (root_msg) |msg| msg.destroy(sema.gpa);
try sema.resolveStructFieldInits(array_ty);
var i = instrs.len; var i = instrs.len;
while (i < array_len) : (i += 1) { while (i < array_len) : (i += 1) {
const default_val = array_ty.structFieldDefaultValue(i, mod); const default_val = array_ty.structFieldDefaultValue(i, mod).toIntern();
if (default_val.toIntern() == .unreachable_value) { if (default_val == .unreachable_value) {
const template = "missing tuple field with index {d}"; const template = "missing tuple field with index {d}";
if (root_msg) |msg| { if (root_msg) |msg| {
try sema.errNote(block, init_src, msg, template, .{i}); try sema.errNote(block, init_src, msg, template, .{i});
} else { } else {
root_msg = try sema.errMsg(block, init_src, template, .{i}); root_msg = try sema.errMsg(block, init_src, template, .{i});
} }
continue;
} }
element_vals[i] = default_val;
} }
if (root_msg) |msg| { if (root_msg) |msg| {
@ -5105,12 +5116,6 @@ fn zirValidatePtrArrayInit(
var array_is_comptime = true; var array_is_comptime = true;
var first_block_index = block.instructions.items.len; var first_block_index = block.instructions.items.len;
// Collect the comptime element values in case the array literal ends up
// being comptime-known.
const element_vals = try sema.arena.alloc(
InternPool.Index,
try sema.usizeCast(block, init_src, array_len),
);
const air_tags = sema.air_instructions.items(.tag); const air_tags = sema.air_instructions.items(.tag);
const air_datas = sema.air_instructions.items(.data); const air_datas = sema.air_instructions.items(.data);

View File

@ -3073,8 +3073,8 @@ pub const Type = struct {
const ip = &mod.intern_pool; const ip = &mod.intern_pool;
switch (ip.indexToKey(ty.toIntern())) { switch (ip.indexToKey(ty.toIntern())) {
.struct_type => |struct_type| { .struct_type => |struct_type| {
assert(struct_type.haveFieldInits(ip));
if (struct_type.fieldIsComptime(ip, index)) { if (struct_type.fieldIsComptime(ip, index)) {
assert(struct_type.haveFieldInits(ip));
return Value.fromInterned(struct_type.field_inits.get(ip)[index]); return Value.fromInterned(struct_type.field_inits.get(ip)[index]);
} else { } else {
return Type.fromInterned(struct_type.field_types.get(ip)[index]).onePossibleValue(mod); return Type.fromInterned(struct_type.field_types.get(ip)[index]).onePossibleValue(mod);

View File

@ -560,3 +560,17 @@ test "comptime fields in tuple can be initialized" {
var a: T = .{ 0, 0 }; var a: T = .{ 0, 0 };
_ = &a; _ = &a;
} }
test "tuple default values" {
const T = struct {
usize,
usize = 123,
usize = 456,
};
const t: T = .{1};
try expectEqual(1, t[0]);
try expectEqual(123, t[1]);
try expectEqual(456, t[2]);
}