diff --git a/releasenotes.md b/releasenotes.md index c06363dd9..dba3e8d8f 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -100,6 +100,7 @@ - `int? ?` was not correctly handled. #2786 - Casting const bytes to vector with different element size was broken #2787 - Unable to access fields of a const inline enum with an aggregate underlying type. #2802 +- Using an optional type as generic parameter was not properly caught #2799 ### Stdlib changes - Add `ThreadPool` join function to wait for all threads to finish in the pool without destroying the threads. diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 7cb943950..b3b7d1c72 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -5438,6 +5438,10 @@ Decl *sema_analyse_parameterized_identifier(SemaContext *context, Path *decl_pat return poisoned_decl; } Type *type = param->const_expr.typeid; + if (type_is_optional(type)) + { + RETURN_VAL_SEMA_ERROR(poisoned_decl, param, "The generic type can never be an optional, please use only non-optional types."); + } if (type_is_func_ptr(type)) { if (!sema_resolve_type_decl(context, type->pointer)) return poisoned_decl; @@ -5447,18 +5451,20 @@ Decl *sema_analyse_parameterized_identifier(SemaContext *context, Path *decl_pat { if (is_type) { - SEMA_ERROR(param, "Expected a type, not a value, for parameter '%s'.", param_name); - return poisoned_decl; + RETURN_VAL_SEMA_ERROR(poisoned_decl, param, "Expected a type, not a value, for parameter '%s'.", param_name); } if (!sema_analyse_ct_expr(context, param)) return poisoned_decl; Type *type = param->type->canonical; if (type->type_kind == TYPE_TYPEDEF) type = type_flatten(type); + if (IS_OPTIONAL(param)) + { + RETURN_VAL_SEMA_ERROR(poisoned_decl, param, "The parameter may never be an optional value."); + } bool is_enum_or_fault = type_kind_is_enum_or_fault(type->type_kind); if (!type_is_integer_or_bool_kind(type) && !is_enum_or_fault) { - SEMA_ERROR(param, "Only integer, bool, fault and enum values may be generic arguments."); - return poisoned_decl; + RETURN_VAL_SEMA_ERROR(poisoned_decl, param, "Only integer, bool, fault and enum values may be generic arguments."); } ASSERT(expr_is_const(param)); } diff --git a/test/test_suite/generic/generic_param_opt.c3 b/test/test_suite/generic/generic_param_opt.c3 new file mode 100644 index 000000000..f38ff5ee2 --- /dev/null +++ b/test/test_suite/generic/generic_param_opt.c3 @@ -0,0 +1,8 @@ +import std; + +alias Aa = List{Path?}; // #error: The generic type can never be an optional, please use only non-optional types + +fn int main() +{ + return 0; +} \ No newline at end of file