| author | |
| committer | |
| log | 81b5df347a2b92566dc679fdd4e110812dfe27d0 |
| tree | 2e2580b944374f490797ef3211eb752c7b1bc051 |
| parent | edfada4317760a152ad9c36b39f5a2e68eeaebf8 |
When struct types have no field names, the names are implicitly
understood to be strings corresponding to the field indexes in
declaration order. It used to be the case that a NullTerminatedString
would be stored for each field in this case, however, now, callers must
handle the possibility that there are no names stored at all. This
commit introduces `legacyStructFieldName`, a function to fake the
previous behavior. Probably something better could be done by reworking
all the callsites of this function.6 files changed, 66 insertions(+), 36 deletions(-)
src/InternPool.zig+11| ... | @@ -656,6 +656,17 @@ pub const Key = union(enum) { | ... | @@ -656,6 +656,17 @@ pub const Key = union(enum) { |
| 656 | pub fn isTuple(self: AnonStructType) bool { | 656 | pub fn isTuple(self: AnonStructType) bool { |
| 657 | return self.names.len == 0; | 657 | return self.names.len == 0; |
| 658 | } | 658 | } |
| 659 | |||
| 660 | pub fn fieldName( | ||
| 661 | self: AnonStructType, | ||
| 662 | ip: *const InternPool, | ||
| 663 | index: u32, | ||
| 664 | ) OptionalNullTerminatedString { | ||
| 665 | if (self.names.len == 0) | ||
| 666 | return .none; | ||
| 667 | |||
| 668 | return self.names.get(ip)[index].toOptional(); | ||
| 669 | } | ||
| 659 | }; | 670 | }; |
| 660 | 671 | ||
| 661 | /// Serves two purposes: | 672 | /// Serves two purposes: |
src/Sema.zig+19-17| ... | @@ -4699,12 +4699,13 @@ fn validateStructInit( | ... | @@ -4699,12 +4699,13 @@ fn validateStructInit( |
| 4699 | // In this case the only thing we need to do is evaluate the implicit | 4699 | // In this case the only thing we need to do is evaluate the implicit |
| 4700 | // store instructions for default field values, and report any missing fields. | 4700 | // store instructions for default field values, and report any missing fields. |
| 4701 | // Avoid the cost of the extra machinery for detecting a comptime struct init value. | 4701 | // Avoid the cost of the extra machinery for detecting a comptime struct init value. |
| 4702 | for (found_fields, 0..) |field_ptr, i| { | 4702 | for (found_fields, 0..) |field_ptr, i_usize| { |
| 4703 | const i: u32 = @intCast(i_usize); | ||
| 4703 | if (field_ptr != 0) continue; | 4704 | if (field_ptr != 0) continue; |
| 4704 | 4705 | ||
| 4705 | const default_val = struct_ty.structFieldDefaultValue(i, mod); | 4706 | const default_val = struct_ty.structFieldDefaultValue(i, mod); |
| 4706 | if (default_val.toIntern() == .unreachable_value) { | 4707 | if (default_val.toIntern() == .unreachable_value) { |
| 4707 | if (struct_ty.isTuple(mod)) { | 4708 | const field_name = struct_ty.structFieldName(i, mod).unwrap() orelse { |
| 4708 | const template = "missing tuple field with index {d}"; | 4709 | const template = "missing tuple field with index {d}"; |
| 4709 | if (root_msg) |msg| { | 4710 | if (root_msg) |msg| { |
| 4710 | try sema.errNote(block, init_src, msg, template, .{i}); | 4711 | try sema.errNote(block, init_src, msg, template, .{i}); |
| ... | @@ -4712,8 +4713,7 @@ fn validateStructInit( | ... | @@ -4712,8 +4713,7 @@ fn validateStructInit( |
| 4712 | root_msg = try sema.errMsg(block, init_src, template, .{i}); | 4713 | root_msg = try sema.errMsg(block, init_src, template, .{i}); |
| 4713 | } | 4714 | } |
| 4714 | continue; | 4715 | continue; |
| 4715 | } | 4716 | }; |
| 4716 | const field_name = struct_ty.structFieldName(i, mod); | ||
| 4717 | const template = "missing struct field: {}"; | 4717 | const template = "missing struct field: {}"; |
| 4718 | const args = .{field_name.fmt(ip)}; | 4718 | const args = .{field_name.fmt(ip)}; |
| 4719 | if (root_msg) |msg| { | 4719 | if (root_msg) |msg| { |
| ... | @@ -4763,7 +4763,8 @@ fn validateStructInit( | ... | @@ -4763,7 +4763,8 @@ fn validateStructInit( |
| 4763 | // ends up being comptime-known. | 4763 | // ends up being comptime-known. |
| 4764 | const field_values = try sema.arena.alloc(InternPool.Index, struct_ty.structFieldCount(mod)); | 4764 | const field_values = try sema.arena.alloc(InternPool.Index, struct_ty.structFieldCount(mod)); |
| 4765 | 4765 | ||
| 4766 | field: for (found_fields, 0..) |field_ptr, i| { | 4766 | field: for (found_fields, 0..) |field_ptr, i_usize| { |
| 4767 | const i: u32 = @intCast(i_usize); | ||
| 4767 | if (field_ptr != 0) { | 4768 | if (field_ptr != 0) { |
| 4768 | // Determine whether the value stored to this pointer is comptime-known. | 4769 | // Determine whether the value stored to this pointer is comptime-known. |
| 4769 | const field_ty = struct_ty.structFieldType(i, mod); | 4770 | const field_ty = struct_ty.structFieldType(i, mod); |
| ... | @@ -4842,7 +4843,7 @@ fn validateStructInit( | ... | @@ -4842,7 +4843,7 @@ fn validateStructInit( |
| 4842 | 4843 | ||
| 4843 | const default_val = struct_ty.structFieldDefaultValue(i, mod); | 4844 | const default_val = struct_ty.structFieldDefaultValue(i, mod); |
| 4844 | if (default_val.toIntern() == .unreachable_value) { | 4845 | if (default_val.toIntern() == .unreachable_value) { |
| 4845 | if (struct_ty.isTuple(mod)) { | 4846 | const field_name = struct_ty.structFieldName(i, mod).unwrap() orelse { |
| 4846 | const template = "missing tuple field with index {d}"; | 4847 | const template = "missing tuple field with index {d}"; |
| 4847 | if (root_msg) |msg| { | 4848 | if (root_msg) |msg| { |
| 4848 | try sema.errNote(block, init_src, msg, template, .{i}); | 4849 | try sema.errNote(block, init_src, msg, template, .{i}); |
| ... | @@ -4850,8 +4851,7 @@ fn validateStructInit( | ... | @@ -4850,8 +4851,7 @@ fn validateStructInit( |
| 4850 | root_msg = try sema.errMsg(block, init_src, template, .{i}); | 4851 | root_msg = try sema.errMsg(block, init_src, template, .{i}); |
| 4851 | } | 4852 | } |
| 4852 | continue; | 4853 | continue; |
| 4853 | } | 4854 | }; |
| 4854 | const field_name = struct_ty.structFieldName(i, mod); | ||
| 4855 | const template = "missing struct field: {}"; | 4855 | const template = "missing struct field: {}"; |
| 4856 | const args = .{field_name.fmt(ip)}; | 4856 | const args = .{field_name.fmt(ip)}; |
| 4857 | if (root_msg) |msg| { | 4857 | if (root_msg) |msg| { |
| ... | @@ -21862,10 +21862,10 @@ fn ptrCastFull( | ... | @@ -21862,10 +21862,10 @@ fn ptrCastFull( |
| 21862 | const msg = try sema.errMsg(block, src, "cast increases pointer alignment", .{}); | 21862 | const msg = try sema.errMsg(block, src, "cast increases pointer alignment", .{}); |
| 21863 | errdefer msg.destroy(sema.gpa); | 21863 | errdefer msg.destroy(sema.gpa); |
| 21864 | try sema.errNote(block, operand_src, msg, "'{}' has alignment '{d}'", .{ | 21864 | try sema.errNote(block, operand_src, msg, "'{}' has alignment '{d}'", .{ |
| 21865 | operand_ty.fmt(mod), src_align, | 21865 | operand_ty.fmt(mod), src_align.toByteUnits(0), |
| 21866 | }); | 21866 | }); |
| 21867 | try sema.errNote(block, src, msg, "'{}' has alignment '{d}'", .{ | 21867 | try sema.errNote(block, src, msg, "'{}' has alignment '{d}'", .{ |
| 21868 | dest_ty.fmt(mod), dest_align, | 21868 | dest_ty.fmt(mod), dest_align.toByteUnits(0), |
| 21869 | }); | 21869 | }); |
| 21870 | try sema.errNote(block, src, msg, "use @alignCast to assert pointer alignment", .{}); | 21870 | try sema.errNote(block, src, msg, "use @alignCast to assert pointer alignment", .{}); |
| 21871 | break :msg msg; | 21871 | break :msg msg; |
| ... | @@ -26376,7 +26376,7 @@ fn fieldCallBind( | ... | @@ -26376,7 +26376,7 @@ fn fieldCallBind( |
| 26376 | const max = concrete_ty.structFieldCount(mod); | 26376 | const max = concrete_ty.structFieldCount(mod); |
| 26377 | for (0..max) |i_usize| { | 26377 | for (0..max) |i_usize| { |
| 26378 | const i: u32 = @intCast(i_usize); | 26378 | const i: u32 = @intCast(i_usize); |
| 26379 | if (field_name == concrete_ty.structFieldName(i, mod)) { | 26379 | if (field_name == concrete_ty.structFieldName(i, mod).unwrap().?) { |
| 26380 | return sema.finishFieldCallBind(block, src, ptr_ty, concrete_ty.structFieldType(i, mod), i, object_ptr); | 26380 | return sema.finishFieldCallBind(block, src, ptr_ty, concrete_ty.structFieldType(i, mod), i, object_ptr); |
| 26381 | } | 26381 | } |
| 26382 | } | 26382 | } |
| ... | @@ -31143,7 +31143,8 @@ fn coerceTupleToTuple( | ... | @@ -31143,7 +31143,8 @@ fn coerceTupleToTuple( |
| 31143 | var root_msg: ?*Module.ErrorMsg = null; | 31143 | var root_msg: ?*Module.ErrorMsg = null; |
| 31144 | errdefer if (root_msg) |msg| msg.destroy(sema.gpa); | 31144 | errdefer if (root_msg) |msg| msg.destroy(sema.gpa); |
| 31145 | 31145 | ||
| 31146 | for (field_refs, 0..) |*field_ref, i| { | 31146 | for (field_refs, 0..) |*field_ref, i_usize| { |
| 31147 | const i: u32 = @intCast(i_usize); | ||
| 31147 | if (field_ref.* != .none) continue; | 31148 | if (field_ref.* != .none) continue; |
| 31148 | 31149 | ||
| 31149 | const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) { | 31150 | const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) { |
| ... | @@ -31154,7 +31155,7 @@ fn coerceTupleToTuple( | ... | @@ -31154,7 +31155,7 @@ fn coerceTupleToTuple( |
| 31154 | 31155 | ||
| 31155 | const field_src = inst_src; // TODO better source location | 31156 | const field_src = inst_src; // TODO better source location |
| 31156 | if (default_val == .none) { | 31157 | if (default_val == .none) { |
| 31157 | if (tuple_ty.isTuple(mod)) { | 31158 | const field_name = tuple_ty.structFieldName(i, mod).unwrap() orelse { |
| 31158 | const template = "missing tuple field: {d}"; | 31159 | const template = "missing tuple field: {d}"; |
| 31159 | if (root_msg) |msg| { | 31160 | if (root_msg) |msg| { |
| 31160 | try sema.errNote(block, field_src, msg, template, .{i}); | 31161 | try sema.errNote(block, field_src, msg, template, .{i}); |
| ... | @@ -31162,9 +31163,9 @@ fn coerceTupleToTuple( | ... | @@ -31162,9 +31163,9 @@ fn coerceTupleToTuple( |
| 31162 | root_msg = try sema.errMsg(block, field_src, template, .{i}); | 31163 | root_msg = try sema.errMsg(block, field_src, template, .{i}); |
| 31163 | } | 31164 | } |
| 31164 | continue; | 31165 | continue; |
| 31165 | } | 31166 | }; |
| 31166 | const template = "missing struct field: {}"; | 31167 | const template = "missing struct field: {}"; |
| 31167 | const args = .{tuple_ty.structFieldName(i, mod).fmt(ip)}; | 31168 | const args = .{field_name.fmt(ip)}; |
| 31168 | if (root_msg) |msg| { | 31169 | if (root_msg) |msg| { |
| 31169 | try sema.errNote(block, field_src, msg, template, args); | 31170 | try sema.errNote(block, field_src, msg, template, args); |
| 31170 | } else { | 31171 | } else { |
| ... | @@ -33897,8 +33898,9 @@ fn resolvePeerTypesInner( | ... | @@ -33897,8 +33898,9 @@ fn resolvePeerTypesInner( |
| 33897 | } | 33898 | } |
| 33898 | 33899 | ||
| 33899 | if (!is_tuple) { | 33900 | if (!is_tuple) { |
| 33900 | for (field_names, 0..) |expected, field_idx| { | 33901 | for (field_names, 0..) |expected, field_index_usize| { |
| 33901 | const actual = ty.structFieldName(field_idx, mod); | 33902 | const field_index: u32 = @intCast(field_index_usize); |
| 33903 | const actual = ty.structFieldName(field_index, mod).unwrap().?; | ||
| 33902 | if (actual == expected) continue; | 33904 | if (actual == expected) continue; |
| 33903 | return .{ .conflict = .{ | 33905 | return .{ .conflict = .{ |
| 33904 | .peer_idx_a = first_idx, | 33906 | .peer_idx_a = first_idx, |
src/TypedValue.zig+3-3| ... | @@ -355,11 +355,11 @@ pub fn print( | ... | @@ -355,11 +355,11 @@ pub fn print( |
| 355 | const container_ty = ptr_container_ty.childType(mod); | 355 | const container_ty = ptr_container_ty.childType(mod); |
| 356 | switch (container_ty.zigTypeTag(mod)) { | 356 | switch (container_ty.zigTypeTag(mod)) { |
| 357 | .Struct => { | 357 | .Struct => { |
| 358 | if (container_ty.isTuple(mod)) { | 358 | if (container_ty.structFieldName(@intCast(field.index), mod).unwrap()) |field_name| { |
| 359 | try writer.print(".{i}", .{field_name.fmt(ip)}); | ||
| 360 | } else { | ||
| 359 | try writer.print("[{d}]", .{field.index}); | 361 | try writer.print("[{d}]", .{field.index}); |
| 360 | } | 362 | } |
| 361 | const field_name = container_ty.structFieldName(@as(usize, @intCast(field.index)), mod); | ||
| 362 | try writer.print(".{i}", .{field_name.fmt(ip)}); | ||
| 363 | }, | 363 | }, |
| 364 | .Union => { | 364 | .Union => { |
| 365 | const field_name = mod.typeToUnion(container_ty).?.field_names.get(ip)[@intCast(field.index)]; | 365 | const field_name = mod.typeToUnion(container_ty).?.field_names.get(ip)[@intCast(field.index)]; |
src/codegen/c.zig+8-6| ... | @@ -5226,7 +5226,8 @@ fn fieldLocation( | ... | @@ -5226,7 +5226,8 @@ fn fieldLocation( |
| 5226 | const container_ty = container_ptr_ty.childType(mod); | 5226 | const container_ty = container_ptr_ty.childType(mod); |
| 5227 | return switch (container_ty.zigTypeTag(mod)) { | 5227 | return switch (container_ty.zigTypeTag(mod)) { |
| 5228 | .Struct => switch (container_ty.containerLayout(mod)) { | 5228 | .Struct => switch (container_ty.containerLayout(mod)) { |
| 5229 | .Auto, .Extern => for (field_index..container_ty.structFieldCount(mod)) |next_field_index| { | 5229 | .Auto, .Extern => for (field_index..container_ty.structFieldCount(mod)) |next_field_index_usize| { |
| 5230 | const next_field_index: u32 = @intCast(next_field_index_usize); | ||
| 5230 | if (container_ty.structFieldIsComptime(next_field_index, mod)) continue; | 5231 | if (container_ty.structFieldIsComptime(next_field_index, mod)) continue; |
| 5231 | const field_ty = container_ty.structFieldType(next_field_index, mod); | 5232 | const field_ty = container_ty.structFieldType(next_field_index, mod); |
| 5232 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 5233 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| ... | @@ -5234,7 +5235,7 @@ fn fieldLocation( | ... | @@ -5234,7 +5235,7 @@ fn fieldLocation( |
| 5234 | break .{ .field = if (container_ty.isSimpleTuple(mod)) | 5235 | break .{ .field = if (container_ty.isSimpleTuple(mod)) |
| 5235 | .{ .field = next_field_index } | 5236 | .{ .field = next_field_index } |
| 5236 | else | 5237 | else |
| 5237 | .{ .identifier = ip.stringToSlice(container_ty.structFieldName(next_field_index, mod)) } }; | 5238 | .{ .identifier = ip.stringToSlice(container_ty.legacyStructFieldName(next_field_index, mod)) } }; |
| 5238 | } else if (container_ty.hasRuntimeBitsIgnoreComptime(mod)) .end else .begin, | 5239 | } else if (container_ty.hasRuntimeBitsIgnoreComptime(mod)) .end else .begin, |
| 5239 | .Packed => if (field_ptr_ty.ptrInfo(mod).packed_offset.host_size == 0) | 5240 | .Packed => if (field_ptr_ty.ptrInfo(mod).packed_offset.host_size == 0) |
| 5240 | .{ .byte_offset = container_ty.packedStructFieldByteOffset(field_index, mod) + @divExact(container_ptr_ty.ptrInfo(mod).packed_offset.bit_offset, 8) } | 5241 | .{ .byte_offset = container_ty.packedStructFieldByteOffset(field_index, mod) + @divExact(container_ptr_ty.ptrInfo(mod).packed_offset.bit_offset, 8) } |
| ... | @@ -5421,7 +5422,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5421,7 +5422,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5421 | .Auto, .Extern => if (struct_ty.isSimpleTuple(mod)) | 5422 | .Auto, .Extern => if (struct_ty.isSimpleTuple(mod)) |
| 5422 | .{ .field = extra.field_index } | 5423 | .{ .field = extra.field_index } |
| 5423 | else | 5424 | else |
| 5424 | .{ .identifier = ip.stringToSlice(struct_ty.structFieldName(extra.field_index, mod)) }, | 5425 | .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, mod)) }, |
| 5425 | .Packed => { | 5426 | .Packed => { |
| 5426 | const struct_type = mod.typeToStruct(struct_ty).?; | 5427 | const struct_type = mod.typeToStruct(struct_ty).?; |
| 5427 | const int_info = struct_ty.intInfo(mod); | 5428 | const int_info = struct_ty.intInfo(mod); |
| ... | @@ -5483,7 +5484,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5483,7 +5484,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5483 | .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len == 0) | 5484 | .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len == 0) |
| 5484 | .{ .field = extra.field_index } | 5485 | .{ .field = extra.field_index } |
| 5485 | else | 5486 | else |
| 5486 | .{ .identifier = ip.stringToSlice(struct_ty.structFieldName(extra.field_index, mod)) }, | 5487 | .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, mod)) }, |
| 5487 | 5488 | ||
| 5488 | .union_type => |union_type| field_name: { | 5489 | .union_type => |union_type| field_name: { |
| 5489 | const union_obj = ip.loadUnionType(union_type); | 5490 | const union_obj = ip.loadUnionType(union_type); |
| ... | @@ -6816,7 +6817,8 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6816,7 +6817,8 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6816 | } | 6817 | } |
| 6817 | }, | 6818 | }, |
| 6818 | .Struct => switch (inst_ty.containerLayout(mod)) { | 6819 | .Struct => switch (inst_ty.containerLayout(mod)) { |
| 6819 | .Auto, .Extern => for (resolved_elements, 0..) |element, field_i| { | 6820 | .Auto, .Extern => for (resolved_elements, 0..) |element, field_i_usize| { |
| 6821 | const field_i: u32 = @intCast(field_i_usize); | ||
| 6820 | if (inst_ty.structFieldIsComptime(field_i, mod)) continue; | 6822 | if (inst_ty.structFieldIsComptime(field_i, mod)) continue; |
| 6821 | const field_ty = inst_ty.structFieldType(field_i, mod); | 6823 | const field_ty = inst_ty.structFieldType(field_i, mod); |
| 6822 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 6824 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| ... | @@ -6825,7 +6827,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6825,7 +6827,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6825 | try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple(mod)) | 6827 | try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple(mod)) |
| 6826 | .{ .field = field_i } | 6828 | .{ .field = field_i } |
| 6827 | else | 6829 | else |
| 6828 | .{ .identifier = ip.stringToSlice(inst_ty.structFieldName(field_i, mod)) }); | 6830 | .{ .identifier = ip.stringToSlice(inst_ty.legacyStructFieldName(field_i, mod)) }); |
| 6829 | try a.assign(f, writer); | 6831 | try a.assign(f, writer); |
| 6830 | try f.writeCValue(writer, element, .Other); | 6832 | try f.writeCValue(writer, element, .Other); |
| 6831 | try a.end(f, writer); | 6833 | try a.end(f, writer); |
src/codegen/c/type.zig+9-6| ... | @@ -1953,7 +1953,8 @@ pub const CType = extern union { | ... | @@ -1953,7 +1953,8 @@ pub const CType = extern union { |
| 1953 | 1953 | ||
| 1954 | const fields_pl = try arena.alloc(Payload.Fields.Field, c_fields_len); | 1954 | const fields_pl = try arena.alloc(Payload.Fields.Field, c_fields_len); |
| 1955 | var c_field_i: usize = 0; | 1955 | var c_field_i: usize = 0; |
| 1956 | for (0..fields_len) |field_i| { | 1956 | for (0..fields_len) |field_i_usize| { |
| 1957 | const field_i: u32 = @intCast(field_i_usize); | ||
| 1957 | const field_ty = ty.structFieldType(field_i, mod); | 1958 | const field_ty = ty.structFieldType(field_i, mod); |
| 1958 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or | 1959 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or |
| 1959 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 1960 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| ... | @@ -1964,7 +1965,7 @@ pub const CType = extern union { | ... | @@ -1964,7 +1965,7 @@ pub const CType = extern union { |
| 1964 | std.fmt.allocPrintZ(arena, "f{}", .{field_i}) | 1965 | std.fmt.allocPrintZ(arena, "f{}", .{field_i}) |
| 1965 | else | 1966 | else |
| 1966 | arena.dupeZ(u8, ip.stringToSlice(switch (zig_ty_tag) { | 1967 | arena.dupeZ(u8, ip.stringToSlice(switch (zig_ty_tag) { |
| 1967 | .Struct => ty.structFieldName(field_i, mod), | 1968 | .Struct => ty.legacyStructFieldName(field_i, mod), |
| 1968 | .Union => mod.typeToUnion(ty).?.field_names.get(ip)[field_i], | 1969 | .Union => mod.typeToUnion(ty).?.field_names.get(ip)[field_i], |
| 1969 | else => unreachable, | 1970 | else => unreachable, |
| 1970 | })), | 1971 | })), |
| ... | @@ -2097,7 +2098,8 @@ pub const CType = extern union { | ... | @@ -2097,7 +2098,8 @@ pub const CType = extern union { |
| 2097 | .Struct => ty.structFieldCount(mod), | 2098 | .Struct => ty.structFieldCount(mod), |
| 2098 | .Union => mod.typeToUnion(ty).?.field_names.len, | 2099 | .Union => mod.typeToUnion(ty).?.field_names.len, |
| 2099 | else => unreachable, | 2100 | else => unreachable, |
| 2100 | }) |field_i| { | 2101 | }) |field_i_usize| { |
| 2102 | const field_i: u32 = @intCast(field_i_usize); | ||
| 2101 | const field_ty = ty.structFieldType(field_i, mod); | 2103 | const field_ty = ty.structFieldType(field_i, mod); |
| 2102 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or | 2104 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or |
| 2103 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 2105 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| ... | @@ -2116,7 +2118,7 @@ pub const CType = extern union { | ... | @@ -2116,7 +2118,7 @@ pub const CType = extern union { |
| 2116 | std.fmt.bufPrintZ(&name_buf, "f{}", .{field_i}) catch unreachable | 2118 | std.fmt.bufPrintZ(&name_buf, "f{}", .{field_i}) catch unreachable |
| 2117 | else | 2119 | else |
| 2118 | ip.stringToSlice(switch (zig_ty_tag) { | 2120 | ip.stringToSlice(switch (zig_ty_tag) { |
| 2119 | .Struct => ty.structFieldName(field_i, mod), | 2121 | .Struct => ty.legacyStructFieldName(field_i, mod), |
| 2120 | .Union => mod.typeToUnion(ty).?.field_names.get(ip)[field_i], | 2122 | .Union => mod.typeToUnion(ty).?.field_names.get(ip)[field_i], |
| 2121 | else => unreachable, | 2123 | else => unreachable, |
| 2122 | }), | 2124 | }), |
| ... | @@ -2225,7 +2227,8 @@ pub const CType = extern union { | ... | @@ -2225,7 +2227,8 @@ pub const CType = extern union { |
| 2225 | .Struct => ty.structFieldCount(mod), | 2227 | .Struct => ty.structFieldCount(mod), |
| 2226 | .Union => mod.typeToUnion(ty).?.field_names.len, | 2228 | .Union => mod.typeToUnion(ty).?.field_names.len, |
| 2227 | else => unreachable, | 2229 | else => unreachable, |
| 2228 | }) |field_i| { | 2230 | }) |field_i_usize| { |
| 2231 | const field_i: u32 = @intCast(field_i_usize); | ||
| 2229 | const field_ty = ty.structFieldType(field_i, mod); | 2232 | const field_ty = ty.structFieldType(field_i, mod); |
| 2230 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or | 2233 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or |
| 2231 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 2234 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| ... | @@ -2240,7 +2243,7 @@ pub const CType = extern union { | ... | @@ -2240,7 +2243,7 @@ pub const CType = extern union { |
| 2240 | std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable | 2243 | std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable |
| 2241 | else | 2244 | else |
| 2242 | mod.intern_pool.stringToSlice(switch (zig_ty_tag) { | 2245 | mod.intern_pool.stringToSlice(switch (zig_ty_tag) { |
| 2243 | .Struct => ty.structFieldName(field_i, mod), | 2246 | .Struct => ty.legacyStructFieldName(field_i, mod), |
| 2244 | .Union => mod.typeToUnion(ty).?.field_names.get(ip)[field_i], | 2247 | .Union => mod.typeToUnion(ty).?.field_names.get(ip)[field_i], |
| 2245 | else => unreachable, | 2248 | else => unreachable, |
| 2246 | })); | 2249 | })); |
src/type.zig+16-4| ... | @@ -2907,16 +2907,28 @@ pub const Type = struct { | ... | @@ -2907,16 +2907,28 @@ pub const Type = struct { |
| 2907 | return enum_type.tagValueIndex(ip, int_tag); | 2907 | return enum_type.tagValueIndex(ip, int_tag); |
| 2908 | } | 2908 | } |
| 2909 | 2909 | ||
| 2910 | pub fn structFieldName(ty: Type, field_index: usize, mod: *Module) InternPool.NullTerminatedString { | 2910 | /// Returns none in the case of a tuple which uses the integer index as the field name. |
| 2911 | pub fn structFieldName(ty: Type, field_index: u32, mod: *Module) InternPool.OptionalNullTerminatedString { | ||
| 2911 | const ip = &mod.intern_pool; | 2912 | const ip = &mod.intern_pool; |
| 2912 | return switch (ip.indexToKey(ty.toIntern())) { | 2913 | return switch (ip.indexToKey(ty.toIntern())) { |
| 2913 | .struct_type => |struct_type| struct_type.field_names.get(ip)[field_index], | 2914 | .struct_type => |struct_type| struct_type.fieldName(ip, field_index), |
| 2914 | .anon_struct_type => |anon_struct| anon_struct.names.get(ip)[field_index], | 2915 | .anon_struct_type => |anon_struct| anon_struct.fieldName(ip, field_index), |
| 2915 | else => unreachable, | 2916 | else => unreachable, |
| 2916 | }; | 2917 | }; |
| 2917 | } | 2918 | } |
| 2918 | 2919 | ||
| 2919 | pub fn structFieldCount(ty: Type, mod: *Module) usize { | 2920 | /// When struct types have no field names, the names are implicitly understood to be |
| 2921 | /// strings corresponding to the field indexes in declaration order. It used to be the | ||
| 2922 | /// case that a NullTerminatedString would be stored for each field in this case, however, | ||
| 2923 | /// now, callers must handle the possibility that there are no names stored at all. | ||
| 2924 | /// Here we fake the previous behavior. Probably something better could be done by examining | ||
| 2925 | /// all the callsites of this function. | ||
| 2926 | pub fn legacyStructFieldName(ty: Type, i: u32, mod: *Module) InternPool.NullTerminatedString { | ||
| 2927 | return ty.structFieldName(i, mod).unwrap() orelse | ||
| 2928 | mod.intern_pool.getOrPutStringFmt(mod.gpa, "{d}", .{i}) catch @panic("OOM"); | ||
| 2929 | } | ||
| 2930 | |||
| 2931 | pub fn structFieldCount(ty: Type, mod: *Module) u32 { | ||
| 2920 | const ip = &mod.intern_pool; | 2932 | const ip = &mod.intern_pool; |
| 2921 | return switch (ip.indexToKey(ty.toIntern())) { | 2933 | return switch (ip.indexToKey(ty.toIntern())) { |
| 2922 | .struct_type => |struct_type| struct_type.field_types.len, | 2934 | .struct_type => |struct_type| struct_type.field_types.len, |