From 2aaf927bebba52d13eaa5e14ead8556c62210d16 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 21 Aug 2021 13:09:23 +0100 Subject: [PATCH] Improve error message for `Cannot assign value` if they have the same name but are from different packages --- src/check_expr.cpp | 67 +++++++++++++++++++++++++++++++++++++++++----- 1 file 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;