diff --git a/releasenotes.md b/releasenotes.md index b55549085..4768ada0d 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -4,6 +4,7 @@ ### Changes / improvements - Method resolution and `$define` now works together well unless definitions are out of order for real. +- Improve error message when using functions as values #2856 ### Stdlib changes - Summarize sort macros as generic function wrappers to reduce the amount of generated code. #2831 diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index c880af723..0842bfd06 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -65,7 +65,8 @@ void compiler_init(BuildOptions *build_options) INFO_LOG("Version: %s", COMPILER_VERSION); - compiler.context = (GlobalContext) { .in_panic_mode = false }; + GlobalContext new_context = { .in_panic_mode = false }; + compiler.context = new_context; // Skip library detection. //compiler.lib_dir = find_lib_dir(); //DEBUG_LOG("Found std library: %s", compiler.lib_dir); diff --git a/src/compiler/expr.c b/src/compiler/expr.c index 07e13b8a8..000355f18 100644 --- a/src/compiler/expr.c +++ b/src/compiler/expr.c @@ -592,7 +592,7 @@ void expr_insert_addr(Expr *original) Expr *inner = expr_copy(original); original->expr_kind = EXPR_UNARY; original->type = new_type; - original->unary_expr = (ExprUnary) { .operator = UNARYOP_ADDR, .expr = inner }; + original->unary_expr = (ExprUnary) { .operator = UNARYOP_ADDR, .expr = inner, .no_wrap = false, .no_read = false }; } Expr *expr_generated_local(Expr *assign, Decl **decl_ref) @@ -1189,6 +1189,6 @@ void expr_rewrite_const_string(Expr *expr_to_rewrite, const char *string) void expr_rewrite_to_binary(Expr *expr_to_rewrite, Expr *left, Expr *right, BinaryOp op) { - expr_to_rewrite->binary_expr = (ExprBinary) { .operator = op, .left = exprid(left), .right = exprid(right) }; + expr_to_rewrite->binary_expr = (ExprBinary) { .operator = op, .left = exprid(left), .right = exprid(right), .grouped = false }; expr_to_rewrite->expr_kind = EXPR_BINARY; } diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index e6e4de328..543c2ce37 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -3691,7 +3691,8 @@ static inline bool sema_analyse_custom_attribute(SemaContext *context, ResolvedA SemaContext eval_context; sema_context_init(&eval_context, attr_decl->unit); eval_context.macro_call_depth = context->macro_call_depth + 1; - eval_context.call_env = (CallEnv) { .kind = CALL_ENV_ATTR, .attr_declaration = decl, }; + CallEnv eval_env = { .kind = CALL_ENV_ATTR, .attr_declaration = decl, }; + eval_context.call_env = eval_env; // We copy the compilation unit. eval_context.compilation_unit = context->unit; @@ -5372,7 +5373,8 @@ FOUND:; { SemaContext context_gen; sema_context_init(&context_gen, decl->unit); - context_gen.active_scope = (DynamicScope) { .depth = 0 }; + DynamicScope empty = { .depth = 0 }; + context_gen.active_scope = empty; sema_analyse_decl(&context_gen, decl); context_gen.generic_instance = instance; sema_analyse_inner_func_ptr(&context_gen, decl); diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 5e4ef1e29..55d6a4240 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -953,9 +953,8 @@ static inline bool sema_cast_ident_rvalue(SemaContext *context, Expr *expr) decl = decl_flatten(decl); switch (decl->decl_kind) { - case DECL_FNTYPE: case DECL_FUNC: - SEMA_ERROR(expr, "Expected function followed by (...) or prefixed by &."); + SEMA_ERROR(expr, "A function name cannot be used as a value, did you want to pass it by pointer? If so then you need to add '&', like '&%s'.", decl->span); return expr_poison(expr); case DECL_MACRO: SEMA_ERROR(expr, "Expected a macro followed by (...)."); @@ -968,6 +967,7 @@ static inline bool sema_cast_ident_rvalue(SemaContext *context, Expr *expr) case DECL_FAULT: expr_rewrite_const_fault(expr, decl); return true; + case DECL_FNTYPE: case DECL_ALIAS: case DECL_ALIAS_PATH: case DECL_ATTRIBUTE: @@ -1647,7 +1647,8 @@ static bool sema_analyse_parameter(SemaContext *context, Expr *arg, Decl *param, { Expr *inner = expr_copy(arg); arg->expr_kind = EXPR_OTHER_CONTEXT; - arg->expr_other_context = (ExprOtherContext) { .context = context, .inner = inner }; + ExprOtherContext other = { .context = context, .inner = inner }; + arg->expr_other_context = other; arg->resolve_status = RESOLVE_NOT_DONE; } break; @@ -3599,8 +3600,9 @@ FOUND:; new_path->module = kw_std__core__runtime; new_path->span = expr->span; new_path->len = strlen(kw_std__core__runtime); - call->unresolved_ident_expr = (ExprUnresolvedIdentifier) { .ident = kw_at_enum_lookup, .path = new_path }; - expr->call_expr = (ExprCall) { .arguments = args, .function = exprid(call) }; + call->unresolved_ident_expr = (ExprUnresolvedIdentifier) { .ident = kw_at_enum_lookup, .path = new_path, .is_const = false }; + ExprCall call_expr = { .arguments = args, .function = exprid(call) }; + expr->call_expr = call_expr; expr->resolve_status = RESOLVE_NOT_DONE; return sema_analyse_expr_rvalue(context, expr); } @@ -7405,8 +7407,8 @@ AFTER_ADDR:; // init, expr -> lvalue = rvalue + a expr->expr_kind = EXPR_BINARY; left->expr_kind = EXPR_BINARY; - left->binary_expr = (ExprBinary) { .left = exprid(left_lvalue), .right = exprid(right), new_op }; - expr->binary_expr = (ExprBinary) { .left = exprid(left_rvalue), .right = exprid(left), .operator = BINARYOP_ASSIGN, .grouped = false }; + left->binary_expr = (ExprBinary) { exprid(left_lvalue), exprid(right), new_op, false }; + expr->binary_expr = (ExprBinary) { exprid(left_rvalue), exprid(left), BINARYOP_ASSIGN, false }; expr->resolve_status = RESOLVE_NOT_DONE; left->resolve_status = RESOLVE_NOT_DONE; Expr *binary = expr_copy(expr); diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index e799259e7..e0956e140 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -915,7 +915,7 @@ static inline bool sema_analyse_try_unwrap(SemaContext *context, Expr *expr) RETURN_SEMA_ERROR(ident, "Expected this variable to be an optional, otherwise it can't be used for unwrap, maybe you didn't intend to use 'try'?"); } expr->expr_kind = EXPR_TRY; - expr->try_expr = (ExprTry) { .decl = decl }; + expr->try_expr = (ExprTry) { .decl = decl, .assign_existing = false }; expr->type = type_bool; sema_unwrap_var(context, decl); expr->resolve_status = RESOLVE_DONE; @@ -977,7 +977,7 @@ static inline bool sema_analyse_try_unwrap(SemaContext *context, Expr *expr) if (!sema_analyse_var_decl(context, decl, true, NULL)) return false; expr->expr_kind = EXPR_TRY; - expr->try_expr = (ExprTry) { .decl = decl, .optional = optional }; + expr->try_expr = (ExprTry) { .decl = decl, .optional = optional, .assign_existing = false }; expr->type = type_bool; expr->resolve_status = RESOLVE_DONE; return true; @@ -3449,21 +3449,24 @@ bool sema_analyse_function_body(SemaContext *context, Decl *func) // Set up the context for analysis context->original_module = NULL; - context->call_env = (CallEnv) { + CallEnv env = { .current_function = func, .is_naked_fn = func->func_decl.attr_naked, .kind = CALL_ENV_FUNCTION, .pure = func->func_decl.signature.attrs.is_pure, .ignore_deprecation = func->allow_deprecated || decl_is_deprecated(func) }; + context->call_env = env; Type *rtype = context->rtype = typeget(signature->rtype); context->macro_call_depth = 0; - context->active_scope = (DynamicScope) { - .depth = 0, - .label_start = 0, - .current_local = 0 + DynamicScope new_scope = { + .depth = 0, + .label_start = 0, + .current_local = 0 }; + + context->active_scope = new_scope; vec_resize(context->ct_locals, 0); // Clear returns vec_resize(context->block_returns, 0); diff --git a/src/compiler/semantic_analyser.c b/src/compiler/semantic_analyser.c index 406e144e5..e132d3223 100644 --- a/src/compiler/semantic_analyser.c +++ b/src/compiler/semantic_analyser.c @@ -35,18 +35,19 @@ void context_change_scope_with_flags(SemaContext *context, ScopeFlags flags, Sou if (is_macro) flags &= ~(SCOPE_ENSURE | SCOPE_ENSURE_MACRO); unsigned label_start = new_label_scope ? last_local : context->active_scope.label_start; - context->active_scope = (DynamicScope) { - .allow_dead_code = false, - .is_dead = scope_is_dead, - .is_poisoned = scope_is_poisoned, - .depth = depth, - .current_local = last_local, - .label_start = label_start, - .in_defer = previous_defer, - .defer_last = parent_defer, - .defer_start = parent_defer, - .flags = flags, + DynamicScope new_scope = { + .allow_dead_code = false, + .is_dead = scope_is_dead, + .is_poisoned = scope_is_poisoned, + .depth = depth, + .current_local = last_local, + .label_start = label_start, + .in_defer = previous_defer, + .defer_last = parent_defer, + .defer_start = parent_defer, + .flags = flags, }; + context->active_scope = new_scope; } const char *context_filename(SemaContext *context) @@ -144,7 +145,7 @@ void context_pop_defers_and_replace_ast(SemaContext *context, Ast *ast) ASSERT(ast->ast_kind != AST_COMPOUND_STMT); Ast *replacement = ast_copy(ast); ast->ast_kind = AST_COMPOUND_STMT; - ast->compound_stmt = (AstCompoundStmt) { .first_stmt = astid(replacement) }; + ast->compound_stmt = (AstCompoundStmt) { .first_stmt = astid(replacement), .parent_defer = 0 }; replacement->next = defer_first; }