aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-03-27 15:22:05 +0000
committergingerBill <bill@gingerbill.org>2021-03-27 15:22:05 +0000
commit1e587d6635e93ca36ad2e6c8615dffed2b92e1fb (patch)
treeb2e5126aaa891b08db2f1591f5e931f026fc611d /src
parente21d7167200c76ff250db3308f1804b3314267c9 (diff)
Fix #883 - polymorphic specialization with target types of enumerated arrays
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.cpp60
-rw-r--r--src/check_type.cpp6
2 files changed, 65 insertions, 1 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 08bb2f457..98d289aa5 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -897,8 +897,68 @@ bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source,
if (poly->Array.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) {
+ // IMPORTANT TODO(bill): Which is correct?
+ // if (poly->Array.generic_count != nullptr && modify_type) {
+ if (poly->Array.generic_count != nullptr) {
+ Type *gt = poly->Array.generic_count;
+ GB_ASSERT(gt->kind == Type_Generic);
+ Entity *e = scope_lookup(gt->Generic.scope, gt->Generic.name);
+ GB_ASSERT(e != nullptr);
+ if (e->kind == Entity_TypeName) {
+ Type *elem = poly->Array.elem;
+ Type *index = source->EnumeratedArray.index;
+ Type *it = base_type(index);
+ if (it->kind != Type_Enum) {
+ return false;
+ }
+
+ poly->kind = Type_EnumeratedArray;
+ poly->cached_size = -1;
+ poly->cached_align = -1;
+ poly->flags = source->flags;
+ poly->failure = false;
+ poly->EnumeratedArray.elem = source->EnumeratedArray.elem;
+ poly->EnumeratedArray.index = source->EnumeratedArray.index;
+ poly->EnumeratedArray.min_value = source->EnumeratedArray.min_value;
+ poly->EnumeratedArray.max_value = source->EnumeratedArray.max_value;
+ poly->EnumeratedArray.count = source->EnumeratedArray.count;
+ poly->EnumeratedArray.op = source->EnumeratedArray.op;
+
+ e->kind = Entity_TypeName;
+ e->TypeName.is_type_alias = true;
+ e->type = index;
+
+ if (poly->EnumeratedArray.count == source->EnumeratedArray.count) {
+ return is_polymorphic_type_assignable(c, poly->EnumeratedArray.elem, source->EnumeratedArray.elem, true, modify_type);
+ }
+ }
+ }
}
return false;
+ case Type_EnumeratedArray:
+ if (source->kind == Type_EnumeratedArray) {
+ if (poly->EnumeratedArray.op != source->EnumeratedArray.op) {
+ return false;
+ }
+ if (poly->EnumeratedArray.op) {
+ if (poly->EnumeratedArray.count != source->EnumeratedArray.count) {
+ return false;
+ }
+ if (compare_exact_values(Token_NotEq, poly->EnumeratedArray.min_value, source->EnumeratedArray.min_value)) {
+ return false;
+ }
+ if (compare_exact_values(Token_NotEq, poly->EnumeratedArray.max_value, source->EnumeratedArray.max_value)) {
+ return false;
+ }
+ return is_polymorphic_type_assignable(c, poly->EnumeratedArray.index, source->EnumeratedArray.index, true, modify_type);
+ }
+ bool index = is_polymorphic_type_assignable(c, poly->EnumeratedArray.index, source->EnumeratedArray.index, true, modify_type);
+ bool elem = is_polymorphic_type_assignable(c, poly->EnumeratedArray.elem, source->EnumeratedArray.elem, true, modify_type);
+ return index || elem;
+ }
+ return false;
+
case Type_DynamicArray:
if (source->kind == Type_DynamicArray) {
return is_polymorphic_type_assignable(c, poly->DynamicArray.elem, source->DynamicArray.elem, true, modify_type);
diff --git a/src/check_type.cpp b/src/check_type.cpp
index 3eada163c..881bb9600 100644
--- a/src/check_type.cpp
+++ b/src/check_type.cpp
@@ -1187,7 +1187,11 @@ bool check_type_specialization_to(CheckerContext *ctx, Type *specialization, Typ
Type *t = base_type(type);
Type *s = base_type(specialization);
if (t->kind != s->kind) {
- return false;
+ if (t->kind == Type_EnumeratedArray && s->kind == Type_Array) {
+ // Might be okay, check later
+ } else {
+ return false;
+ }
}
if (is_type_untyped(t)) {