Allow recursive generic modules.

This commit is contained in:
Christoffer Lerno
2025-05-28 15:39:35 +02:00
parent 9f30b56e13
commit 349d9ef3cf
3 changed files with 12 additions and 7 deletions

View File

@@ -21,6 +21,7 @@
- Add `$$matrix_mul` and `$$matrix_transpose` builtins. - Add `$$matrix_mul` and `$$matrix_transpose` builtins.
- Add `d` as floating point suffix for `double` types. - Add `d` as floating point suffix for `double` types.
- Deprecate `f32`, `f64` and `f128` suffixes. - Deprecate `f32`, `f64` and `f128` suffixes.
- Allow recursive generic modules.
### Fixes ### Fixes
- Assert triggered when casting from `int[2]` to `uint[2]` #2115 - Assert triggered when casting from `int[2]` to `uint[2]` #2115

View File

@@ -2374,6 +2374,14 @@ static inline bool unit_add_method(SemaContext *context, Type *parent_type, Decl
other = sema_resolve_method(unit, parent, name, &ambiguous, &private); other = sema_resolve_method(unit, parent, name, &ambiguous, &private);
if (other) if (other)
{ {
if (unit->module->generic_module && other->unit->module->generic_module == unit->module->generic_module)
{
const char *module_name = unit->module->generic_module->name->module;
RETURN_SEMA_ERROR(method, "The same method is generated by multiple instances of '%s': '%s%s' and '%s%s'. "
"You need to use `@if` to restrict it to one of them, or move it out of the generic module entirely.",
module_name, module_name, unit->module->generic_suffix, module_name, other->unit->module->generic_suffix);
}
SEMA_ERROR(method, "This %s is already defined for '%s'.", SEMA_ERROR(method, "This %s is already defined for '%s'.",
method_name_by_decl(method), parent_type->name); method_name_by_decl(method), parent_type->name);
SEMA_NOTE(other, "The previous definition was here."); SEMA_NOTE(other, "The previous definition was here.");
@@ -4890,12 +4898,6 @@ Decl *sema_analyse_parameterized_identifier(SemaContext *c, Path *decl_path, con
ASSERT(alias); ASSERT(alias);
Module *module = alias->unit->module; Module *module = alias->unit->module;
if (c->unit->module->generic_module == module)
{
sema_error_at(c, span, "This identifier is recursively using %s.", module->name->module);
return poisoned_decl;
}
unsigned parameter_count = vec_size(module->parameters); unsigned parameter_count = vec_size(module->parameters);
ASSERT(parameter_count > 0); ASSERT(parameter_count > 0);
if (parameter_count != vec_size(params)) if (parameter_count != vec_size(params))

View File

@@ -246,6 +246,7 @@ static bool sema_resolve_type_identifier(SemaContext *context, TypeInfo *type_in
case DECL_TYPEDEF: case DECL_TYPEDEF:
if (!sema_analyse_decl(context, decl)) return type_info_poison(type_info); if (!sema_analyse_decl(context, decl)) return type_info_poison(type_info);
type_info->type = decl->type; type_info->type = decl->type;
assert (type_info->type->canonical->type_kind != TYPE_TYPEDEF);
type_info->resolve_status = RESOLVE_DONE; type_info->resolve_status = RESOLVE_DONE;
return true; return true;
case DECL_POISONED: case DECL_POISONED:
@@ -415,12 +416,13 @@ INLINE bool sema_resolve_generic_type(SemaContext *context, TypeInfo *type_info)
Decl *type = sema_analyse_parameterized_identifier(context, inner->unresolved.path, inner->unresolved.name, Decl *type = sema_analyse_parameterized_identifier(context, inner->unresolved.path, inner->unresolved.name,
inner->span, type_info->generic.params, &was_recursive); inner->span, type_info->generic.params, &was_recursive);
if (!decl_ok(type)) return false; if (!decl_ok(type)) return false;
if (!sema_analyse_decl(context, type)) return false;
type_info->type = type->type; type_info->type = type->type;
if (!was_recursive) return true; if (!was_recursive) return true;
if (!context->current_macro && (context->call_env.kind == CALL_ENV_FUNCTION || context->call_env.kind == CALL_ENV_FUNCTION_STATIC) if (!context->current_macro && (context->call_env.kind == CALL_ENV_FUNCTION || context->call_env.kind == CALL_ENV_FUNCTION_STATIC)
&& !context->call_env.current_function->func_decl.in_macro) && !context->call_env.current_function->func_decl.in_macro)
{ {
RETURN_SEMA_ERROR(type_info, "Recursively generic type declarations are only allowed inside of macros. Use `def` to define an alias for the type instead."); RETURN_SEMA_ERROR(type_info, "Recursively generic type declarations are only allowed inside of macros. Use `alias` to define an alias for the type instead.");
} }
return true; return true;
} }