diff --git a/releasenotes.md b/releasenotes.md index dbfdf0529..cab6917dd 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -24,6 +24,7 @@ - Fixed issue in safe mode when converting enums. - Better checking of operator methods. - Bug when assigning an optional from an optional. +- Lambdas were not type checked thoroughly #1185. ### Stdlib changes - "init_new/init_temp" removed. diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 8f811b194..865905023 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -7691,8 +7691,7 @@ static inline bool sema_expr_analyse_lambda(SemaContext *context, Type *target_t } if (to_sig && vec_size(to_sig->params) != vec_size(sig->params)) { - SEMA_ERROR(expr, "The lambda doesn't match the required type %s.", type_quoted_error_string(target_type)); - return false; + RETURN_SEMA_ERROR(expr, "The lambda doesn't match the required type %s.", type_quoted_error_string(target_type)); } FOREACH_BEGIN_IDX(i, Decl *param, sig->params) if (param->var.type_info) continue; @@ -7730,6 +7729,12 @@ static inline bool sema_expr_analyse_lambda(SemaContext *context, Type *target_t decl->extname = decl->name = scratch_buffer_copy(); decl->type = type_new_func(decl, sig); if (!sema_analyse_function_signature(context, decl, sig->abi, sig)) return false; + if (target_type && flat->pointer->function.prototype->raw_type != decl->type->function.prototype->raw_type) + { + RETURN_SEMA_ERROR(expr, "The lambda has type %s, which doesn't match the required type %s.", + type_quoted_error_string(decl->type), + type_quoted_error_string(target_type)); + } decl->func_decl.lambda_ct_parameters = ct_lambda_parameters; decl->func_decl.is_lambda = true; decl->alignment = type_alloca_alignment(decl->type); diff --git a/test/test_suite/lambda/lambda_checks.c3 b/test/test_suite/lambda/lambda_checks.c3 new file mode 100644 index 000000000..a441e944c --- /dev/null +++ b/test/test_suite/lambda/lambda_checks.c3 @@ -0,0 +1,14 @@ +module test; +def Func = fn void (bool); + +fn bool foo (String) => true; +fn void bar(Func func) => func(false); + +fn void main() +{ + Func funcX = &foo; // #error: Implicitly casting + bar(&foo); // #error: Implicitly casting + + Func func = fn bool (String) { return true; }; // #error: which doesn't match + bar(fn bool (String) { return true; }); // #error: which doesn't match +} \ No newline at end of file