Commit 81b5df347a
Changed files (6)
src/codegen/c/type.zig
@@ -1953,7 +1953,8 @@ pub const CType = extern union {
const fields_pl = try arena.alloc(Payload.Fields.Field, c_fields_len);
var c_field_i: usize = 0;
- for (0..fields_len) |field_i| {
+ for (0..fields_len) |field_i_usize| {
+ const field_i: u32 = @intCast(field_i_usize);
const field_ty = ty.structFieldType(field_i, mod);
if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
@@ -1964,7 +1965,7 @@ pub const CType = extern union {
std.fmt.allocPrintZ(arena, "f{}", .{field_i})
else
arena.dupeZ(u8, ip.stringToSlice(switch (zig_ty_tag) {
- .Struct => ty.structFieldName(field_i, mod),
+ .Struct => ty.legacyStructFieldName(field_i, mod),
.Union => mod.typeToUnion(ty).?.field_names.get(ip)[field_i],
else => unreachable,
})),
@@ -2097,7 +2098,8 @@ pub const CType = extern union {
.Struct => ty.structFieldCount(mod),
.Union => mod.typeToUnion(ty).?.field_names.len,
else => unreachable,
- }) |field_i| {
+ }) |field_i_usize| {
+ const field_i: u32 = @intCast(field_i_usize);
const field_ty = ty.structFieldType(field_i, mod);
if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
@@ -2116,7 +2118,7 @@ pub const CType = extern union {
std.fmt.bufPrintZ(&name_buf, "f{}", .{field_i}) catch unreachable
else
ip.stringToSlice(switch (zig_ty_tag) {
- .Struct => ty.structFieldName(field_i, mod),
+ .Struct => ty.legacyStructFieldName(field_i, mod),
.Union => mod.typeToUnion(ty).?.field_names.get(ip)[field_i],
else => unreachable,
}),
@@ -2225,7 +2227,8 @@ pub const CType = extern union {
.Struct => ty.structFieldCount(mod),
.Union => mod.typeToUnion(ty).?.field_names.len,
else => unreachable,
- }) |field_i| {
+ }) |field_i_usize| {
+ const field_i: u32 = @intCast(field_i_usize);
const field_ty = ty.structFieldType(field_i, mod);
if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
@@ -2240,7 +2243,7 @@ pub const CType = extern union {
std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable
else
mod.intern_pool.stringToSlice(switch (zig_ty_tag) {
- .Struct => ty.structFieldName(field_i, mod),
+ .Struct => ty.legacyStructFieldName(field_i, mod),
.Union => mod.typeToUnion(ty).?.field_names.get(ip)[field_i],
else => unreachable,
}));
src/codegen/c.zig
@@ -5226,7 +5226,8 @@ fn fieldLocation(
const container_ty = container_ptr_ty.childType(mod);
return switch (container_ty.zigTypeTag(mod)) {
.Struct => switch (container_ty.containerLayout(mod)) {
- .Auto, .Extern => for (field_index..container_ty.structFieldCount(mod)) |next_field_index| {
+ .Auto, .Extern => for (field_index..container_ty.structFieldCount(mod)) |next_field_index_usize| {
+ const next_field_index: u32 = @intCast(next_field_index_usize);
if (container_ty.structFieldIsComptime(next_field_index, mod)) continue;
const field_ty = container_ty.structFieldType(next_field_index, mod);
if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
@@ -5234,7 +5235,7 @@ fn fieldLocation(
break .{ .field = if (container_ty.isSimpleTuple(mod))
.{ .field = next_field_index }
else
- .{ .identifier = ip.stringToSlice(container_ty.structFieldName(next_field_index, mod)) } };
+ .{ .identifier = ip.stringToSlice(container_ty.legacyStructFieldName(next_field_index, mod)) } };
} else if (container_ty.hasRuntimeBitsIgnoreComptime(mod)) .end else .begin,
.Packed => if (field_ptr_ty.ptrInfo(mod).packed_offset.host_size == 0)
.{ .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 {
.Auto, .Extern => if (struct_ty.isSimpleTuple(mod))
.{ .field = extra.field_index }
else
- .{ .identifier = ip.stringToSlice(struct_ty.structFieldName(extra.field_index, mod)) },
+ .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, mod)) },
.Packed => {
const struct_type = mod.typeToStruct(struct_ty).?;
const int_info = struct_ty.intInfo(mod);
@@ -5483,7 +5484,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
.anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len == 0)
.{ .field = extra.field_index }
else
- .{ .identifier = ip.stringToSlice(struct_ty.structFieldName(extra.field_index, mod)) },
+ .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, mod)) },
.union_type => |union_type| field_name: {
const union_obj = ip.loadUnionType(union_type);
@@ -6816,7 +6817,8 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
}
},
.Struct => switch (inst_ty.containerLayout(mod)) {
- .Auto, .Extern => for (resolved_elements, 0..) |element, field_i| {
+ .Auto, .Extern => for (resolved_elements, 0..) |element, field_i_usize| {
+ const field_i: u32 = @intCast(field_i_usize);
if (inst_ty.structFieldIsComptime(field_i, mod)) continue;
const field_ty = inst_ty.structFieldType(field_i, mod);
if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
@@ -6825,7 +6827,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple(mod))
.{ .field = field_i }
else
- .{ .identifier = ip.stringToSlice(inst_ty.structFieldName(field_i, mod)) });
+ .{ .identifier = ip.stringToSlice(inst_ty.legacyStructFieldName(field_i, mod)) });
try a.assign(f, writer);
try f.writeCValue(writer, element, .Other);
try a.end(f, writer);
src/InternPool.zig
@@ -656,6 +656,17 @@ pub const Key = union(enum) {
pub fn isTuple(self: AnonStructType) bool {
return self.names.len == 0;
}
+
+ pub fn fieldName(
+ self: AnonStructType,
+ ip: *const InternPool,
+ index: u32,
+ ) OptionalNullTerminatedString {
+ if (self.names.len == 0)
+ return .none;
+
+ return self.names.get(ip)[index].toOptional();
+ }
};
/// Serves two purposes:
src/Sema.zig
@@ -4699,12 +4699,13 @@ fn validateStructInit(
// In this case the only thing we need to do is evaluate the implicit
// store instructions for default field values, and report any missing fields.
// Avoid the cost of the extra machinery for detecting a comptime struct init value.
- for (found_fields, 0..) |field_ptr, i| {
+ for (found_fields, 0..) |field_ptr, i_usize| {
+ const i: u32 = @intCast(i_usize);
if (field_ptr != 0) continue;
const default_val = struct_ty.structFieldDefaultValue(i, mod);
if (default_val.toIntern() == .unreachable_value) {
- if (struct_ty.isTuple(mod)) {
+ const field_name = struct_ty.structFieldName(i, mod).unwrap() orelse {
const template = "missing tuple field with index {d}";
if (root_msg) |msg| {
try sema.errNote(block, init_src, msg, template, .{i});
@@ -4712,8 +4713,7 @@ fn validateStructInit(
root_msg = try sema.errMsg(block, init_src, template, .{i});
}
continue;
- }
- const field_name = struct_ty.structFieldName(i, mod);
+ };
const template = "missing struct field: {}";
const args = .{field_name.fmt(ip)};
if (root_msg) |msg| {
@@ -4763,7 +4763,8 @@ fn validateStructInit(
// ends up being comptime-known.
const field_values = try sema.arena.alloc(InternPool.Index, struct_ty.structFieldCount(mod));
- field: for (found_fields, 0..) |field_ptr, i| {
+ field: for (found_fields, 0..) |field_ptr, i_usize| {
+ const i: u32 = @intCast(i_usize);
if (field_ptr != 0) {
// Determine whether the value stored to this pointer is comptime-known.
const field_ty = struct_ty.structFieldType(i, mod);
@@ -4842,7 +4843,7 @@ fn validateStructInit(
const default_val = struct_ty.structFieldDefaultValue(i, mod);
if (default_val.toIntern() == .unreachable_value) {
- if (struct_ty.isTuple(mod)) {
+ const field_name = struct_ty.structFieldName(i, mod).unwrap() orelse {
const template = "missing tuple field with index {d}";
if (root_msg) |msg| {
try sema.errNote(block, init_src, msg, template, .{i});
@@ -4850,8 +4851,7 @@ fn validateStructInit(
root_msg = try sema.errMsg(block, init_src, template, .{i});
}
continue;
- }
- const field_name = struct_ty.structFieldName(i, mod);
+ };
const template = "missing struct field: {}";
const args = .{field_name.fmt(ip)};
if (root_msg) |msg| {
@@ -21862,10 +21862,10 @@ fn ptrCastFull(
const msg = try sema.errMsg(block, src, "cast increases pointer alignment", .{});
errdefer msg.destroy(sema.gpa);
try sema.errNote(block, operand_src, msg, "'{}' has alignment '{d}'", .{
- operand_ty.fmt(mod), src_align,
+ operand_ty.fmt(mod), src_align.toByteUnits(0),
});
try sema.errNote(block, src, msg, "'{}' has alignment '{d}'", .{
- dest_ty.fmt(mod), dest_align,
+ dest_ty.fmt(mod), dest_align.toByteUnits(0),
});
try sema.errNote(block, src, msg, "use @alignCast to assert pointer alignment", .{});
break :msg msg;
@@ -26376,7 +26376,7 @@ fn fieldCallBind(
const max = concrete_ty.structFieldCount(mod);
for (0..max) |i_usize| {
const i: u32 = @intCast(i_usize);
- if (field_name == concrete_ty.structFieldName(i, mod)) {
+ if (field_name == concrete_ty.structFieldName(i, mod).unwrap().?) {
return sema.finishFieldCallBind(block, src, ptr_ty, concrete_ty.structFieldType(i, mod), i, object_ptr);
}
}
@@ -31143,7 +31143,8 @@ fn coerceTupleToTuple(
var root_msg: ?*Module.ErrorMsg = null;
errdefer if (root_msg) |msg| msg.destroy(sema.gpa);
- for (field_refs, 0..) |*field_ref, i| {
+ for (field_refs, 0..) |*field_ref, i_usize| {
+ const i: u32 = @intCast(i_usize);
if (field_ref.* != .none) continue;
const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) {
@@ -31154,7 +31155,7 @@ fn coerceTupleToTuple(
const field_src = inst_src; // TODO better source location
if (default_val == .none) {
- if (tuple_ty.isTuple(mod)) {
+ const field_name = tuple_ty.structFieldName(i, mod).unwrap() orelse {
const template = "missing tuple field: {d}";
if (root_msg) |msg| {
try sema.errNote(block, field_src, msg, template, .{i});
@@ -31162,9 +31163,9 @@ fn coerceTupleToTuple(
root_msg = try sema.errMsg(block, field_src, template, .{i});
}
continue;
- }
+ };
const template = "missing struct field: {}";
- const args = .{tuple_ty.structFieldName(i, mod).fmt(ip)};
+ const args = .{field_name.fmt(ip)};
if (root_msg) |msg| {
try sema.errNote(block, field_src, msg, template, args);
} else {
@@ -33897,8 +33898,9 @@ fn resolvePeerTypesInner(
}
if (!is_tuple) {
- for (field_names, 0..) |expected, field_idx| {
- const actual = ty.structFieldName(field_idx, mod);
+ for (field_names, 0..) |expected, field_index_usize| {
+ const field_index: u32 = @intCast(field_index_usize);
+ const actual = ty.structFieldName(field_index, mod).unwrap().?;
if (actual == expected) continue;
return .{ .conflict = .{
.peer_idx_a = first_idx,
src/type.zig
@@ -2907,16 +2907,28 @@ pub const Type = struct {
return enum_type.tagValueIndex(ip, int_tag);
}
- pub fn structFieldName(ty: Type, field_index: usize, mod: *Module) InternPool.NullTerminatedString {
+ /// Returns none in the case of a tuple which uses the integer index as the field name.
+ pub fn structFieldName(ty: Type, field_index: u32, mod: *Module) InternPool.OptionalNullTerminatedString {
const ip = &mod.intern_pool;
return switch (ip.indexToKey(ty.toIntern())) {
- .struct_type => |struct_type| struct_type.field_names.get(ip)[field_index],
- .anon_struct_type => |anon_struct| anon_struct.names.get(ip)[field_index],
+ .struct_type => |struct_type| struct_type.fieldName(ip, field_index),
+ .anon_struct_type => |anon_struct| anon_struct.fieldName(ip, field_index),
else => unreachable,
};
}
- pub fn structFieldCount(ty: Type, mod: *Module) usize {
+ /// 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.
+ /// Here we fake the previous behavior. Probably something better could be done by examining
+ /// all the callsites of this function.
+ pub fn legacyStructFieldName(ty: Type, i: u32, mod: *Module) InternPool.NullTerminatedString {
+ return ty.structFieldName(i, mod).unwrap() orelse
+ mod.intern_pool.getOrPutStringFmt(mod.gpa, "{d}", .{i}) catch @panic("OOM");
+ }
+
+ pub fn structFieldCount(ty: Type, mod: *Module) u32 {
const ip = &mod.intern_pool;
return switch (ip.indexToKey(ty.toIntern())) {
.struct_type => |struct_type| struct_type.field_types.len,
src/TypedValue.zig
@@ -355,11 +355,11 @@ pub fn print(
const container_ty = ptr_container_ty.childType(mod);
switch (container_ty.zigTypeTag(mod)) {
.Struct => {
- if (container_ty.isTuple(mod)) {
+ if (container_ty.structFieldName(@intCast(field.index), mod).unwrap()) |field_name| {
+ try writer.print(".{i}", .{field_name.fmt(ip)});
+ } else {
try writer.print("[{d}]", .{field.index});
}
- const field_name = container_ty.structFieldName(@as(usize, @intCast(field.index)), mod);
- try writer.print(".{i}", .{field_name.fmt(ip)});
},
.Union => {
const field_name = mod.typeToUnion(container_ty).?.field_names.get(ip)[@intCast(field.index)];