Try to improve the error handling for procedure groups

This commit is contained in:
gingerBill
2026-02-19 13:51:20 +00:00
parent ad6cde0b3c
commit 7c9ac5a777

View File

@@ -7255,18 +7255,45 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c,
}
}
// auto print_argument_types = [&]() {
// error_line("\tGiven argument types: (");
// isize i = 0;
// for (Operand const &o : positional_operands) {
// if (i++ > 0) error_line(", ");
// gbString type = type_to_string(o.type);
// defer (gb_string_free(type));
// error_line("%s", type);
// }
// for (Operand const &o : named_operands) {
// if (i++ > 0) error_line(", ");
// gbString type = type_to_string(o.type);
// defer (gb_string_free(type));
// if (i < ce->split_args->named.count) {
// Ast *named_field = ce->split_args->named[i];
// ast_node(fv, FieldValue, named_field);
// gbString field = expr_to_string(fv->field);
// defer (gb_string_free(field));
// error_line("%s = %s", field, type);
// } else {
// error_line("%s", type);
// }
// }
// error_line(")\n");
// };
auto print_argument_types = [&]() {
error_line("\tGiven argument types: (");
error_line("\tGiven argument types:\n");
isize i = 0;
for (Operand const &o : positional_operands) {
if (i++ > 0) error_line(", ");
gbString type = type_to_string(o.type);
defer (gb_string_free(type));
error_line("%s", type);
error_line("\t • %s\n", type);
}
for (Operand const &o : named_operands) {
if (i++ > 0) error_line(", ");
gbString type = type_to_string(o.type);
defer (gb_string_free(type));
@@ -7277,12 +7304,11 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c,
gbString field = expr_to_string(fv->field);
defer (gb_string_free(field));
error_line("%s = %s", field, type);
error_line("\t%s = %s\n", field, type);
} else {
error_line("%s", type);
error_line("\t • %s\n", type);
}
}
error_line(")\n");
};
if (valids.count == 0) {
@@ -7298,9 +7324,6 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c,
if (procs.count == 0) {
procs = proc_group_entities_cloned(c, *operand);
}
if (procs.count > 0) {
error_line("Did you mean to use one of the following:\n");
}
// Try to reduce the list further for `$T: typeid` like parameters
bool *possibly_ignore = temporary_alloc_array<bool>(procs.count);
@@ -7397,6 +7420,80 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c,
}
spaces[max_spaces] = 0;
{
bool try_addr = false;
isize try_addr_idx = -1;
for_array(i, procs) {
if (possibly_ignore_set != 0 && possibly_ignore[i]) {
continue;
}
Entity *proc = procs[i];
TokenPos pos = proc->token.pos;
Type *t = base_type(proc->type);
if (t == t_invalid) continue;
GB_ASSERT(t->kind == Type_Proc);
if (t->Proc.params && t->Proc.params->Tuple.variables.count > 0) {
isize n = gb_min(t->Proc.params->Tuple.variables.count, positional_operands.count);
for (isize i = 0; i < n; i++) {
Type *dst = t->Proc.params->Tuple.variables[i]->type;
Operand src = positional_operands[i];
if (check_is_assignable_to(c, &src, dst)) {
// okay
} else if (check_is_assignable_to(c, &src, type_deref(dst))) {
try_addr = true;
if (try_addr_idx < 0) {
try_addr_idx = i;
}
}
}
}
}
if (try_addr) {
error_line(" \n");
error_line("\tSuggestion:\n");
error_line("\t\t%s(", expr_name);
isize i = 0;
for (Operand const &o : positional_operands) {
if (i++ > 0) error_line(", ");
gbString expr = expr_to_string(o.expr);
defer (gb_string_free(expr));
if (i-1 == try_addr_idx) {
error_line("&");
}
error_line("%s", expr);
}
for (Operand const &o : named_operands) {
if (i++ > 0) error_line(", ");
gbString expr = expr_to_string(o.expr);
defer (gb_string_free(expr));
if (i < ce->split_args->named.count) {
Ast *named_field = ce->split_args->named[i];
ast_node(fv, FieldValue, named_field);
gbString field = expr_to_string(fv->field);
defer (gb_string_free(field));
error_line("%s = %s", field, expr);
} else {
error_line("%s", expr);
}
}
error_line(")\n");
error_line(" \n"); // extra spaces to prevent newlines being consumed by the error handling syste,
}
}
if (procs.count > 0) {
error_line("Did you mean one of the following overloads?\n");
}
for_array(i, procs) {
if (possibly_ignore_set != 0 && possibly_ignore[i]) {
continue;