diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 943b1972d..cb54f6b7a 100644 --- a/src/check_expr.cpp +++ b/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"); } diff --git a/src/check_type.cpp b/src/check_type.cpp index 88c9e4bcf..235aaec71 100644 --- a/src/check_type.cpp +++ b/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); diff --git a/src/types.cpp b/src/types.cpp index fa0cb88d7..3969d9603 100644 --- a/src/types.cpp +++ b/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) {