mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Allow recursive generic modules.
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user