Sema: correct one possible value for tuples

Closes #12376
This commit is contained in:
Veikka Tuominen 2022-08-28 14:00:26 +03:00
parent 776caaf999
commit e2dc77ab62
3 changed files with 41 additions and 13 deletions

View File

@ -22248,8 +22248,7 @@ fn tupleField(
if (try sema.resolveMaybeUndefVal(block, tuple_src, tuple)) |tuple_val| {
if (tuple_val.isUndef()) return sema.addConstUndef(field_ty);
const field_values = tuple_val.castTag(.aggregate).?.data;
return sema.addConstant(field_ty, field_values[field_index]);
return sema.addConstant(field_ty, tuple_val.fieldValue(tuple_ty, field_index));
}
try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src);
@ -28848,10 +28847,11 @@ pub fn typeHasOnePossibleValue(
.tuple, .anon_struct => {
const tuple = ty.tupleFields();
for (tuple.values) |val| {
if (val.tag() == .unreachable_value) {
return null; // non-comptime field
}
for (tuple.values) |val, i| {
const is_comptime = val.tag() != .unreachable_value;
if (is_comptime) continue;
if ((try sema.typeHasOnePossibleValue(block, src, tuple.types[i])) != null) continue;
return null;
}
return Value.initTag(.empty_struct_value);
},

View File

@ -4979,19 +4979,20 @@ pub const Type = extern union {
const s = ty.castTag(.@"struct").?.data;
assert(s.haveFieldTypes());
for (s.fields.values()) |field| {
if (field.ty.onePossibleValue() == null) {
return null;
}
if (field.is_comptime) continue;
if (field.ty.onePossibleValue() != null) continue;
return null;
}
return Value.initTag(.empty_struct_value);
},
.tuple, .anon_struct => {
const tuple = ty.tupleFields();
for (tuple.values) |val| {
if (val.tag() == .unreachable_value) {
return null; // non-comptime field
}
for (tuple.values) |val, i| {
const is_comptime = val.tag() != .unreachable_value;
if (is_comptime) continue;
if (tuple.types[i].onePossibleValue() != null) continue;
return null;
}
return Value.initTag(.empty_struct_value);
},

View File

@ -301,3 +301,30 @@ test "tuple type with void field" {
const x = T{{}};
try expect(@TypeOf(x[0]) == void);
}
test "zero sized struct in tuple handled correctly" {
const State = struct {
const Self = @This();
data: @Type(.{
.Struct = .{
.is_tuple = true,
.layout = .Auto,
.decls = &.{},
.fields = &.{.{
.name = "0",
.field_type = struct {},
.default_value = null,
.is_comptime = false,
.alignment = 0,
}},
},
}),
pub fn do(this: Self) usize {
return @sizeOf(@TypeOf(this));
}
};
var s: State = undefined;
try expect(s.do() == 0);
}