mirror of
https://github.com/odin-lang/Odin.git
synced 2026-07-22 23:42:33 +00:00
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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user