Fix is_type_polymorphic infinite recursion bug

This commit is contained in:
gingerBill
2018-11-22 09:41:08 +00:00
parent f61c4715c1
commit 6ab6447791
3 changed files with 36 additions and 27 deletions
+10 -7
View File
@@ -108,10 +108,11 @@ bool does_field_type_allow_using(Type *t) {
} }
void check_struct_fields(CheckerContext *ctx, Ast *node, Array<Entity *> *fields, Array<Ast *> const &params, void check_struct_fields(CheckerContext *ctx, Ast *node, Array<Entity *> *fields, Array<Ast *> const &params,
isize init_field_capacity, Type *named_type, String context) { isize init_field_capacity, Type *struct_type, String context) {
*fields = array_make<Entity *>(heap_allocator(), 0, init_field_capacity); *fields = array_make<Entity *>(heap_allocator(), 0, init_field_capacity);
GB_ASSERT(node->kind == Ast_StructType); GB_ASSERT(node->kind == Ast_StructType);
GB_ASSERT(struct_type->kind == Type_Struct);
isize variable_count = 0; isize variable_count = 0;
for_array(i, params) { for_array(i, params) {
@@ -137,6 +138,7 @@ void check_struct_fields(CheckerContext *ctx, Ast *node, Array<Entity *> *fields
if (type_expr != nullptr) { if (type_expr != nullptr) {
type = check_type_expr(ctx, type_expr, nullptr); type = check_type_expr(ctx, type_expr, nullptr);
if (is_type_polymorphic(type)) { if (is_type_polymorphic(type)) {
struct_type->Struct.is_polymorphic = true;
type = nullptr; type = nullptr;
} }
} }
@@ -336,10 +338,12 @@ void check_struct_type(CheckerContext *ctx, Type *struct_type, Ast *node, Array<
context = str_lit("struct #raw_union"); context = str_lit("struct #raw_union");
} }
Type *polymorphic_params = nullptr; // NOTE(bill): Yes I know it's a non-const reference, what you gonna do?
bool is_polymorphic = false; bool &is_polymorphic = struct_type->Struct.is_polymorphic;
bool can_check_fields = true;
bool is_poly_specialized = false; Type *polymorphic_params = nullptr;
bool can_check_fields = true;
bool is_poly_specialized = false;
if (st->polymorphic_params != nullptr) { if (st->polymorphic_params != nullptr) {
ast_node(field_list, FieldList, st->polymorphic_params); ast_node(field_list, FieldList, st->polymorphic_params);
@@ -489,12 +493,11 @@ void check_struct_type(CheckerContext *ctx, Type *struct_type, Ast *node, Array<
struct_type->Struct.scope = ctx->scope; struct_type->Struct.scope = ctx->scope;
struct_type->Struct.is_packed = st->is_packed; struct_type->Struct.is_packed = st->is_packed;
struct_type->Struct.polymorphic_params = polymorphic_params; struct_type->Struct.polymorphic_params = polymorphic_params;
struct_type->Struct.is_polymorphic = is_polymorphic;
struct_type->Struct.is_poly_specialized = is_poly_specialized; struct_type->Struct.is_poly_specialized = is_poly_specialized;
if (!is_polymorphic) { if (!is_polymorphic) {
check_struct_fields(ctx, node, &struct_type->Struct.fields, st->fields, min_field_count, named_type, context); check_struct_fields(ctx, node, &struct_type->Struct.fields, st->fields, min_field_count, struct_type, context);
} }
if (st->align != nullptr) { if (st->align != nullptr) {
+4 -2
View File
@@ -5163,7 +5163,7 @@ String ir_mangle_name(irGen *s, Entity *e) {
isize max_len = pkgn.len + 1 + name.len + 1; isize max_len = pkgn.len + 1 + name.len + 1;
bool require_suffix_id = is_type_polymorphic(e->type); bool require_suffix_id = is_type_polymorphic(e->type, true);
if (require_suffix_id) { if (require_suffix_id) {
max_len += 21; max_len += 21;
} }
@@ -5192,7 +5192,7 @@ void ir_mangle_add_sub_type_name(irModule *m, Entity *field, String parent) {
String cn = field->token.string; String cn = field->token.string;
isize max_len = parent.len + 1 + 16 + 1 + cn.len; isize max_len = parent.len + 1 + 16 + 1 + cn.len;
bool require_suffix_id = is_type_polymorphic(field->type); bool require_suffix_id = is_type_polymorphic(field->type, true);
if (require_suffix_id) { if (require_suffix_id) {
max_len += 21; max_len += 21;
} }
@@ -5325,6 +5325,8 @@ void ir_gen_global_type_name(irModule *m, Entity *e, String name) {
ir_mangle_add_sub_type_name(m, sub, name); ir_mangle_add_sub_type_name(m, sub, name);
} }
} }
} else {
GB_PANIC("Unknown poly type %s %p", type_to_string(e->type), e);
} }
return; return;
} }
+22 -18
View File
@@ -1120,30 +1120,30 @@ TypeTuple *get_record_polymorphic_params(Type *t) {
} }
bool is_type_polymorphic(Type *t) { bool is_type_polymorphic(Type *t, bool or_specialized=false) {
switch (t->kind) { switch (t->kind) {
case Type_Generic: case Type_Generic:
return true; return true;
case Type_Named: case Type_Named:
return is_type_polymorphic(t->Named.base); return is_type_polymorphic(t->Named.base, or_specialized);
case Type_Opaque: case Type_Opaque:
return is_type_polymorphic(t->Opaque.elem); return is_type_polymorphic(t->Opaque.elem, or_specialized);
case Type_Pointer: case Type_Pointer:
return is_type_polymorphic(t->Pointer.elem); return is_type_polymorphic(t->Pointer.elem, or_specialized);
case Type_Array: case Type_Array:
if (t->Array.generic_count != nullptr) { if (t->Array.generic_count != nullptr) {
return true; return true;
} }
return is_type_polymorphic(t->Array.elem); return is_type_polymorphic(t->Array.elem, or_specialized);
case Type_DynamicArray: case Type_DynamicArray:
return is_type_polymorphic(t->DynamicArray.elem); return is_type_polymorphic(t->DynamicArray.elem, or_specialized);
case Type_Slice: case Type_Slice:
return is_type_polymorphic(t->Slice.elem); return is_type_polymorphic(t->Slice.elem, or_specialized);
case Type_Tuple: case Type_Tuple:
for_array(i, t->Tuple.variables) { for_array(i, t->Tuple.variables) {
if (is_type_polymorphic(t->Tuple.variables[i]->type)) { if (is_type_polymorphic(t->Tuple.variables[i]->type, or_specialized)) {
return true; return true;
} }
} }
@@ -1155,11 +1155,11 @@ bool is_type_polymorphic(Type *t) {
} }
#if 1 #if 1
if (t->Proc.param_count > 0 && if (t->Proc.param_count > 0 &&
is_type_polymorphic(t->Proc.params)) { is_type_polymorphic(t->Proc.params, or_specialized)) {
return true; return true;
} }
if (t->Proc.result_count > 0 && if (t->Proc.result_count > 0 &&
is_type_polymorphic(t->Proc.results)) { is_type_polymorphic(t->Proc.results, or_specialized)) {
return true; return true;
} }
#endif #endif
@@ -1168,14 +1168,20 @@ bool is_type_polymorphic(Type *t) {
case Type_Enum: case Type_Enum:
if (t->kind == Type_Enum) { if (t->kind == Type_Enum) {
if (t->Enum.base_type != nullptr) { if (t->Enum.base_type != nullptr) {
return is_type_polymorphic(t->Enum.base_type); return is_type_polymorphic(t->Enum.base_type, or_specialized);
} }
return false; return false;
} }
break; break;
case Type_Union: case Type_Union:
if (t->Union.is_polymorphic) {
return true;
}
if (or_specialized && t->Union.is_poly_specialized) {
return true;
}
for_array(i, t->Union.variants) { for_array(i, t->Union.variants) {
if (is_type_polymorphic(t->Union.variants[i])) { if (is_type_polymorphic(t->Union.variants[i], or_specialized)) {
return true; return true;
} }
} }
@@ -1184,18 +1190,16 @@ bool is_type_polymorphic(Type *t) {
if (t->Struct.is_polymorphic) { if (t->Struct.is_polymorphic) {
return true; return true;
} }
for_array(i, t->Struct.fields) { if (or_specialized && t->Struct.is_poly_specialized) {
if (is_type_polymorphic(t->Struct.fields[i]->type)) { return true;
return true;
}
} }
break; break;
case Type_Map: case Type_Map:
if (is_type_polymorphic(t->Map.key)) { if (is_type_polymorphic(t->Map.key, or_specialized)) {
return true; return true;
} }
if (is_type_polymorphic(t->Map.value)) { if (is_type_polymorphic(t->Map.value, or_specialized)) {
return true; return true;
} }
break; break;