aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2023-09-21 17:29:34 -0700
committerAndrew Kelley <andrew@ziglang.org>2023-09-21 17:29:34 -0700
commit81b5df347a2b92566dc679fdd4e110812dfe27d0 (patch)
tree2e2580b944374f490797ef3211eb752c7b1bc051 /src/Sema.zig
parentedfada4317760a152ad9c36b39f5a2e68eeaebf8 (diff)
downloadzig-81b5df347a2b92566dc679fdd4e110812dfe27d0.tar.gz
zig-81b5df347a2b92566dc679fdd4e110812dfe27d0.zip
compiler: fix structFieldName crash for tuples
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.
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig36
1 files changed, 19 insertions, 17 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index ca5b692da1..5c08102a27 100644
--- a/src/Sema.zig
+++ b/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,