diff --git a/releasenotes.md b/releasenotes.md index ab81bec58..6c9076577 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -9,6 +9,7 @@ - Fix issue requiring prefix on a generic interface declaration. - Fix bug in SHA1 for longer blocks #1854. - Fix lack of location for reporting lambdas with missing return statement #1857. +- Compiler allows a generic module to be declared with different parameters #1856. ### Stdlib changes - Added '%h' and '%H' for printing out binary data in hexadecimal using the formatter. diff --git a/src/compiler/context.c b/src/compiler/context.c index 5b4dfa445..677721acf 100644 --- a/src/compiler/context.c +++ b/src/compiler/context.c @@ -20,26 +20,42 @@ static inline bool create_module_or_check_name(CompilationUnit *unit, Path *modu if (!module) { module = unit->module = compiler_find_or_create_module(module_name, parameters); - if ((parameters == NULL) == module->is_generic) + if (module->is_generic != (parameters != NULL)) { print_error_at(module_name->span, "'%s' is both used as regular and generic module, it can't be both.", - module_name->module); + module_name->module); SEMA_NOTE(module->name, "The definition here is different."); return false; } - } - else - { - if (unit->module->name->module != module_name->module) + if (!module->is_generic) goto DONE; + if (vec_size(parameters) != vec_size(module->parameters)) { - RETURN_PRINT_ERROR_AT(false, - module_name, - "Module name here '%s' did not match actual module '%s'.", - module_name->module, - module->name->module); + PRINT_ERROR_AT(module_name, "The parameter declarations of the generic module '%s' don't match."); + SEMA_NOTE(module->name, "A different definition can be found here."); + return false; } + FOREACH_IDX(idx, const char *, name, parameters) + { + bool is_type = str_is_type(name); + if (is_type != str_is_type(module->parameters[idx])) + { + PRINT_ERROR_AT(module_name, "The parameter declarations of the generic module '%s' don't match."); + SEMA_NOTE(module->name, "The other definition is here."); + return false; + } + } + goto DONE; + } + if (unit->module->name->module != module_name->module) + { + RETURN_PRINT_ERROR_AT(false, + module_name, + "Module name here '%s' did not match actual module '%s'.", + module_name->module, + module->name->module); } +DONE:; vec_add(module->units, unit); return true; } diff --git a/test/test_suite/generic/different_generic_def.c3 b/test/test_suite/generic/different_generic_def.c3 new file mode 100644 index 000000000..d22e10dd4 --- /dev/null +++ b/test/test_suite/generic/different_generic_def.c3 @@ -0,0 +1,21 @@ +module test; +import test2; +fn int main() +{ + Foo1() a; + return 0; +} + +module test2(); + +struct Foo +{ + Type f; +} + +module test2(); // #error: declarations of the generic + +struct Foo1 +{ + Type a; +}