aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-08-21 13:09:23 +0100
committergingerBill <bill@gingerbill.org>2021-08-21 13:09:23 +0100
commit2aaf927bebba52d13eaa5e14ead8556c62210d16 (patch)
tree5ebc606bc8b4ecf7db25d333b0ed305c028debf1 /src
parent2f5edebefa75381283d75adcc4260277a3945524 (diff)
Improve error message for `Cannot assign value` if they have the same name but are from different packages
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.cpp67
1 files changed, 61 insertions, 6 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 9e6a47a4e..7c46ef4ca 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -707,6 +707,42 @@ bool check_is_assignable_to(CheckerContext *c, Operand *operand, Type *type) {
return check_is_assignable_to_with_score(c, operand, type, &score);
}
+AstPackage *get_package_of_type(Type *type) {
+ for (;;) {
+ if (type == nullptr) {
+ return nullptr;
+ }
+ switch (type->kind) {
+ case Type_Basic:
+ return builtin_pkg;
+ case Type_Named:
+ if (type->Named.type_name != nullptr) {
+ return type->Named.type_name->pkg;
+ }
+ return nullptr;
+ case Type_Pointer:
+ type = type->Pointer.elem;
+ continue;
+ case Type_Array:
+ type = type->Array.elem;
+ continue;
+ case Type_Slice:
+ type = type->Slice.elem;
+ continue;
+ case Type_DynamicArray:
+ type = type->DynamicArray.elem;
+ continue;
+ case Type_RelativePointer:
+ type = type->RelativePointer.pointer_type;
+ continue;
+ case Type_RelativeSlice:
+ type = type->RelativeSlice.slice_type;
+ continue;
+ }
+ return nullptr;
+ }
+}
+
// NOTE(bill): 'content_name' is for debugging and error messages
void check_assignment(CheckerContext *c, Operand *operand, Type *type, String context_name) {
@@ -819,13 +855,32 @@ void check_assignment(CheckerContext *c, Operand *operand, Type *type, String co
break;
default:
// TODO(bill): is this a good enough error message?
- error(operand->expr,
- "Cannot assign value '%s' of type '%s' to '%s' in %.*s",
- expr_str,
- op_type_str,
- type_str,
- LIT(context_name));
+ {
+ gbString op_type_extra = gb_string_make(heap_allocator(), "");
+ gbString type_extra = gb_string_make(heap_allocator(), "");
+ defer (gb_string_free(op_type_extra));
+ defer (gb_string_free(type_extra));
+
+ isize on = gb_string_length(op_type_str);
+ isize tn = gb_string_length(type_str);
+ if (on == tn && gb_strncmp(op_type_str, type_str, on) == 0) {
+ AstPackage *op_pkg = get_package_of_type(operand->type);
+ AstPackage *type_pkg = get_package_of_type(type);
+ if (op_pkg != nullptr) {
+ op_type_extra = gb_string_append_fmt(op_type_extra, " (package %.*s)", LIT(op_pkg->name));
+ }
+ if (type_pkg != nullptr) {
+ type_extra = gb_string_append_fmt(type_extra, " (package %.*s)", LIT(type_pkg->name));
+ }
+ }
+ error(operand->expr,
+ "Cannot assign value '%s' of type '%s%s' to '%s%s' in %.*s",
+ expr_str,
+ op_type_str, op_type_extra,
+ type_str, type_extra,
+ LIT(context_name));
check_assignment_error_suggestion(c, operand, type);
+ }
break;
}
operand->mode = Addressing_Invalid;