From dda89a69bf131ea4331b9c494a4afe4a420276bc Mon Sep 17 00:00:00 2001 From: Roland Kovacs Date: Wed, 7 Aug 2024 21:37:34 +0200 Subject: [PATCH] Check if procedure parameter type declares polymorphic args When a procedure parameter's type was declared in an imported package the type checker correctly resolved to the parametric type, but it did not check if the expression that refers to that type conforms to a polymorphic type declaration. This error was not detected if the procedure was unused, since it was marked as polymorphic, where further type check is done on instantiation. --- src/check_type.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/check_type.cpp b/src/check_type.cpp index 41de8ccce..5f456fb31 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -2309,8 +2309,28 @@ gb_internal Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_res return tuple; } +gb_internal void check_procedure_param_polymorphic_type(CheckerContext *ctx, Type *type, Ast *type_expr) { + GB_ASSERT_NOT_NULL(type_expr); + if (type == nullptr || ctx->in_polymorphic_specialization) { return; } + if (!is_type_polymorphic_record_unspecialized(type)) { return; } + bool invalid_polymorpic_type_use = false; + switch (type_expr->kind) { + case_ast_node(pt, Ident, type_expr); + invalid_polymorpic_type_use = true; + case_end; + case_ast_node(pt, SelectorExpr, type_expr); + invalid_polymorpic_type_use = true; + case_end; + } + + if (invalid_polymorpic_type_use) { + gbString expr_str = expr_to_string(type_expr); + defer (gb_string_free(expr_str)); + error(type_expr, "Invalid use of a non-specialized polymorphic type '%s'", expr_str); + } +} // NOTE(bill): 'operands' is for generating non generic procedure type gb_internal bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node, Array const *operands) { @@ -2433,6 +2453,7 @@ gb_internal bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc if (e->kind != Entity_Variable) { is_polymorphic = true; } else if (is_type_polymorphic(e->type)) { + check_procedure_param_polymorphic_type(c, e->type, e->Variable.type_expr); is_polymorphic = true; }