Fix Using @if with methods with generic params only inferred from the parent type fails #2770

This commit is contained in:
Christoffer Lerno
2026-01-20 01:04:12 +01:00
parent 0b9b49673e
commit e84e23f7ec
4 changed files with 54 additions and 0 deletions

View File

@@ -2567,6 +2567,7 @@ Decl *sema_find_label_symbol_anywhere(SemaContext *context, const char *symbol);
Decl *sema_find_local(SemaContext *context, const char *symbol);
Decl *sema_resolve_symbol(SemaContext *context, const char *symbol, Path *path, SourceSpan span);
Decl *sema_resolve_parameterized_symbol(SemaContext *context, const char *symbol, Path *path, SourceSpan span);
Decl *sema_resolve_maybe_parameterized_symbol(SemaContext *context, const char *symbol, Path *path, SourceSpan span);
BoolErr sema_symbol_is_defined_in_scope(SemaContext *c, const char *symbol);
bool sema_resolve_array_like_len(SemaContext *context, TypeInfo *type_info, ArraySize *len_ref);

View File

@@ -1190,6 +1190,21 @@ Decl *sema_resolve_parameterized_symbol(SemaContext *context, const char *symbol
return resolve.found;
}
Decl *sema_resolve_maybe_parameterized_symbol(SemaContext *context, const char *symbol, Path *path, SourceSpan span)
{
NameResolve resolve = {
.path = path,
.span = span,
.symbol = symbol,
.is_parameterized = true,
.suppress_error = true
};
if (!sema_resolve_symbol_common(context, &resolve)) return NULL;
Decl *found = resolve.found;
if (!decl_ok(found)) return NULL;
return resolve.found;
}
bool sema_parameterized_type_is_found(SemaContext *context, Path *decl_path, const char *name, SourceSpan span)
{
NameResolve name_resolve = {

View File

@@ -163,11 +163,38 @@ FOUND_ALIAS:
DEBUG_LOG("Pass finished processing %d import(s) with %d error(s).", total_import_count, compiler.context.errors_found);
}
static bool sema_check_if_implicit_generic(SemaContext *context, Decl *decl)
{
if (!decl->func_decl.type_parent) return false;
TypeInfo *typedecl = type_infoptr(decl->func_decl.type_parent);
Decl *d = NULL;
if (typedecl->resolve_status == RESOLVE_DONE)
{
CanonicalType *type = typedecl->type->canonical;
if (!type_is_user_defined(type)) return false;
d = type->decl;
}
else if (typedecl->kind == TYPE_INFO_IDENTIFIER && typedecl->subtype == TYPE_COMPRESSED_NONE)
{
d = sema_resolve_maybe_parameterized_symbol(context, typedecl->unresolved.name, typedecl->unresolved.path, typedecl->span);
}
return d && d->is_template;
}
void unit_register_optional_global_decl(CompilationUnit *unit, Decl *decl)
{
SemaContext context;
sema_context_init(&context, unit);
if (decl->is_templated) context.generic_instance = declptr(decl->instance_id);
if (!decl->is_templated && (decl->decl_kind == DECL_MACRO || decl->decl_kind == DECL_FUNC))
{
if (sema_check_if_implicit_generic(&context, decl))
{
unit_register_global_decl(unit, decl);
sema_context_destroy(&context);
return;
}
}
if (sema_decl_if_cond(&context, decl))
{
unit_register_global_decl(unit, decl);

View File

@@ -0,0 +1,11 @@
import std;
struct Foo <Type> { int a; }
fn void Foo.test(self) @if(Type.sizeof > 4)
{ }
fn int main()
{
Foo{int} x;
return 0;
}