From ca878a1de7e90ba62d146fd091ff918b8d65e334 Mon Sep 17 00:00:00 2001 From: Isabella Basso Date: Thu, 21 May 2026 02:26:27 -0300 Subject: [PATCH] checker: keep polymorphic probes read-only Overload candidate checks pass modify_type=false, but generic array counts still specialized their candidate Type and scope entity. Parallel probes could then observe and mutate the same partial specialization. Resolve generic dimensions in local state and commit them only when specializing. Keep array-like and map cache updates out of probe mode. --- src/check_expr.cpp | 89 +++++++++++++++++++++++++++++++--------------- 1 file changed, 61 insertions(+), 28 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 7b95da1ad..0bad86a8c 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1386,22 +1386,22 @@ gb_internal void check_assignment(CheckerContext *c, Operand *operand, Type *typ } } -gb_internal bool polymorphic_assign_index(Type **gt_, i64 *dst_count, i64 source_count) { +gb_internal bool polymorphic_assign_index(Type **gt_, i64 *dst_count, i64 source_count, bool modify_type) { Type *gt = *gt_; - GB_ASSERT(gt->kind == Type_Generic); Entity *e = scope_lookup(gt->Generic.scope, gt->Generic.interned_name, 0); GB_ASSERT(e != nullptr); if (e->kind == Entity_TypeName) { - *gt_ = nullptr; *dst_count = source_count; - e->kind = Entity_Constant; - e->Constant.value = exact_value_i64(source_count); - e->type = t_untyped_integer; + if (modify_type) { + *gt_ = nullptr; + e->kind = Entity_Constant; + e->Constant.value = exact_value_i64(source_count); + e->type = t_untyped_integer; + } return true; } else if (e->kind == Entity_Constant) { - *gt_ = nullptr; if (e->Constant.value.kind != ExactValue_Integer) { return false; } @@ -1410,6 +1410,9 @@ gb_internal bool polymorphic_assign_index(Type **gt_, i64 *dst_count, i64 source return false; } *dst_count = source_count; + if (modify_type) { + *gt_ = nullptr; + } return true; } return false; @@ -1490,12 +1493,18 @@ gb_internal bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, T case Type_Array: if (source->kind == Type_Array) { - if (poly->Array.generic_count != nullptr) { - if (!polymorphic_assign_index(&poly->Array.generic_count, &poly->Array.count, source->Array.count)) { + Type *generic_count = poly->Array.generic_count; + i64 count = poly->Array.count; + if (generic_count != nullptr) { + if (!polymorphic_assign_index(&generic_count, &count, source->Array.count, modify_type)) { return false; } + if (modify_type) { + poly->Array.generic_count = generic_count; + poly->Array.count = count; + } } - if (poly->Array.count == source->Array.count) { + if (count == source->Array.count) { return is_polymorphic_type_assignable(c, poly->Array.elem, source->Array.elem, true, modify_type); } } else if (source->kind == Type_EnumeratedArray) { @@ -1510,6 +1519,9 @@ gb_internal bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, T if (it->kind != Type_Enum) { return false; } + if (!modify_type) { + return is_polymorphic_type_assignable(c, poly->Array.elem, source->EnumeratedArray.elem, true, false); + } poly->kind = Type_EnumeratedArray; poly->cached_size = -1; @@ -1565,14 +1577,18 @@ gb_internal bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, T case Type_FixedCapacityDynamicArray: if (source->kind == Type_FixedCapacityDynamicArray) { - if (poly->FixedCapacityDynamicArray.generic_capacity != nullptr) { - if (!polymorphic_assign_index(&poly->FixedCapacityDynamicArray.generic_capacity, - &poly->FixedCapacityDynamicArray.capacity, - source->FixedCapacityDynamicArray.capacity)) { + Type *generic_capacity = poly->FixedCapacityDynamicArray.generic_capacity; + i64 capacity = poly->FixedCapacityDynamicArray.capacity; + if (generic_capacity != nullptr) { + if (!polymorphic_assign_index(&generic_capacity, &capacity, source->FixedCapacityDynamicArray.capacity, modify_type)) { return false; } + if (modify_type) { + poly->FixedCapacityDynamicArray.generic_capacity = generic_capacity; + poly->FixedCapacityDynamicArray.capacity = capacity; + } } - if (poly->FixedCapacityDynamicArray.capacity == source->FixedCapacityDynamicArray.capacity) { + if (capacity == source->FixedCapacityDynamicArray.capacity) { return is_polymorphic_type_assignable(c, poly->FixedCapacityDynamicArray.elem, source->FixedCapacityDynamicArray.elem, true, modify_type); } } @@ -1723,8 +1739,10 @@ gb_internal bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, T bool key = is_polymorphic_type_assignable(c, poly->Map.key, source->Map.key, true, modify_type); bool value = is_polymorphic_type_assignable(c, poly->Map.value, source->Map.value, true, modify_type); if (key || value) { - poly->Map.lookup_result_type = nullptr; - init_map_internal_types(poly); + if (modify_type) { + poly->Map.lookup_result_type = nullptr; + init_map_internal_types(poly); + } return true; } } @@ -1732,20 +1750,29 @@ gb_internal bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, T case Type_Matrix: if (source->kind == Type_Matrix) { - if (poly->Matrix.generic_row_count != nullptr) { - poly->Matrix.stride_in_bytes = 0; - if (!polymorphic_assign_index(&poly->Matrix.generic_row_count, &poly->Matrix.row_count, source->Matrix.row_count)) { + Type *generic_row_count = poly->Matrix.generic_row_count; + Type *generic_column_count = poly->Matrix.generic_column_count; + i64 row_count = poly->Matrix.row_count; + i64 column_count = poly->Matrix.column_count; + if (generic_row_count != nullptr) { + if (!polymorphic_assign_index(&generic_row_count, &row_count, source->Matrix.row_count, modify_type)) { return false; } } - if (poly->Matrix.generic_column_count != nullptr) { - poly->Matrix.stride_in_bytes = 0; - if (!polymorphic_assign_index(&poly->Matrix.generic_column_count, &poly->Matrix.column_count, source->Matrix.column_count)) { + if (generic_column_count != nullptr) { + if (!polymorphic_assign_index(&generic_column_count, &column_count, source->Matrix.column_count, modify_type)) { return false; } } - if (poly->Matrix.row_count == source->Matrix.row_count && - poly->Matrix.column_count == source->Matrix.column_count) { + if (modify_type && (poly->Matrix.generic_row_count != nullptr || poly->Matrix.generic_column_count != nullptr)) { + poly->Matrix.generic_row_count = generic_row_count; + poly->Matrix.generic_column_count = generic_column_count; + poly->Matrix.row_count = row_count; + poly->Matrix.column_count = column_count; + poly->Matrix.stride_in_bytes = 0; + } + if (row_count == source->Matrix.row_count && + column_count == source->Matrix.column_count) { return is_polymorphic_type_assignable(c, poly->Matrix.elem, source->Matrix.elem, true, modify_type); } } @@ -1753,12 +1780,18 @@ gb_internal bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, T case Type_SimdVector: if (source->kind == Type_SimdVector) { - if (poly->SimdVector.generic_count != nullptr) { - if (!polymorphic_assign_index(&poly->SimdVector.generic_count, &poly->SimdVector.count, source->SimdVector.count)) { + Type *generic_count = poly->SimdVector.generic_count; + i64 count = poly->SimdVector.count; + if (generic_count != nullptr) { + if (!polymorphic_assign_index(&generic_count, &count, source->SimdVector.count, modify_type)) { return false; } + if (modify_type) { + poly->SimdVector.generic_count = generic_count; + poly->SimdVector.count = count; + } } - if (poly->SimdVector.count == source->SimdVector.count) { + if (count == source->SimdVector.count) { return is_polymorphic_type_assignable(c, poly->SimdVector.elem, source->SimdVector.elem, true, modify_type); } }