Browse Source

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

gingerBill 6 years ago
parent
commit
0a4b88f9a6
3 changed files with 37 additions and 8 deletions
  1. 12 8
      src/check_expr.cpp
  2. 6 0
      src/check_type.cpp
  3. 19 0
      src/types.cpp

+ 12 - 8
src/check_expr.cpp

@@ -27,7 +27,7 @@ struct CallArgumentData {
 };
 
 struct PolyProcData {
-	Entity *      gen_entity;
+	Entity * gen_entity;
 	ProcInfo proc_info;
 };
 
@@ -4818,7 +4818,6 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
 	ast_node(ce, CallExpr, call);
 
 	Type *original_type = operand->type;
-	Type *struct_type = base_type(operand->type);
 	GB_ASSERT(is_type_polymorphic_record(original_type));
 
 	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));
 
+		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 *bt = base_type(original_type);
 		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;
 			set_base_type(named_type, struct_type);
 
-			check_open_scope(c, node);
-			check_struct_type(c, struct_type, node, &ordered_operands, named_type, original_type);
-			check_close_scope(c);
+			check_open_scope(&ctx, node);
+			check_struct_type(&ctx, struct_type, node, &ordered_operands, named_type, original_type);
+			check_close_scope(&ctx);
 		} else if (bt->kind == Type_Union) {
 			Ast *node = clone_ast(bt->Union.node);
 			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;
 			set_base_type(named_type, union_type);
 
-			check_open_scope(c, node);
-			check_union_type(c, union_type, node, &ordered_operands, named_type, original_type);
-			check_close_scope(c);
+			check_open_scope(&ctx, node);
+			check_union_type(&ctx, union_type, node, &ordered_operands, named_type, original_type);
+			check_close_scope(&ctx);
 		} else {
 			GB_PANIC("Unsupported parametric polymorphic record type");
 		}

+ 6 - 0
src/check_type.cpp

@@ -2521,6 +2521,12 @@ Type *check_type_expr(CheckerContext *ctx, Ast *e, Type *named_type) {
 		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 (!ctx->allow_polymorphic_types && is_type_polymorphic(type)) {
 		gbString str = type_to_string(type);

+ 19 - 0
src/types.cpp

@@ -215,6 +215,11 @@ String const type_strings[] = {
 	TYPE_KINDS
 #undef TYPE_KIND
 
+enum TypeFlag : u32 {
+	TypeFlag_Polymorphic     = 1<<1,
+	TypeFlag_PolySpecialized = 1<<2,
+};
+
 struct Type {
 	TypeKind kind;
 	union {
@@ -226,6 +231,7 @@ struct Type {
 	// NOTE(bill): These need to be at the end to not affect the unionized data
 	i64  cached_size;
 	i64  cached_align;
+	u32  flags; // TypeFlag
 	bool failure;
 };
 
@@ -1072,6 +1078,7 @@ bool is_type_indexable(Type *t) {
 	return false;
 }
 
+
 bool is_type_polymorphic_record(Type *t) {
 	t = base_type(t);
 	if (t->kind == Type_Struct) {
@@ -1082,6 +1089,18 @@ bool is_type_polymorphic_record(Type *t) {
 	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) {
 	t = base_type(t);
 	if (t->kind == Type_Struct) {