From 6a85546b761b67fa012a2cd49e32b2211bf02971 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 14 Feb 2018 21:46:39 +0000 Subject: Fix #187 --- src/check_type.cpp | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) (limited to 'src/check_type.cpp') diff --git a/src/check_type.cpp b/src/check_type.cpp index 46399f7f1..47e27c27d 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -920,6 +920,7 @@ bool check_type_specialization_to(Checker *c, Type *specialization, Type *type, } // gb_printf_err("#1 %s %s\n", type_to_string(type), type_to_string(specialization)); if (t->kind == Type_Struct) { + if (t->Struct.polymorphic_parent == specialization) { return true; } @@ -1937,24 +1938,31 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) Operand o = {}; check_ident(c, &o, e, named_type, nullptr, false); - gbString err_str; + gbString err_str = nullptr; + defer (gb_string_free(err_str)); + switch (o.mode) { case Addressing_Invalid: break; - case Addressing_Type: + case Addressing_Type: { *type = o.type; + if (!c->context.in_polymorphic_specialization) { + if (is_type_polymorphic_struct_unspecialized(o.type)) { + err_str = expr_to_string(e); + error(e, "Invalid use of a non-specialized polymorphic type '%s'", err_str); + } + } return true; + } case Addressing_NoValue: err_str = expr_to_string(e); error(e, "'%s' used as a type", err_str); - gb_string_free(err_str); break; default: err_str = expr_to_string(e); error(e, "'%s' used as a type when not a type", err_str); - gb_string_free(err_str); break; } case_end; @@ -1980,6 +1988,10 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) Token token = ident->Ident.token; Type *specific = nullptr; if (pt->specialization != nullptr) { + auto prev_ips = c->context.in_polymorphic_specialization; + defer (c->context.in_polymorphic_specialization = prev_ips); + c->context.in_polymorphic_specialization = true; + AstNode *s = pt->specialization; specific = check_type(c, s); if (false && !is_type_polymorphic_struct(specific)) { @@ -2088,6 +2100,10 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) case_end; case_ast_node(st, StructType, e); + bool ips = c->context.in_polymorphic_specialization; + defer (c->context.in_polymorphic_specialization = ips); + c->context.in_polymorphic_specialization = false; + *type = make_type_struct(c->allocator); set_base_type(named_type, *type); check_open_scope(c, e); @@ -2098,6 +2114,10 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) case_end; case_ast_node(ut, UnionType, e); + bool ips = c->context.in_polymorphic_specialization; + defer (c->context.in_polymorphic_specialization = ips); + c->context.in_polymorphic_specialization = false; + *type = make_type_union(c->allocator); set_base_type(named_type, *type); check_open_scope(c, e); @@ -2108,6 +2128,10 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) case_end; case_ast_node(et, EnumType, e); + bool ips = c->context.in_polymorphic_specialization; + defer (c->context.in_polymorphic_specialization = ips); + c->context.in_polymorphic_specialization = false; + *type = make_type_enum(c->allocator); set_base_type(named_type, *type); check_open_scope(c, e); @@ -2127,6 +2151,10 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) case_end; case_ast_node(pt, ProcType, e); + bool ips = c->context.in_polymorphic_specialization; + defer (c->context.in_polymorphic_specialization = ips); + c->context.in_polymorphic_specialization = false; + *type = alloc_type(c->allocator, Type_Proc); set_base_type(named_type, *type); check_open_scope(c, e); @@ -2136,6 +2164,10 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) case_end; case_ast_node(mt, MapType, e); + bool ips = c->context.in_polymorphic_specialization; + defer (c->context.in_polymorphic_specialization = ips); + c->context.in_polymorphic_specialization = false; + *type = alloc_type(c->allocator, Type_Map); set_base_type(named_type, *type); check_map_type(c, *type, e); -- cgit v1.2.3