| author | |
| committer | |
| log | e2dc77ab62edf5446af830356eceef8eefb67cfa |
| tree | ca09907e11ad2b5a10d3e11acf69cae7be220f2d |
| parent | 776caaf99927181a2bb135afa9b502014782691c |
Closes #123763 files changed, 41 insertions(+), 13 deletions(-)
src/Sema.zig+6-6| ... | ... | @@ -22248,8 +22248,7 @@ fn tupleField( |
| 22248 | 22248 | |
| 22249 | 22249 | if (try sema.resolveMaybeUndefVal(block, tuple_src, tuple)) |tuple_val| { |
| 22250 | 22250 | 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)); | |
| 22253 | 22252 | } |
| 22254 | 22253 | |
| 22255 | 22254 | try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src); |
| ... | ... | @@ -28848,10 +28847,11 @@ pub fn typeHasOnePossibleValue( |
| 28848 | 28847 | |
| 28849 | 28848 | .tuple, .anon_struct => { |
| 28850 | 28849 | 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; | |
| 28855 | 28855 | } |
| 28856 | 28856 | return Value.initTag(.empty_struct_value); |
| 28857 | 28857 | }, |
src/type.zig+8-7| ... | ... | @@ -4979,19 +4979,20 @@ pub const Type = extern union { |
| 4979 | 4979 | const s = ty.castTag(.@"struct").?.data; |
| 4980 | 4980 | assert(s.haveFieldTypes()); |
| 4981 | 4981 | 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; | |
| 4985 | 4985 | } |
| 4986 | 4986 | return Value.initTag(.empty_struct_value); |
| 4987 | 4987 | }, |
| 4988 | 4988 | |
| 4989 | 4989 | .tuple, .anon_struct => { |
| 4990 | 4990 | 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; | |
| 4995 | 4996 | } |
| 4996 | 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 | 301 | const x = T{{}}; |
| 302 | 302 | try expect(@TypeOf(x[0]) == void); |
| 303 | 303 | } |
| 304 | ||
| 305 | test "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 | } |