aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2023-02-21 23:08:02 +0000
committergingerBill <bill@gingerbill.org>2023-02-21 23:08:02 +0000
commit59a601f2cf1f7575662e4e7f1c3cabd079280d0a (patch)
treeb0787582029308bb443948be13dc454ecdcd01d8 /src
parentb6a5c5f5d2a466e867f59c463987ba8ee28664a5 (diff)
Improve error messages when trying to access a non-existent field on a type
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.cpp37
1 files changed, 23 insertions, 14 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index c4a29b04a..30e2c9ad8 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -4745,20 +4745,29 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod
gbString op_str = expr_to_string(op_expr);
gbString type_str = type_to_string_shorthand(operand->type);
gbString sel_str = expr_to_string(selector);
- error(op_expr, "'%s' of type '%s' has no field '%s'", op_str, type_str, sel_str);
-
- if (operand->type != nullptr && selector->kind == Ast_Ident) {
- String const &name = selector->Ident.token.string;
- Type *bt = base_type(operand->type);
- if (operand->type->kind == Type_Named &&
- operand->type->Named.type_name &&
- operand->type->Named.type_name->kind == Entity_TypeName &&
- operand->type->Named.type_name->TypeName.objc_metadata) {
- check_did_you_mean_objc_entity(name, operand->type->Named.type_name, operand->mode == Addressing_Type);
- } else if (bt->kind == Type_Struct) {
- check_did_you_mean_type(name, bt->Struct.fields);
- } else if (bt->kind == Type_Enum) {
- check_did_you_mean_type(name, bt->Enum.fields);
+
+ if (operand->mode == Addressing_Type) {
+ if (is_type_polymorphic(operand->type, true)) {
+ error(op_expr, "Type '%s' has no field nor polymorphic parameter '%s'", op_str, sel_str);
+ } else {
+ error(op_expr, "Type '%s' has no field '%s'", op_str, sel_str);
+ }
+ } else {
+ error(op_expr, "'%s' of type '%s' has no field '%s'", op_str, type_str, sel_str);
+
+ if (operand->type != nullptr && selector->kind == Ast_Ident) {
+ String const &name = selector->Ident.token.string;
+ Type *bt = base_type(operand->type);
+ if (operand->type->kind == Type_Named &&
+ operand->type->Named.type_name &&
+ operand->type->Named.type_name->kind == Entity_TypeName &&
+ operand->type->Named.type_name->TypeName.objc_metadata) {
+ check_did_you_mean_objc_entity(name, operand->type->Named.type_name, operand->mode == Addressing_Type);
+ } else if (bt->kind == Type_Struct) {
+ check_did_you_mean_type(name, bt->Struct.fields);
+ } else if (bt->kind == Type_Enum) {
+ check_did_you_mean_type(name, bt->Enum.fields);
+ }
}
}