fn failUnexpected(
self: @This(),
T: type,
item_kind: []const u8,
node: Zoir.Node.Index,
field: ?usize,
name: []const u8,
) error{ OutOfMemory, ParseZon } {
@branchHint(.cold);
if (self.diag == null) return error.ParseZon;
const gpa = self.gpa;
const token = if (field) |f| b: {
var buf: [2]Ast.Node.Index = undefined;
const struct_init = self.ast.fullStructInit(&buf, node.getAstNode(self.zoir)).?;
const field_node = struct_init.ast.fields[f];
break :b self.ast.firstToken(field_node) - 2;
} else self.ast.nodeMainToken(node.getAstNode(self.zoir));
switch (@typeInfo(T)) {
inline .@"struct", .@"union", .@"enum" => |info| {
const note: Error.TypeCheckFailure.Note = if (info.field_names.len == 0) b: {
break :b .{
.token = token,
.offset = 0,
.msg = "none expected",
.owned = false,
};
} else b: {
const msg = "supported: ";
var buf: std.ArrayList(u8) = try .initCapacity(gpa, 64);
defer buf.deinit(gpa);
try buf.appendSlice(gpa, msg);
inline for (info.field_names, 0..) |field_name, i| {
if (i != 0) try buf.appendSlice(gpa, ", ");
try buf.print(gpa, "'{f}'", .{std.zig.fmtIdFlags(field_name, .{
.allow_primitive = true,
.allow_underscore = true,
})});
}
break :b .{
.token = token,
.offset = 0,
.msg = try buf.toOwnedSlice(gpa),
.owned = true,
};
};
return self.failTokenFmtNote(
token,
0,
"unexpected {s} '{s}'",
.{ item_kind, name },
note,
);
},
else => comptime unreachable,
}
}