From e257500e034ae9fad18b92642ba52adef21d3d83 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Thu, 22 Jan 2026 19:16:54 +0100 Subject: [PATCH] Recursive definition of tag not detected with nested tag/tagof #2790 --- releasenotes.md | 1 + src/compiler/sema_expr.c | 3 ++- test/test_suite/compile_time_introspection/recursive_tag2.c3 | 4 ++++ 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 test/test_suite/compile_time_introspection/recursive_tag2.c3 diff --git a/releasenotes.md b/releasenotes.md index 067c15905..a397ae3fd 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -104,6 +104,7 @@ - Using an optional type as generic parameter was not properly caught #2799 - Instantiating an alias of a user-defined type was not properly caught #2798 - Too deeply nested scopes was a fatal crash and not a regular semantic error. #2796 +- Recursive definition of tag not detected with nested tag/tagof #2790 ### Stdlib changes - Add `ThreadPool` join function to wait for all threads to finish in the pool without destroying the threads. diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 2c05647a1..bd97830b7 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -3604,6 +3604,8 @@ static inline bool sema_expr_analyse_typecall(SemaContext *context, Expr *expr) { Expr *tag = exprptr(expr->call_expr.function); expr->call_expr.arguments = sema_expand_vasplat_exprs(context, expr->call_expr.arguments); + Decl *decl = tag->type_call_expr.type; + if (decl && !sema_analyse_decl(context, decl)) return false; switch (tag->type_call_expr.property) { case TYPE_PROPERTY_FROM_ORDINAL: @@ -3626,7 +3628,6 @@ static inline bool sema_expr_analyse_typecall(SemaContext *context, Expr *expr) { RETURN_SEMA_ERROR(key, "The tag name should be a string constant."); } - Decl *decl = tag->type_call_expr.type; const char *tagname = key->const_expr.bytes.ptr; if (!decl) goto NOT_FOUND; ASSERT_SPAN(expr, decl->resolved_attributes); diff --git a/test/test_suite/compile_time_introspection/recursive_tag2.c3 b/test/test_suite/compile_time_introspection/recursive_tag2.c3 new file mode 100644 index 000000000..d8e8fa97d --- /dev/null +++ b/test/test_suite/compile_time_introspection/recursive_tag2.c3 @@ -0,0 +1,4 @@ +struct Foo @tag("", Foo.tagof("")) // #error: Recursive definition of 'Foo'. +{ +} +fn int main() => 1; \ No newline at end of file