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.
This commit is contained in:
Isabella Basso
2026-05-21 02:26:27 -03:00
parent 6ccea209ba
commit ca878a1de7

View File

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