From 06a083bafc446b841cb3515aa19047fdfcd7a9d2 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sun, 15 Sep 2024 22:12:03 +0200 Subject: [PATCH] Lambda / function type would accidentally be processed as a method. --- releasenotes.md | 1 + src/compiler/sema_decls.c | 18 +++++++++--------- src/compiler/sema_expr.c | 2 +- src/compiler/sema_internal.h | 2 +- .../functions/accidental_method_1448.c3 | 11 +++++++++++ 5 files changed, 23 insertions(+), 11 deletions(-) create mode 100644 test/test_suite/functions/accidental_method_1448.c3 diff --git a/releasenotes.md b/releasenotes.md index 348da060f..d9eb8a630 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -27,6 +27,7 @@ - Use atexit to fix finalizers on Windows #1361. - Fix bugs in "trap-on-wrap" #1434. - Bug with casting anyfault to error. +- Lambda / function type would accidentally be processed as a method. ### Stdlib changes - Additional init functions for hashmap. diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 8c2d5869c..b23ef8003 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -11,7 +11,7 @@ static inline bool sema_analyse_func_macro(SemaContext *context, Decl *decl, AttributeDomain domain, bool *erase_decl); static inline bool sema_analyse_func(SemaContext *context, Decl *decl, bool *erase_decl); static inline bool sema_analyse_macro(SemaContext *context, Decl *decl, bool *erase_decl); -static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, TypeInfoId type_parent, bool is_export); +static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, TypeInfo *method_parent, bool is_export); static inline bool sema_analyse_main_function(SemaContext *context, Decl *decl); static inline bool sema_check_param_uniqueness_and_type(SemaContext *context, Decl **decls, Decl *current, unsigned current_index, unsigned count); @@ -1084,7 +1084,7 @@ ERROR: return decl_poison(decl); } -static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, TypeInfoId type_parent, bool is_export) +static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, TypeInfo *method_parent, bool is_export) { Variadic variadic_type = sig->variadic; Decl **params = sig->params; @@ -1133,7 +1133,6 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, "consider using varargs.", MAX_PARAMS); } - TypeInfo *method_parent = type_infoptrzero(type_parent); if (method_parent) { if (!sema_resolve_type_info(context, method_parent, @@ -1233,7 +1232,7 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, SEMA_ERROR(param, "Only regular parameters are allowed for functions."); return decl_poison(param); } - if (!is_macro_at_name && (!type_parent || i != 0 || var_kind != VARDECL_PARAM_REF)) + if (!is_macro_at_name && (!method_parent || i != 0 || var_kind != VARDECL_PARAM_REF)) { SEMA_ERROR(param, "Ref and expression parameters are not allowed in function-like macros. Prefix the macro name with '@'."); return decl_poison(param); @@ -1324,12 +1323,12 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, return true; } -bool sema_analyse_function_signature(SemaContext *context, Decl *func_decl, CallABI abi, Signature *signature) +bool sema_analyse_function_signature(SemaContext *context, Decl *func_decl, TypeInfo *parent, CallABI abi, Signature *signature) { // Get param count and variadic type Decl **params = signature->params; - if (!sema_analyse_signature(context, signature, func_decl->func_decl.type_parent, func_decl->is_export)) return false; + if (!sema_analyse_signature(context, signature, parent, func_decl->is_export)) return false; Variadic variadic_type = signature->variadic; @@ -1363,7 +1362,7 @@ static inline bool sema_analyse_fntype(SemaContext *context, Decl *decl, bool *e if (!sema_analyse_attributes(context, decl, decl->attributes, ATTR_DEF, erase_decl)) return decl_poison(decl); if (*erase_decl) return true; Signature *sig = &decl->fntype_decl; - return sema_analyse_function_signature(context, decl, sig->abi, sig); + return sema_analyse_function_signature(context, decl, NULL, sig->abi, sig); } static inline bool sema_analyse_typedef(SemaContext *context, Decl *decl, bool *erase_decl) @@ -3325,7 +3324,7 @@ static inline bool sema_analyse_func(SemaContext *context, Decl *decl, bool *era } decl->type = type_new_func(decl, sig); - if (!sema_analyse_function_signature(context, decl, sig->abi, sig)) return decl_poison(decl); + if (!sema_analyse_function_signature(context, decl, type_infoptrzero(decl->func_decl.type_parent), sig->abi, sig)) return decl_poison(decl); TypeInfo *rtype_info = type_infoptr(sig->rtype); assert(rtype_info); Type *rtype = rtype_info->type->canonical; @@ -3493,7 +3492,8 @@ static inline bool sema_analyse_macro(SemaContext *context, Decl *decl, bool *er if (!sema_analyse_func_macro(context, decl, ATTR_MACRO, erase_decl)) return false; if (*erase_decl) return true; - if (!sema_analyse_signature(context, &decl->func_decl.signature, decl->func_decl.type_parent, + if (!sema_analyse_signature(context, &decl->func_decl.signature, + type_infoptrzero(decl->func_decl.type_parent), false)) return false; if (!decl->func_decl.signature.is_at_macro && decl->func_decl.body_param && !decl->func_decl.signature.is_safemacro) diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index d90568a9c..9a03242a8 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -8299,7 +8299,7 @@ static inline bool sema_expr_analyse_lambda(SemaContext *context, Type *target_t decl->name = scratch_buffer_copy(); decl->extname = decl->name; decl->type = type_new_func(decl, sig); - if (!sema_analyse_function_signature(context, decl, sig->abi, sig)) return false; + if (!sema_analyse_function_signature(context, decl, NULL, sig->abi, sig)) return false; if (flat && 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.", diff --git a/src/compiler/sema_internal.h b/src/compiler/sema_internal.h index 6ab39cace..2d984564b 100644 --- a/src/compiler/sema_internal.h +++ b/src/compiler/sema_internal.h @@ -106,7 +106,7 @@ bool sema_analyse_asm(SemaContext *context, AsmInlineBlock *block, Ast *asm_stmt bool sema_bit_assignment_check(SemaContext *context, Expr *right, Decl *member); CondResult sema_check_comp_time_bool(SemaContext *context, Expr *expr); bool sema_expr_check_assign(SemaContext *context, Expr *expr); -bool sema_analyse_function_signature(SemaContext *context, Decl *func_decl, CallABI abi, Signature *signature); +bool sema_analyse_function_signature(SemaContext *context, Decl *func_decl, TypeInfo *parent, CallABI abi, Signature *signature); ConstInitializer *sema_merge_bitstruct_const_initializers(ConstInitializer *lhs, ConstInitializer *rhs, BinaryOp op); void sema_invert_bitstruct_const_initializer(ConstInitializer *initializer); ArrayIndex sema_len_from_const(Expr *expr); diff --git a/test/test_suite/functions/accidental_method_1448.c3 b/test/test_suite/functions/accidental_method_1448.c3 new file mode 100644 index 000000000..8afbcd726 --- /dev/null +++ b/test/test_suite/functions/accidental_method_1448.c3 @@ -0,0 +1,11 @@ +import std; +def MaybeInt = maybe::Maybe(); + +def Func = fn void (args...); + +fn int main() { + Func t; + MaybeInt m = maybe::EMPTY(); + io::printfn("%s %s", m.value, m.has_value); + return 0; +} \ No newline at end of file