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(...@@ -22248,8 +22248,7 @@ fn tupleField(
2224822248
22249 if (try sema.resolveMaybeUndefVal(block, tuple_src, tuple)) |tuple_val| {22249 if (try sema.resolveMaybeUndefVal(block, tuple_src, tuple)) |tuple_val| {
22250 if (tuple_val.isUndef()) return sema.addConstUndef(field_ty);22250 if (tuple_val.isUndef()) return sema.addConstUndef(field_ty);
22251 const field_values = tuple_val.castTag(.aggregate).?.data;22251 return sema.addConstant(field_ty, tuple_val.fieldValue(tuple_ty, field_index));
22252 return sema.addConstant(field_ty, field_values[field_index]);
22253 }22252 }
2225422253
22255 try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src);22254 try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src);
...@@ -28848,10 +28847,11 @@ pub fn typeHasOnePossibleValue(...@@ -28848,10 +28847,11 @@ pub fn typeHasOnePossibleValue(
2884828847
28849 .tuple, .anon_struct => {28848 .tuple, .anon_struct => {
28850 const tuple = ty.tupleFields();28849 const tuple = ty.tupleFields();
28851 for (tuple.values) |val| {28850 for (tuple.values) |val, i| {
28852 if (val.tag() == .unreachable_value) {28851 const is_comptime = val.tag() != .unreachable_value;
28853 return null; // non-comptime field28852 if (is_comptime) continue;
28854 }28853 if ((try sema.typeHasOnePossibleValue(block, src, tuple.types[i])) != null) continue;
28854 return null;
28855 }28855 }
28856 return Value.initTag(.empty_struct_value);28856 return Value.initTag(.empty_struct_value);
28857 },28857 },
src/type.zig+8-7
...@@ -4979,19 +4979,20 @@ pub const Type = extern union {...@@ -4979,19 +4979,20 @@ pub const Type = extern union {
4979 const s = ty.castTag(.@"struct").?.data;4979 const s = ty.castTag(.@"struct").?.data;
4980 assert(s.haveFieldTypes());4980 assert(s.haveFieldTypes());
4981 for (s.fields.values()) |field| {4981 for (s.fields.values()) |field| {
4982 if (field.ty.onePossibleValue() == null) {4982 if (field.is_comptime) continue;
4983 return null;4983 if (field.ty.onePossibleValue() != null) continue;
4984 }4984 return null;
4985 }4985 }
4986 return Value.initTag(.empty_struct_value);4986 return Value.initTag(.empty_struct_value);
4987 },4987 },
49884988
4989 .tuple, .anon_struct => {4989 .tuple, .anon_struct => {
4990 const tuple = ty.tupleFields();4990 const tuple = ty.tupleFields();
4991 for (tuple.values) |val| {4991 for (tuple.values) |val, i| {
4992 if (val.tag() == .unreachable_value) {4992 const is_comptime = val.tag() != .unreachable_value;
4993 return null; // non-comptime field4993 if (is_comptime) continue;
4994 }4994 if (tuple.types[i].onePossibleValue() != null) continue;
4995 return null;
4995 }4996 }
4996 return Value.initTag(.empty_struct_value);4997 return Value.initTag(.empty_struct_value);
4997 },4998 },
test/behavior/tuple.zig+27
...@@ -301,3 +301,30 @@ test "tuple type with void field" {...@@ -301,3 +301,30 @@ test "tuple type with void field" {
301 const x = T{{}};301 const x = T{{}};
302 try expect(@TypeOf(x[0]) == void);302 try expect(@TypeOf(x[0]) == void);
303}303}
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}