diff --git a/src/build_settings.cpp b/src/build_settings.cpp index ab501fe84..e1b9c4156 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -309,6 +309,7 @@ enum VetFlags : u64 { VetFlag_Cast = 1u<<8, VetFlag_Tabs = 1u<<9, VetFlag_UnusedProcedures = 1u<<10, + VetFlag_ExplicitAllocators = 1u<<11, VetFlag_Unused = VetFlag_UnusedVariables|VetFlag_UnusedImports, @@ -342,6 +343,8 @@ u64 get_vet_flag_from_name(String const &name) { return VetFlag_Tabs; } else if (name == "unused-procedures") { return VetFlag_UnusedProcedures; + } else if (name == "explicit-allocators") { + return VetFlag_ExplicitAllocators; } return VetFlag_NONE; } diff --git a/src/check_expr.cpp b/src/check_expr.cpp index aa9c8837d..b6fd85231 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -6245,20 +6245,43 @@ gb_internal CallArgumentError check_call_arguments_internal(CheckerContext *c, A for (isize i = 0; i < pt->param_count; i++) { if (!visited[i]) { Entity *e = pt->params->Tuple.variables[i]; + bool context_allocator_error = false; if (e->kind == Entity_Variable) { if (e->Variable.param_value.kind != ParameterValue_Invalid) { - ordered_operands[i].mode = Addressing_Value; - ordered_operands[i].type = e->type; - ordered_operands[i].expr = e->Variable.param_value.original_ast_expr; + if (ast_file_vet_explicit_allocators(c->file)) { + // NOTE(lucas): check if we are trying to default to context.allocator or context.temp_allocator + if (e->Variable.param_value.original_ast_expr->kind == Ast_SelectorExpr) { + auto& expr = e->Variable.param_value.original_ast_expr->SelectorExpr.expr; + auto& selector = e->Variable.param_value.original_ast_expr->SelectorExpr.selector; + if (expr->kind == Ast_Implicit && + expr->Implicit.string == STR_LIT("context") && + selector->kind == Ast_Ident && + (selector->Ident.token.string == STR_LIT("allocator") || + selector->Ident.token.string == STR_LIT("temp_allocator"))) { + context_allocator_error = true; + } + } + } - dummy_argument_count += 1; - score += assign_score_function(1); - continue; + if (!context_allocator_error) { + ordered_operands[i].mode = Addressing_Value; + ordered_operands[i].type = e->type; + ordered_operands[i].expr = e->Variable.param_value.original_ast_expr; + + dummy_argument_count += 1; + score += assign_score_function(1); + continue; + } } } if (show_error) { - if (e->kind == Entity_TypeName) { + if (context_allocator_error) { + gbString str = type_to_string(e->type); + error(call, "Parameter '%.*s' of type '%s' must be explicitly provided in procedure call", + LIT(e->token.string), str); + gb_string_free(str); + } else if (e->kind == Entity_TypeName) { error(call, "Type parameter '%.*s' is missing in procedure call", LIT(e->token.string)); } else if (e->kind == Entity_Constant && e->Constant.value.kind != ExactValue_Invalid) { diff --git a/src/parser.cpp b/src/parser.cpp index 7a2693e29..1ccc3feaa 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -33,6 +33,10 @@ gb_internal bool ast_file_vet_deprecated(AstFile *f) { return (ast_file_vet_flags(f) & VetFlag_Deprecated) != 0; } +gb_internal bool ast_file_vet_explicit_allocators(AstFile *f) { + return (ast_file_vet_flags(f) & VetFlag_ExplicitAllocators) != 0; +} + gb_internal bool file_allow_newline(AstFile *f) { bool is_strict = build_context.strict_style || ast_file_vet_style(f); return !is_strict; @@ -6356,6 +6360,7 @@ gb_internal u64 parse_vet_tag(Token token_for_pos, String s) { error_line("\textra\n"); error_line("\tcast\n"); error_line("\ttabs\n"); + error_line("\texplicit-allocators\n"); return build_context.vet_flags; } }