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); } }