diff --git a/core/odin/ast/ast.odin b/core/odin/ast/ast.odin index 18916a788..f5eab84cc 100644 --- a/core/odin/ast/ast.odin +++ b/core/odin/ast/ast.odin @@ -562,6 +562,7 @@ Field_Flags_Struct :: Field_Flags{ }; Field_Flags_Record_Poly_Params :: Field_Flags{ .Typeid_Token, + .Default_Parameters, }; Field_Flags_Signature :: Field_Flags{ .Ellipsis, diff --git a/src/check_type.cpp b/src/check_type.cpp index eb2891cb7..3eada163c 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -152,10 +152,12 @@ void check_struct_fields(CheckerContext *ctx, Ast *node, Array *fields for_array(j, p->names) { Ast *name = p->names[j]; - if (!ast_node_expect(name, Ast_Ident)) { + if (!ast_node_expect2(name, Ast_Ident, Ast_PolyType)) { continue; } - + if (name->kind == Ast_PolyType) { + name = name->PolyType.type; + } Token name_token = name->Ident.token; Entity *field = alloc_entity_field(ctx->scope, name_token, type, is_using, field_src_index); @@ -464,9 +466,12 @@ void check_struct_type(CheckerContext *ctx, Type *struct_type, Ast *node, Array< Scope *scope = ctx->scope; for_array(j, p->names) { Ast *name = p->names[j]; - if (!ast_node_expect(name, Ast_Ident)) { + if (!ast_node_expect2(name, Ast_Ident, Ast_PolyType)) { continue; } + if (name->kind == Ast_PolyType) { + name = name->PolyType.type; + } Entity *e = nullptr; Token token = name->Ident.token; @@ -680,9 +685,12 @@ void check_union_type(CheckerContext *ctx, Type *union_type, Ast *node, Arrayscope; for_array(j, p->names) { Ast *name = p->names[j]; - if (!ast_node_expect(name, Ast_Ident)) { + if (!ast_node_expect2(name, Ast_Ident, Ast_PolyType)) { continue; } + if (name->kind == Ast_PolyType) { + name = name->PolyType.type; + } Entity *e = nullptr; Token token = name->Ident.token; diff --git a/src/parser.cpp b/src/parser.cpp index 46eb9145c..4b77255dc 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -490,6 +490,13 @@ bool ast_node_expect(Ast *node, AstKind kind) { } return true; } +bool ast_node_expect2(Ast *node, AstKind kind0, AstKind kind1) { + if (node->kind != kind0 && node->kind != kind1) { + syntax_error(node, "Expected %.*s or %.*s, got %.*s", LIT(ast_strings[kind0]), LIT(ast_strings[kind1]), LIT(ast_strings[node->kind])); + return false; + } + return true; +} Ast *ast_bad_expr(AstFile *f, Token begin, Token end) { Ast *result = alloc_ast_node(f, Ast_BadExpr); @@ -1863,9 +1870,9 @@ void check_polymorphic_params_for_type(AstFile *f, Ast *polymorphic_params, Toke } for_array(i, field->Field.names) { Ast *name = field->Field.names[i]; - if (name->kind == Ast_PolyType) { - syntax_error(name, "Polymorphic names are not needed for %.*s parameters", LIT(token.string)); - return; // TODO(bill): Err multiple times or just the once? + if (name->kind != field->Field.names[0]->kind) { + syntax_error(name, "Mixture of polymorphic names using both $ and not for %.*s parameters", LIT(token.string)); + return; } } }