From abbedeec4feb9a8a4331fdcf4b060f27fd9590e8 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sat, 21 Sep 2024 15:55:39 +0200 Subject: [PATCH] Allow the "self" parameter to be $/# for macro methods. Fix bug when passing a type as a compile time value. --- releasenotes.md | 2 ++ src/compiler/sema_decls.c | 12 ++++++---- src/compiler/sema_expr.c | 24 ++++++++++++------- .../expressions/test_ct_param_bug.c3 | 7 ++++++ 4 files changed, 31 insertions(+), 14 deletions(-) create mode 100644 test/test_suite/expressions/test_ct_param_bug.c3 diff --git a/releasenotes.md b/releasenotes.md index 55d4f7e80..5bfd2717f 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -17,6 +17,7 @@ - Add `env::COMPILER_BUILD_HASH` and `env::COMPILER_BUILD_DATE` - Support linking .o files in compilation command. #1417 - Slicing constant strings at compile time works. +- Allow the "self" parameter to be $/# for macro methods. ### Fixes - Issue where a lambda wasn't correctly registered as external. #1408 @@ -48,6 +49,7 @@ - LLVM issue with try when bool is combined #1467. - Segfault using ternary with no assignment #1468. - Inner types make some errors misleading #1471. +- Fix bug when passing a type as a compile time value. ### Stdlib changes - Additional init functions for hashmap. diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 1b5efd091..fb8f6952d 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -1150,16 +1150,18 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, if (!is_macro) param->var.kind = VARDECL_PARAM; break; case VARDECL_PARAM: + case VARDECL_PARAM_EXPR: + case VARDECL_PARAM_CT: inferred_type = method_parent->type; break; + case VARDECL_PARAM_CT_TYPE: + RETURN_SEMA_ERROR(param, "Expected a parameter of type %s here.", method_parent->type); default: - goto CHECK_PARAMS; + UNREACHABLE } param->var.type_info = type_info_id_new_base(inferred_type, param->span); } - CHECK_PARAMS: - // Check parameters for (unsigned i = 0; i < param_count; i++) { @@ -3448,12 +3450,12 @@ static bool sema_analyse_macro_method(SemaContext *context, Decl *decl) Decl *first_param = decl->func_decl.signature.params[0]; if (!first_param) { - SEMA_ERROR(decl, "The first parameter to this method must be of type '%s'.", type_to_error_string(parent_type)); + RETURN_SEMA_ERROR(decl, "The first parameter to this method must be of type '%s'.", type_to_error_string(parent_type)); return false; } if (!sema_is_valid_method_param(context, first_param, parent_type->canonical, false)) return false; - if (first_param->var.kind != VARDECL_PARAM_CT && first_param->var.kind != VARDECL_PARAM_REF && first_param->var.kind != VARDECL_PARAM) + if (first_param->var.kind != VARDECL_PARAM_EXPR && first_param->var.kind != VARDECL_PARAM_CT && first_param->var.kind != VARDECL_PARAM_REF && first_param->var.kind != VARDECL_PARAM) { RETURN_SEMA_ERROR(first_param, "The first parameter must be a compile time, regular or ref (&) type."); } diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index aa5e33f82..69899a0aa 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -1231,7 +1231,8 @@ INLINE bool sema_arg_is_pass_through_ref(Expr *expr) return decl->var.kind == VARDECL_PARAM_REF; } -static bool sema_analyse_parameter(SemaContext *context, Expr *arg, Decl *param, Decl *definition, bool *optional_ref, bool *no_match_ref, bool macro) +static bool sema_analyse_parameter(SemaContext *context, Expr *arg, Decl *param, Decl *definition, bool *optional_ref, + bool *no_match_ref, bool macro, bool is_method_target) { VarDeclKind kind = param->var.kind; Type *type = param->type; @@ -1337,7 +1338,11 @@ static bool sema_analyse_parameter(SemaContext *context, Expr *arg, Decl *param, } if (!sema_cast_const(arg) && !expr_is_runtime_const(arg)) { - RETURN_SEMA_FUNC_ERROR(definition, arg, "A compile time parameter must always be a constant, did you mistake it for a normal paramter?"); + if (is_method_target) + { + RETURN_SEMA_FUNC_ERROR(definition, arg, "This method is only valid on a compile time constant value."); + } + RETURN_SEMA_FUNC_ERROR(definition, arg, "A compile time parameter must always be a constant, did you mistake it for a normal parameter?"); } break; case VARDECL_PARAM_CT_TYPE: @@ -1385,7 +1390,7 @@ INLINE bool sema_set_default_argument(SemaContext *context, CalledDecl *callee, : call->span.row; new_context->original_module = context->original_module; success = sema_analyse_parameter(new_context, arg, param, callee->definition, optional, no_match_ref, - callee->macro); + callee->macro, false); SCOPE_END; sema_context_destroy(&default_context); if (no_match_ref && *no_match_ref) return true; @@ -1403,7 +1408,7 @@ INLINE bool sema_set_default_argument(SemaContext *context, CalledDecl *callee, case VARDECL_PARAM_EXPR: *expr_ref = arg; return sema_analyse_parameter(context, arg, param, callee->definition, optional, no_match_ref, - callee->macro); + callee->macro, false); default: break; } @@ -1415,7 +1420,7 @@ INLINE bool sema_set_default_argument(SemaContext *context, CalledDecl *callee, function_scope_arg->default_arg_expr.loc = callee->call_location; *expr_ref = function_scope_arg; return sema_analyse_parameter(context, function_scope_arg, param, callee->definition, optional, no_match_ref, - callee->macro); + callee->macro, false); } @@ -1647,7 +1652,8 @@ SPLAT_NORMAL:; last_named_arg = arg; actual_args[index] = arg->named_argument_expr.value; - if (!sema_analyse_parameter(context, actual_args[index], param, callee->definition, optional, no_match_ref, callee->macro)) return false; + if (!sema_analyse_parameter(context, actual_args[index], param, callee->definition, optional, no_match_ref, + callee->macro, false)) return false; continue; } if (call->call_expr.va_is_splat) @@ -1714,7 +1720,7 @@ SPLAT_NORMAL:; vec_add(call->call_expr.varargs, arg); continue; } - if (!sema_analyse_parameter(context, arg, params[i], callee->definition, optional, no_match_ref, callee->macro)) return false; + if (!sema_analyse_parameter(context, arg, params[i], callee->definition, optional, no_match_ref, callee->macro, callee->struct_var && i == 0)) return false; actual_args[i] = arg; } if (num_args) last = args[num_args - 1]; @@ -2381,7 +2387,7 @@ static bool sema_call_analyse_body_expansion(SemaContext *macro_context, Expr *c { Decl *param = params[i]; Expr *expr = args[i]; - if (!sema_analyse_parameter(macro_context, expr, param, body_decl, &has_optional_arg, NULL, true)) + if (!sema_analyse_parameter(macro_context, expr, param, body_decl, &has_optional_arg, NULL, true, false)) { return false; } @@ -9131,6 +9137,7 @@ bool sema_analyse_expr_rhs(SemaContext *context, Type *to, Expr *expr, bool allo { if (!sema_analyse_inferred_expr(context, to, expr)) return false; } + if (!sema_cast_rvalue(context, expr)) return false; Type *to_canonical = to ? to->canonical : NULL; Type *rhs_type = expr->type; Type *rhs_type_canonical = rhs_type->canonical; @@ -9145,7 +9152,6 @@ bool sema_analyse_expr_rhs(SemaContext *context, Type *to, Expr *expr, bool allo } } // Let's see if we have a fixed slice. - if (to && type_is_arraylike(to_canonical) && expr->expr_kind == EXPR_SLICE && rhs_type_canonical->type_kind == TYPE_SLICE) { Type *element = type_get_indexed_type(rhs_type_canonical)->canonical; diff --git a/test/test_suite/expressions/test_ct_param_bug.c3 b/test/test_suite/expressions/test_ct_param_bug.c3 new file mode 100644 index 000000000..c8c19cf25 --- /dev/null +++ b/test/test_suite/expressions/test_ct_param_bug.c3 @@ -0,0 +1,7 @@ +module test; +macro @foo($aaa) {} +fn int main(String[] args) +{ + @foo(int); // #error: must be followed by either + return 0; +} \ No newline at end of file