Fix Issue with referencing a polymorphic struct in another package referencing itself #283

This commit is contained in:
gingerBill
2018-11-25 10:35:49 +00:00
parent 4c2f03b1f2
commit 0a4b88f9a6
3 changed files with 37 additions and 8 deletions
+12 -8
View File
@@ -27,7 +27,7 @@ struct CallArgumentData {
}; };
struct PolyProcData { struct PolyProcData {
Entity * gen_entity; Entity * gen_entity;
ProcInfo proc_info; ProcInfo proc_info;
}; };
@@ -4818,7 +4818,6 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
ast_node(ce, CallExpr, call); ast_node(ce, CallExpr, call);
Type *original_type = operand->type; Type *original_type = operand->type;
Type *struct_type = base_type(operand->type);
GB_ASSERT(is_type_polymorphic_record(original_type)); GB_ASSERT(is_type_polymorphic_record(original_type));
bool show_error = true; bool show_error = true;
@@ -4983,6 +4982,11 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
String generated_name = make_string_c(expr_to_string(call)); String generated_name = make_string_c(expr_to_string(call));
CheckerContext ctx = *c;
// NOTE(bill): We need to make sure the lookup scope for the record is the same as where it was created
ctx.scope = polymorphic_record_parent_scope(original_type);
GB_ASSERT(ctx.scope != nullptr);
Type *named_type = alloc_type_named(generated_name, nullptr, nullptr); Type *named_type = alloc_type_named(generated_name, nullptr, nullptr);
Type *bt = base_type(original_type); Type *bt = base_type(original_type);
if (bt->kind == Type_Struct) { if (bt->kind == Type_Struct) {
@@ -4992,9 +4996,9 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
struct_type->Struct.polymorphic_parent = original_type; struct_type->Struct.polymorphic_parent = original_type;
set_base_type(named_type, struct_type); set_base_type(named_type, struct_type);
check_open_scope(c, node); check_open_scope(&ctx, node);
check_struct_type(c, struct_type, node, &ordered_operands, named_type, original_type); check_struct_type(&ctx, struct_type, node, &ordered_operands, named_type, original_type);
check_close_scope(c); check_close_scope(&ctx);
} else if (bt->kind == Type_Union) { } else if (bt->kind == Type_Union) {
Ast *node = clone_ast(bt->Union.node); Ast *node = clone_ast(bt->Union.node);
Type *union_type = alloc_type_union(); Type *union_type = alloc_type_union();
@@ -5002,9 +5006,9 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
union_type->Union.polymorphic_parent = original_type; union_type->Union.polymorphic_parent = original_type;
set_base_type(named_type, union_type); set_base_type(named_type, union_type);
check_open_scope(c, node); check_open_scope(&ctx, node);
check_union_type(c, union_type, node, &ordered_operands, named_type, original_type); check_union_type(&ctx, union_type, node, &ordered_operands, named_type, original_type);
check_close_scope(c); check_close_scope(&ctx);
} else { } else {
GB_PANIC("Unsupported parametric polymorphic record type"); GB_PANIC("Unsupported parametric polymorphic record type");
} }
+6
View File
@@ -2521,6 +2521,12 @@ Type *check_type_expr(CheckerContext *ctx, Ast *e, Type *named_type) {
type->Named.base = t_invalid; type->Named.base = t_invalid;
} }
if (is_type_polymorphic(type)) {
type->flags |= TypeFlag_Polymorphic;
} else if (is_type_polymorphic(type, true)) {
type->flags |= TypeFlag_PolySpecialized;
}
#if 0 #if 0
if (!ctx->allow_polymorphic_types && is_type_polymorphic(type)) { if (!ctx->allow_polymorphic_types && is_type_polymorphic(type)) {
gbString str = type_to_string(type); gbString str = type_to_string(type);
+19
View File
@@ -215,6 +215,11 @@ String const type_strings[] = {
TYPE_KINDS TYPE_KINDS
#undef TYPE_KIND #undef TYPE_KIND
enum TypeFlag : u32 {
TypeFlag_Polymorphic = 1<<1,
TypeFlag_PolySpecialized = 1<<2,
};
struct Type { struct Type {
TypeKind kind; TypeKind kind;
union { union {
@@ -226,6 +231,7 @@ struct Type {
// NOTE(bill): These need to be at the end to not affect the unionized data // NOTE(bill): These need to be at the end to not affect the unionized data
i64 cached_size; i64 cached_size;
i64 cached_align; i64 cached_align;
u32 flags; // TypeFlag
bool failure; bool failure;
}; };
@@ -1072,6 +1078,7 @@ bool is_type_indexable(Type *t) {
return false; return false;
} }
bool is_type_polymorphic_record(Type *t) { bool is_type_polymorphic_record(Type *t) {
t = base_type(t); t = base_type(t);
if (t->kind == Type_Struct) { if (t->kind == Type_Struct) {
@@ -1082,6 +1089,18 @@ bool is_type_polymorphic_record(Type *t) {
return false; return false;
} }
Scope *polymorphic_record_parent_scope(Type *t) {
t = base_type(t);
if (is_type_polymorphic_record(t)) {
if (t->kind == Type_Struct) {
return t->Struct.scope->parent;
} else if (t->kind == Type_Union) {
return t->Union.scope->parent;
}
}
return nullptr;
}
bool is_type_polymorphic_record_specialized(Type *t) { bool is_type_polymorphic_record_specialized(Type *t) {
t = base_type(t); t = base_type(t);
if (t->kind == Type_Struct) { if (t->kind == Type_Struct) {