diff --git a/src/compiler/ast.c b/src/compiler/ast.c index 002f519d0..fc83299b6 100644 --- a/src/compiler/ast.c +++ b/src/compiler/ast.c @@ -327,6 +327,45 @@ bool decl_is_defaulted_var(Decl *decl) return decl->decl_kind == DECL_VAR && decl->var.no_init && decl->var.defaulted; } +bool decl_may_be_generic(Decl *decl) +{ + switch (decl->decl_kind) + { + case DECL_POISONED: + case DECL_BODYPARAM: + case DECL_CT_ASSERT: + case DECL_CT_ECHO: + case DECL_CT_EXEC: + case DECL_CT_INCLUDE: + case DECL_ALIAS_PATH: + case DECL_ENUM_CONSTANT: + case DECL_ERASED: + case DECL_FAULT: + case DECL_GROUP: + case DECL_GENERIC: + case DECL_GENERIC_INSTANCE: + case DECL_IMPORT: + case DECL_LABEL: + case DECL_CONST_ENUM: + return false; + case DECL_ATTRIBUTE: + case DECL_BITSTRUCT: + case DECL_DECLARRAY: + case DECL_ALIAS: + case DECL_TYPEDEF: + case DECL_ENUM: + case DECL_FNTYPE: + case DECL_FUNC: + case DECL_MACRO: + case DECL_INTERFACE: + case DECL_STRUCT: + case DECL_TYPE_ALIAS: + case DECL_UNION: + case DECL_VAR: + return true; + } + UNREACHABLE +} /* * Count the expected number of elements needed for an initializer * by folding any anonymous structs and unions. diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 40e41e7e6..939f20a90 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -2382,6 +2382,7 @@ const char *decl_to_name(Decl *decl); const char *decl_to_a_name(Decl *decl); int decl_count_elements(Decl *structlike); bool decl_is_defaulted_var(Decl *decl); +bool decl_may_be_generic(Decl *decl); void decl_append_links_to_global_during_codegen(Decl *decl); Decl *decl_template_get_generic(Decl *decl); diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index 1027bc4d7..2eb502458 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -1323,12 +1323,18 @@ static bool parse_attributes_for_global(ParseContext *c, Decl *decl) bool is_builtin = false; bool is_cond; Decl *generics = NULL; + bool can_be_generic = decl_may_be_generic(decl); if (!parse_attributes(c, &decl->attributes, &visibility, decl_needs_prefix(decl) ? &is_builtin : NULL, &is_cond, &generics)) return false; if (generics) { + if (!can_be_generic) + { + print_error_at(decl->span, "This declaration cannot be generic."); + return false; + } parse_attach_generics(c, generics); } - if (!generics && c->unit->default_generic_section) + if (!generics && c->unit->default_generic_section && can_be_generic) { generics = c->unit->default_generic_section; } @@ -2318,7 +2324,7 @@ static inline Decl *parse_alias_type(ParseContext *c, AstId contracts) { advance_and_verify(c, TOKEN_ALIAS); - Decl *decl = decl_new(DECL_POISONED, symstr(c), c->span); + Decl *decl = decl_new(DECL_TYPE_ALIAS, symstr(c), c->span); DEBUG_LOG("Parse def %s", decl->name); if (!try_consume(c, TOKEN_TYPE_IDENT)) { diff --git a/src/compiler/semantic_analyser.c b/src/compiler/semantic_analyser.c index 6b62ee01e..671b12535 100644 --- a/src/compiler/semantic_analyser.c +++ b/src/compiler/semantic_analyser.c @@ -251,9 +251,6 @@ static void register_generic_decls(CompilationUnit *unit, Decl **decls) case DECL_POISONED: continue; case DECL_FAULT: - PRINT_ERROR_AT(decl, "Generic modules cannot use 'faultdef', place the declaration in a separate sub module or parent module instead."); - decl_poison(decl); - break; case DECL_BODYPARAM: case DECL_DECLARRAY: case DECL_ENUM_CONSTANT: diff --git a/test/test_suite/generic/generic_fault.c3t b/test/test_suite/generic/generic_fault.c3t index 2782097a0..ce7bce1d5 100644 --- a/test/test_suite/generic/generic_fault.c3t +++ b/test/test_suite/generic/generic_fault.c3t @@ -1,11 +1,11 @@ module abc {Type}; attrdef @Hello = @inline; -faultdef ABC; // #error: Generic modules cannot use 'faultdef' +faultdef ABC; module bcd; - +import abc; fn void main() { - Abc{int} a; + int? a = abc::ABC~; } \ No newline at end of file diff --git a/test/test_suite/generic/generic_fault2.c3t b/test/test_suite/generic/generic_fault2.c3t new file mode 100644 index 000000000..71fd096ea --- /dev/null +++ b/test/test_suite/generic/generic_fault2.c3t @@ -0,0 +1,7 @@ +module g{T}; + +faultdef F0, F1; + +module main; + +fn void main() {} \ No newline at end of file