From 65b4c793f011ab67ad51773273ebc4333c12bff5 Mon Sep 17 00:00:00 2001 From: Lucas Perlind Date: Sun, 27 Apr 2025 22:47:03 +1000 Subject: [PATCH 1/2] Add -vet-explicit-allocators This vet flag will make it so that allocators must be explicitly used in places where context.allocator and context.temp_allocator are a procedure parameter. The goal of this flag is to prevent using the context.allocator in cases where a different allocator was meant to be used. Some code bases default context.allocator to nil/panic allocator to catch this at runtime. This effectively makes it a compile time error instead. --- src/build_settings.cpp | 3 +++ src/check_expr.cpp | 37 ++++++++++++++++++++++++++++++------- src/main.cpp | 26 ++++++++++++++++---------- src/parser.cpp | 5 +++++ 4 files changed, 54 insertions(+), 17 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index c941e0f68..c2d244440 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -305,6 +305,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, @@ -338,6 +339,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 91d9e669f..6daa3edf8 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -6253,20 +6253,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/main.cpp b/src/main.cpp index b2cfbe018..1b02d78f6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -346,6 +346,7 @@ enum BuildFlagKind { BuildFlag_VetCast, BuildFlag_VetTabs, BuildFlag_VetPackages, + BuildFlag_VetExplicitAllocators, BuildFlag_CustomAttribute, BuildFlag_IgnoreUnknownAttributes, @@ -565,6 +566,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_VetCast, str_lit("vet-cast"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_VetTabs, str_lit("vet-tabs"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_VetPackages, str_lit("vet-packages"), BuildFlagParam_String, Command__does_check); + add_flag(&build_flags, BuildFlag_VetExplicitAllocators, str_lit("vet-explicit-allocators"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_CustomAttribute, str_lit("custom-attribute"), BuildFlagParam_String, Command__does_check, true); add_flag(&build_flags, BuildFlag_IgnoreUnknownAttributes, str_lit("ignore-unknown-attributes"), BuildFlagParam_None, Command__does_check); @@ -1276,16 +1278,17 @@ gb_internal bool parse_build_flags(Array args) { build_context.vet_flags |= VetFlag_All; break; - case BuildFlag_VetUnusedVariables: build_context.vet_flags |= VetFlag_UnusedVariables; break; - case BuildFlag_VetUnusedImports: build_context.vet_flags |= VetFlag_UnusedImports; break; - case BuildFlag_VetUnused: build_context.vet_flags |= VetFlag_Unused; break; - case BuildFlag_VetShadowing: build_context.vet_flags |= VetFlag_Shadowing; break; - case BuildFlag_VetUsingStmt: build_context.vet_flags |= VetFlag_UsingStmt; break; - case BuildFlag_VetUsingParam: build_context.vet_flags |= VetFlag_UsingParam; break; - case BuildFlag_VetStyle: build_context.vet_flags |= VetFlag_Style; break; - case BuildFlag_VetSemicolon: build_context.vet_flags |= VetFlag_Semicolon; break; - case BuildFlag_VetCast: build_context.vet_flags |= VetFlag_Cast; break; - case BuildFlag_VetTabs: build_context.vet_flags |= VetFlag_Tabs; break; + case BuildFlag_VetUnusedVariables: build_context.vet_flags |= VetFlag_UnusedVariables; break; + case BuildFlag_VetUnusedImports: build_context.vet_flags |= VetFlag_UnusedImports; break; + case BuildFlag_VetUnused: build_context.vet_flags |= VetFlag_Unused; break; + case BuildFlag_VetShadowing: build_context.vet_flags |= VetFlag_Shadowing; break; + case BuildFlag_VetUsingStmt: build_context.vet_flags |= VetFlag_UsingStmt; break; + case BuildFlag_VetUsingParam: build_context.vet_flags |= VetFlag_UsingParam; break; + case BuildFlag_VetStyle: build_context.vet_flags |= VetFlag_Style; break; + case BuildFlag_VetSemicolon: build_context.vet_flags |= VetFlag_Semicolon; break; + case BuildFlag_VetCast: build_context.vet_flags |= VetFlag_Cast; break; + case BuildFlag_VetTabs: build_context.vet_flags |= VetFlag_Tabs; break; + case BuildFlag_VetExplicitAllocators: build_context.vet_flags |= VetFlag_ExplicitAllocators; break; case BuildFlag_VetUnusedProcedures: build_context.vet_flags |= VetFlag_UnusedProcedures; if (!set_flags[BuildFlag_VetPackages]) { @@ -2841,6 +2844,9 @@ gb_internal void print_show_help(String const arg0, String command, String optio print_usage_line(2, "Checks for the use of 'using' as a statement."); print_usage_line(2, "'using' is considered bad practice outside of immediate refactoring."); } + if (print_flag("-vet-explicit-allocators")) { + print_usage_line(2, "Checks for the use of allocators being explicitely passed to a procedure."); + } } if (check) { diff --git a/src/parser.cpp b/src/parser.cpp index a397585e8..ea95dac31 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; @@ -6325,6 +6329,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; } } From 51d427f424b7ffbf44bb9aa1e9086e2984b419f0 Mon Sep 17 00:00:00 2001 From: Lucas Perlind Date: Mon, 28 Apr 2025 19:30:35 +1000 Subject: [PATCH 2/2] Remove vet explicit allocators from cli --- src/main.cpp | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 1b02d78f6..b2cfbe018 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -346,7 +346,6 @@ enum BuildFlagKind { BuildFlag_VetCast, BuildFlag_VetTabs, BuildFlag_VetPackages, - BuildFlag_VetExplicitAllocators, BuildFlag_CustomAttribute, BuildFlag_IgnoreUnknownAttributes, @@ -566,7 +565,6 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_VetCast, str_lit("vet-cast"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_VetTabs, str_lit("vet-tabs"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_VetPackages, str_lit("vet-packages"), BuildFlagParam_String, Command__does_check); - add_flag(&build_flags, BuildFlag_VetExplicitAllocators, str_lit("vet-explicit-allocators"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_CustomAttribute, str_lit("custom-attribute"), BuildFlagParam_String, Command__does_check, true); add_flag(&build_flags, BuildFlag_IgnoreUnknownAttributes, str_lit("ignore-unknown-attributes"), BuildFlagParam_None, Command__does_check); @@ -1278,17 +1276,16 @@ gb_internal bool parse_build_flags(Array args) { build_context.vet_flags |= VetFlag_All; break; - case BuildFlag_VetUnusedVariables: build_context.vet_flags |= VetFlag_UnusedVariables; break; - case BuildFlag_VetUnusedImports: build_context.vet_flags |= VetFlag_UnusedImports; break; - case BuildFlag_VetUnused: build_context.vet_flags |= VetFlag_Unused; break; - case BuildFlag_VetShadowing: build_context.vet_flags |= VetFlag_Shadowing; break; - case BuildFlag_VetUsingStmt: build_context.vet_flags |= VetFlag_UsingStmt; break; - case BuildFlag_VetUsingParam: build_context.vet_flags |= VetFlag_UsingParam; break; - case BuildFlag_VetStyle: build_context.vet_flags |= VetFlag_Style; break; - case BuildFlag_VetSemicolon: build_context.vet_flags |= VetFlag_Semicolon; break; - case BuildFlag_VetCast: build_context.vet_flags |= VetFlag_Cast; break; - case BuildFlag_VetTabs: build_context.vet_flags |= VetFlag_Tabs; break; - case BuildFlag_VetExplicitAllocators: build_context.vet_flags |= VetFlag_ExplicitAllocators; break; + case BuildFlag_VetUnusedVariables: build_context.vet_flags |= VetFlag_UnusedVariables; break; + case BuildFlag_VetUnusedImports: build_context.vet_flags |= VetFlag_UnusedImports; break; + case BuildFlag_VetUnused: build_context.vet_flags |= VetFlag_Unused; break; + case BuildFlag_VetShadowing: build_context.vet_flags |= VetFlag_Shadowing; break; + case BuildFlag_VetUsingStmt: build_context.vet_flags |= VetFlag_UsingStmt; break; + case BuildFlag_VetUsingParam: build_context.vet_flags |= VetFlag_UsingParam; break; + case BuildFlag_VetStyle: build_context.vet_flags |= VetFlag_Style; break; + case BuildFlag_VetSemicolon: build_context.vet_flags |= VetFlag_Semicolon; break; + case BuildFlag_VetCast: build_context.vet_flags |= VetFlag_Cast; break; + case BuildFlag_VetTabs: build_context.vet_flags |= VetFlag_Tabs; break; case BuildFlag_VetUnusedProcedures: build_context.vet_flags |= VetFlag_UnusedProcedures; if (!set_flags[BuildFlag_VetPackages]) { @@ -2844,9 +2841,6 @@ gb_internal void print_show_help(String const arg0, String command, String optio print_usage_line(2, "Checks for the use of 'using' as a statement."); print_usage_line(2, "'using' is considered bad practice outside of immediate refactoring."); } - if (print_flag("-vet-explicit-allocators")) { - print_usage_line(2, "Checks for the use of allocators being explicitely passed to a procedure."); - } } if (check) {