authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-08-28 14:00:26+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-08-28 15:41:21+03:00
loge2dc77ab62edf5446af830356eceef8eefb67cfa
treeca09907e11ad2b5a10d3e11acf69cae7be220f2d
parent776caaf99927181a2bb135afa9b502014782691c

Sema: correct one possible value for tuples

Closes #12376

3 files changed, 41 insertions(+), 13 deletions(-)

src/Sema.zig+6-6
......@@ -22248,8 +22248,7 @@ fn tupleField(
2224822248
2224922249 if (try sema.resolveMaybeUndefVal(block, tuple_src, tuple)) |tuple_val| {
2225022250 if (tuple_val.isUndef()) return sema.addConstUndef(field_ty);
22251 const field_values = tuple_val.castTag(.aggregate).?.data;
22252 return sema.addConstant(field_ty, field_values[field_index]);
22251 return sema.addConstant(field_ty, tuple_val.fieldValue(tuple_ty, field_index));
2225322252 }
2225422253
2225522254 try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src);
......@@ -28848,10 +28847,11 @@ pub fn typeHasOnePossibleValue(
2884828847
2884928848 .tuple, .anon_struct => {
2885028849 const tuple = ty.tupleFields();
28851 for (tuple.values) |val| {
28852 if (val.tag() == .unreachable_value) {
28853 return null; // non-comptime field
28854 }
28850 for (tuple.values) |val, i| {
28851 const is_comptime = val.tag() != .unreachable_value;
28852 if (is_comptime) continue;
28853 if ((try sema.typeHasOnePossibleValue(block, src, tuple.types[i])) != null) continue;
28854 return null;
2885528855 }
2885628856 return Value.initTag(.empty_struct_value);
2885728857 },
src/type.zig+8-7
......@@ -4979,19 +4979,20 @@ pub const Type = extern union {
49794979 const s = ty.castTag(.@"struct").?.data;
49804980 assert(s.haveFieldTypes());
49814981 for (s.fields.values()) |field| {
4982 if (field.ty.onePossibleValue() == null) {
4983 return null;
4984 }
4982 if (field.is_comptime) continue;
4983 if (field.ty.onePossibleValue() != null) continue;
4984 return null;
49854985 }
49864986 return Value.initTag(.empty_struct_value);
49874987 },
49884988
49894989 .tuple, .anon_struct => {
49904990 const tuple = ty.tupleFields();
4991 for (tuple.values) |val| {
4992 if (val.tag() == .unreachable_value) {
4993 return null; // non-comptime field
4994 }
4991 for (tuple.values) |val, i| {
4992 const is_comptime = val.tag() != .unreachable_value;
4993 if (is_comptime) continue;
4994 if (tuple.types[i].onePossibleValue() != null) continue;
4995 return null;
49954996 }
49964997 return Value.initTag(.empty_struct_value);
49974998 },
test/behavior/tuple.zig+27
......@@ -301,3 +301,30 @@ test "tuple type with void field" {
301301 const x = T{{}};
302302 try expect(@TypeOf(x[0]) == void);
303303}
304
305test "zero sized struct in tuple handled correctly" {
306 const State = struct {
307 const Self = @This();
308 data: @Type(.{
309 .Struct = .{
310 .is_tuple = true,
311 .layout = .Auto,
312 .decls = &.{},
313 .fields = &.{.{
314 .name = "0",
315 .field_type = struct {},
316 .default_value = null,
317 .is_comptime = false,
318 .alignment = 0,
319 }},
320 },
321 }),
322
323 pub fn do(this: Self) usize {
324 return @sizeOf(@TypeOf(this));
325 }
326 };
327
328 var s: State = undefined;
329 try expect(s.do() == 0);
330}