From 30c6fea9e9dfb9be1efff6ce4e6954ae138d06bf Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Fri, 2 May 2025 15:38:43 +0200 Subject: Allow polymorphic #simd array as return type --- src/check_type.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/check_type.cpp') diff --git a/src/check_type.cpp b/src/check_type.cpp index 1549f477e..452da4023 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -3297,8 +3297,11 @@ gb_internal void check_array_type_internal(CheckerContext *ctx, Ast *e, Type **t if (generic_type != nullptr) { // Ignore } else if (count < 1 || !is_power_of_two(count)) { - error(at->count, "Invalid length for #simd, expected a power of two length, got '%lld'", cast(long long)count); *type = alloc_type_array(elem, count, generic_type); + if (ctx->disallow_polymorphic_return_types && count == 0) { + return; + } + error(at->count, "Invalid length for #simd, expected a power of two length, got '%lld'", cast(long long)count); return; } -- cgit v1.2.3 From af6b763449a7876f08b3edaf9875c57769f10bd4 Mon Sep 17 00:00:00 2001 From: bogwi Date: Mon, 5 May 2025 17:53:32 +0900 Subject: CHECK 3 done Enhance support for polymorphic procedures in type checking 1. In src/check_type.cpp, added special handling for polymorphic procedures used as default parameter values. We now allow a polymorphic procedure to be used as a default parameter value, even when its type parameters can't be immediately determined. 2. In src/check_expr.cpp, we modified the check_is_assignable_to_with_score function to handle the special case of assigning a polymorphic procedure as a default parameter. The function now allows a polymorphic procedure to be assigned to a concrete procedure type in this specific context. --- src/check_expr.cpp | 38 +++++++++++++++++++++++++++++--------- src/check_type.cpp | 11 ++++++++++- 2 files changed, 39 insertions(+), 10 deletions(-) (limited to 'src/check_type.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 10b37bbf3..7ccca1b57 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -643,7 +643,7 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E gb_internal bool check_polymorphic_procedure_assignment(CheckerContext *c, Operand *operand, Type *type, Ast *poly_def_node, PolyProcData *poly_proc_data) { if (operand->expr == nullptr) return false; - Entity *base_entity = entity_of_node(operand->expr); + Entity *base_entity = entity_from_expr(operand->expr); if (base_entity == nullptr) return false; return find_or_generate_polymorphic_procedure(c, base_entity, type, nullptr, poly_def_node, poly_proc_data); } @@ -995,14 +995,34 @@ gb_internal i64 assign_score_function(i64 distance, bool is_variadic=false) { gb_internal bool check_is_assignable_to_with_score(CheckerContext *c, Operand *operand, Type *type, i64 *score_, bool is_variadic=false, bool allow_array_programming=true) { - i64 score = 0; - i64 distance = check_distance_between_types(c, operand, type, allow_array_programming); - bool ok = distance >= 0; - if (ok) { - score = assign_score_function(distance, is_variadic); + if (c == nullptr) { + GB_ASSERT(operand->mode == Addressing_Value); + GB_ASSERT(is_type_typed(operand->type)); + } + if (operand->mode == Addressing_Invalid || type == t_invalid) { + if (score_) *score_ = 0; + return false; + } + + // Handle polymorphic procedure used as default parameter + if (operand->mode == Addressing_Value && is_type_proc(type) && is_type_proc(operand->type)) { + Entity *e = entity_from_expr(operand->expr); + if (e != nullptr && e->kind == Entity_Procedure && is_type_polymorphic(e->type) && !is_type_polymorphic(type)) { + // Special case: Allow a polymorphic procedure to be used as default value for concrete proc type + // during the initial check. It will be properly instantiated when actually used. + if (score_) *score_ = assign_score_function(1); + return true; + } + } + + i64 score = check_distance_between_types(c, operand, type, allow_array_programming); + if (score >= 0) { + if (score_) *score_ = assign_score_function(score, is_variadic); + return true; } - if (score_) *score_ = score; - return ok; + + if (score_) *score_ = 0; + return false; } @@ -10996,7 +11016,7 @@ gb_internal ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast return kind; case_end; - case_ast_node(i, Implicit, node) + case_ast_node(i, Implicit, node); switch (i->kind) { case Token_context: { diff --git a/src/check_type.cpp b/src/check_type.cpp index 452da4023..431698459 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1910,9 +1910,18 @@ gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_para case ParameterValue_Location: case ParameterValue_Expression: case ParameterValue_Value: + // Special case for polymorphic procedures as default values + if (param_value.ast_value != nullptr) { + Entity *e = entity_from_expr(param_value.ast_value); + if (e != nullptr && e->kind == Entity_Procedure && is_type_polymorphic(e->type)) { + // Allow polymorphic procedures as default parameter values + // The type will be correctly determined at call site + break; + } + } gbString str = type_to_string(type); error(params[i], "A default value for a parameter must not be a polymorphic constant type, got %s", str); - gb_string_free(str); + gb_string_free(str); break; } } -- cgit v1.2.3 From 478c923e2cc6d4fc15ccf550b0c952495d8b81df Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Mon, 26 May 2025 19:48:28 +0200 Subject: fix another type alias issue with mini cycle --- src/check_type.cpp | 8 ++++++-- tests/issues/run.bat | 1 + tests/issues/run.sh | 1 + tests/issues/test_issue_5097-2.odin | 24 ++++++++++++++++++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 tests/issues/test_issue_5097-2.odin (limited to 'src/check_type.cpp') diff --git a/src/check_type.cpp b/src/check_type.cpp index 431698459..450b5e100 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -3805,7 +3805,11 @@ gb_internal Type *check_type_expr(CheckerContext *ctx, Ast *e, Type *named_type) #if 0 error(e, "Invalid type definition of '%.*s'", LIT(type->Named.name)); #endif - type->Named.base = t_invalid; + if (type->Named.type_name->TypeName.is_type_alias) { + // NOTE(laytan): keep it null, type declaration is a mini "cycle" to be filled later. + } else { + type->Named.base = t_invalid; + } } if (is_type_polymorphic(type)) { @@ -3823,7 +3827,7 @@ gb_internal Type *check_type_expr(CheckerContext *ctx, Ast *e, Type *named_type) } #endif - if (is_type_typed(type)) { + if (type->kind == Type_Named && type->Named.base == nullptr || is_type_typed(type)) { add_type_and_value(ctx, e, Addressing_Type, type, empty_exact_value); } else { gbString name = type_to_string(type); diff --git a/tests/issues/run.bat b/tests/issues/run.bat index 267a2e030..db941b55a 100644 --- a/tests/issues/run.bat +++ b/tests/issues/run.bat @@ -19,6 +19,7 @@ set COMMON=-define:ODIN_TEST_FANCY=false -file -vet -strict-style ..\..\..\odin test ..\test_issue_4584.odin %COMMON% || exit /b ..\..\..\odin build ..\test_issue_5043.odin %COMMON% || exit /b ..\..\..\odin build ..\test_issue_5097.odin %COMMON% || exit /b +..\..\..\odin build ..\test_issue_5097-2.odin %COMMON% || exit /b @echo off diff --git a/tests/issues/run.sh b/tests/issues/run.sh index 5102ee307..db0864c3e 100755 --- a/tests/issues/run.sh +++ b/tests/issues/run.sh @@ -26,6 +26,7 @@ else fi $ODIN build ../test_issue_5043.odin $COMMON $ODIN build ../test_issue_5097.odin $COMMON +$ODIN build ../test_issue_5097-2.odin $COMMON set +x diff --git a/tests/issues/test_issue_5097-2.odin b/tests/issues/test_issue_5097-2.odin new file mode 100644 index 000000000..1e4ad59c9 --- /dev/null +++ b/tests/issues/test_issue_5097-2.odin @@ -0,0 +1,24 @@ +// Tests another variation of, this should compile #5097 https://github.com/odin-lang/Odin/issues/5097 +package test_issues + +Face :: ^FaceRec +GlyphSlot :: ^GlyphSlotRec +Size :: ^SizeRec + +SizeRec :: struct { + face: Face, +} + +GlyphSlotRec :: struct { + face: Face, +} + +FaceRec :: struct { + glyph: GlyphSlot, + size: Size, +} + +main :: proc() { + face: Face + _ = face +} -- cgit v1.2.3