aboutsummaryrefslogtreecommitdiff
path: root/src/check_expr.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2024-05-22 21:52:15 +0100
committergingerBill <bill@gingerbill.org>2024-05-22 21:52:15 +0100
commit2f35ee9671cf52b980d37fd8b1f18c8faccd951a (patch)
tree6d2e6c480c65e4fc1de23d876c1286dbecf2e808 /src/check_expr.cpp
parent856537f0ce11bd0e966fc6647b949fc99373ef29 (diff)
Improve errors a lot for assigning procedures of the wrong signature
Diffstat (limited to 'src/check_expr.cpp')
-rw-r--r--src/check_expr.cpp49
1 files changed, 47 insertions, 2 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 013f146f6..a0e6b33df 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -1179,15 +1179,60 @@ gb_internal void check_assignment(CheckerContext *c, Operand *operand, Type *typ
LIT(context_name));
check_assignment_error_suggestion(c, operand, type);
+ Type *src = base_type(operand->type);
+ Type *dst = base_type(type);
if (context_name == "procedure argument") {
- Type *src = base_type(operand->type);
- Type *dst = base_type(type);
if (is_type_slice(src) && are_types_identical(src->Slice.elem, dst)) {
gbString a = expr_to_string(operand->expr);
error_line("\tSuggestion: Did you mean to pass the slice into the variadic parameter with ..%s?\n\n", a);
gb_string_free(a);
}
}
+ if (src->kind == dst->kind && src->kind == Type_Proc) {
+ Type *x = src;
+ Type *y = dst;
+ bool same_inputs = are_types_identical_internal(x->Proc.params, y->Proc.params, false);
+ bool same_outputs = are_types_identical_internal(x->Proc.results, y->Proc.results, false);
+ if (same_inputs && same_outputs) {
+ if (x->Proc.calling_convention != y->Proc.calling_convention) {
+ gbString s_expected = type_to_string(y);
+ gbString s_got = type_to_string(x);
+
+ error_line("\tNote: The calling conventions differ between the procedure signature types\n");
+ error_line("\t Expected \"%s\", got \"%s\"\n",
+ proc_calling_convention_strings[y->Proc.calling_convention],
+ proc_calling_convention_strings[x->Proc.calling_convention]);
+ error_line("\t Expected: %s\n", s_expected);
+ error_line("\t Got: %s\n", s_got);
+ gb_string_free(s_got);
+ gb_string_free(s_expected);
+ }
+ } else if (same_inputs) {
+ gbString s_expected = type_to_string(y->Proc.results);
+ gbString s_got = type_to_string(x->Proc.results);
+ error_line("\tNote: The return types differ between the procedure signature types\n");
+ error_line("\t Expected: %s\n", s_expected);
+ error_line("\t Got: %s\n", s_got);
+ gb_string_free(s_got);
+ gb_string_free(s_expected);
+ } else if (same_outputs) {
+ gbString s_expected = type_to_string(y->Proc.params);
+ gbString s_got = type_to_string(x->Proc.params);
+ error_line("\tNote: The input parameter types differ between the procedure signature types\n");
+ error_line("\t Expected: %s\n", s_expected);
+ error_line("\t Got: %s\n", s_got);
+ gb_string_free(s_got);
+ gb_string_free(s_expected);
+ } else {
+ gbString s_expected = type_to_string(y);
+ gbString s_got = type_to_string(x);
+ error_line("\tNote: The signature type do not match whatsoever\n");
+ error_line("\t Expected: %s\n", s_expected);
+ error_line("\t Got: %s\n", s_got);
+ gb_string_free(s_got);
+ gb_string_free(s_expected);
+ }
+ }
}
break;
}