diff --git a/releasenotes.md b/releasenotes.md index 1847e46eb..13501fc96 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -20,6 +20,7 @@ - Compiler assert when getting a member of a `bitstruct : char @bigendian` #2517. - Add ??? and +++= to list-precedence. - Fix issues with linking when using symbol aliases. #2519 +- Splatting optional compile-time macro parameter from inside lambda expression does not work #2532. ### Stdlib changes - Sorting functions correctly took slices by value, but also other types by value. Now, only slices are accepted by value, other containers are always by ref. diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 8c97c9a5a..1c185cc38 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -1778,9 +1778,9 @@ static inline ArrayIndex sema_len_from_expr(Expr *expr) return range_const_len(&expr->slice_expr.range); } -static Decl *sema_find_splat_arg(Decl *macro, const char *name) +static Decl *sema_find_splat_arg(Decl **params, const char *name) { - FOREACH(Decl *, decl, macro->func_decl.signature.params) + FOREACH(Decl *, decl, params) { if (decl && decl->name == name) return decl; } @@ -1797,19 +1797,31 @@ typedef enum static SplatResult sema_splat_optional_argument(SemaContext *context, Expr *expr) { Decl *macro = context->current_macro; - if (!macro) return SPLAT_NONE; + Decl **macro_params; + if (macro) + { + macro_params = macro->func_decl.signature.params; + } + else + { + if (context->call_env.kind != CALL_ENV_FUNCTION || !context->call_env.current_function->func_decl.in_macro) + { + return SPLAT_NONE; + } + macro_params = context->call_env.current_function->func_decl.lambda_ct_parameters; + } Decl *candidate = NULL; switch (expr->expr_kind) { case EXPR_UNRESOLVED_IDENTIFIER: if (expr->unresolved_ident_expr.path) break; - candidate = sema_find_splat_arg(macro, expr->unresolved_ident_expr.ident); + candidate = sema_find_splat_arg(macro_params, expr->unresolved_ident_expr.ident); break; case EXPR_HASH_IDENT: - candidate = sema_find_splat_arg(macro, expr->hash_ident_expr.identifier); + candidate = sema_find_splat_arg(macro_params, expr->hash_ident_expr.identifier); break; case EXPR_CT_IDENT: - candidate = sema_find_splat_arg(macro, expr->ct_ident_expr.identifier); + candidate = sema_find_splat_arg(macro_params, expr->ct_ident_expr.identifier); break; default: return SPLAT_NONE; diff --git a/test/test_suite/lambda/lambda_splat_macro.c3t b/test/test_suite/lambda/lambda_splat_macro.c3t new file mode 100644 index 000000000..d9366d5c6 --- /dev/null +++ b/test/test_suite/lambda/lambda_splat_macro.c3t @@ -0,0 +1,31 @@ +// #target: macos-x64 +module test; +import std; +fn int main() +{ + bool x = test1a(true)(); + return 0; +} + +macro test1a(bool $a = ...) => fn bool() +{ + return test1b(...$a); +}; +macro test1b(bool $a = ...) => $defined($a) ??? $a : false; + + +/* #expect: test.ll + +define i32 @main() #0 { +entry: + %x = alloca i8, align 1 + %0 = call i8 @"test.test1a$lambda1"() + store i8 %0, ptr %x, align 1 + ret i32 0 +} + +define internal zeroext i8 @"test.test1a$lambda1"() #0 { +entry: + ret i8 1 +} +