From 328e6f518cafafdcdf93b2b201dcb830f3e82607 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Mon, 29 Dec 2025 19:34:45 +0100 Subject: [PATCH] Fix bug when encountering Type{} where Type is a generic parameter. --- src/compiler/sema_name_resolution.c | 33 ++++++++++--------- .../generic/generic_default_wrong_init.c3 | 8 +++++ 2 files changed, 26 insertions(+), 15 deletions(-) create mode 100644 test/test_suite/generic/generic_default_wrong_init.c3 diff --git a/src/compiler/sema_name_resolution.c b/src/compiler/sema_name_resolution.c index 1ef5c2415..0d018bc43 100644 --- a/src/compiler/sema_name_resolution.c +++ b/src/compiler/sema_name_resolution.c @@ -790,6 +790,7 @@ INLINE bool sema_resolve_symbol_common(SemaContext *context, NameResolve *name_r name_resolve->ambiguous_other_decl = NULL; name_resolve->private_decl = NULL; name_resolve->path_found = NULL; + Decl *found = NULL; if (name_resolve->path) { if (!sema_resolve_path_symbol(context, name_resolve)) return false; @@ -811,13 +812,18 @@ INLINE bool sema_resolve_symbol_common(SemaContext *context, NameResolve *name_r { FOREACH(Decl *, param, context->generic_instance->instance_decl.params) { - if (param->name == name_resolve->symbol) return name_resolve->found = param, true; + if (param->name == name_resolve->symbol) + { + found = name_resolve->found = param; + if (name_resolve->is_parameterized) goto NOT_GENERIC; + return true; + } } } if (!sema_resolve_no_path_symbol(context, name_resolve)) return false; } - Decl *found = name_resolve->found; + found = name_resolve->found; if (!found || name_resolve->ambiguous_other_decl) { if (name_resolve->suppress_error) return name_resolve->found = NULL, true; @@ -857,21 +863,18 @@ INLINE bool sema_resolve_symbol_common(SemaContext *context, NameResolve *name_r if (name_resolve->suppress_error) return name_resolve->found = NULL, true; RETURN_SEMA_ERROR_AT(name_resolve->span, "'%s' is a generic %s, did you forget the parameters '{ ... }'?", found->name, decl_to_name(found)); } - else + if (!name_resolve->is_parameterized) return true; + if (name_resolve->suppress_error) return name_resolve->found = NULL, true; +NOT_GENERIC:; + if (decl_is_user_defined_type(found) + || (found->decl_kind == DECL_VAR && (found->var.kind == VARDECL_PARAM_CT_TYPE || found->var.kind == VARDECL_LOCAL_CT_TYPE))) { - if (!name_resolve->is_parameterized) return true; - if (name_resolve->suppress_error) return name_resolve->found = NULL, true; - bool is_type = decl_is_user_defined_type(name_resolve->found); - const char *str = is_type ? "type" : "symbol"; - if (is_type) - { - RETURN_SEMA_ERROR_AT(name_resolve->span, "'%s' is not a generic type. Did you want an initializer " - "but forgot () around the type? That is, you typed '%s { ... }' but intended '(%s) { ... }'?", - name_resolve->symbol, name_resolve->symbol, name_resolve->symbol); - } - RETURN_SEMA_ERROR_AT(name_resolve->span, "Found '%s' in module '%s', but it is not a generic %s.", found->name, found->unit->module->name->module, str); + RETURN_SEMA_ERROR_AT(name_resolve->span, "'%s' is not a generic type. Did you want an initializer " + "but forgot () around the type? That is, you typed '%s { ... }' but intended '(%s) { ... }'?", + name_resolve->symbol, name_resolve->symbol, name_resolve->symbol); } - return true; + RETURN_SEMA_ERROR_AT(name_resolve->span, "Found '%s', but it is not generic so the { ... } after looks like a mistake?", found->name); + } Decl *sema_find_extension_method_in_list(Decl **extensions, Type *type, const char *method_name) diff --git a/test/test_suite/generic/generic_default_wrong_init.c3 b/test/test_suite/generic/generic_default_wrong_init.c3 new file mode 100644 index 000000000..c15dce51f --- /dev/null +++ b/test/test_suite/generic/generic_default_wrong_init.c3 @@ -0,0 +1,8 @@ +fn Type test_val(Type val = Type{}) @generic(Type) => val; // #error: 'Type' is not a generic type. Did you want an initializer but forgot () around the type? That is, you typed 'Type { ... }' but intended '(Type) { ... }' + +fn int main() +{ + int x = test_val{int}(1); + int y = test_val{int}(); + return 0; +} \ No newline at end of file