From 0fc1871ddfafcd6e4edf8f1d7c09e8d733f28ea5 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Wed, 7 Jan 2026 15:53:54 +0100 Subject: [PATCH] - Assert on optional-returning-function in a comma expression. #2722 --- releasenotes.md | 1 + src/compiler/llvm_codegen_stmt.c | 3 +-- src/compiler/llvm_codegen_value.c | 4 ++++ src/compiler/sema_stmts.c | 4 +++- test/test_suite/errors/discard_in_cond_valid.c3t | 8 ++++++++ test/test_suite/errors/optional_discard_in_cond.c3 | 8 ++++++++ test/test_suite/errors/try_with_chained_unwrap_errors.c3 | 2 +- 7 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 test/test_suite/errors/discard_in_cond_valid.c3t create mode 100644 test/test_suite/errors/optional_discard_in_cond.c3 diff --git a/releasenotes.md b/releasenotes.md index ab457c85a..083358b96 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -52,6 +52,7 @@ - `io::read_fully` now handles unbounded streams properly. - Crash when doing a type property lookup for const inline enums in some cases #2717. - Incorrect alignment on typedef and local variable debug info. +- Assert on optional-returning-function in a comma expression. #2722 ### 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/llvm_codegen_stmt.c b/src/compiler/llvm_codegen_stmt.c index a6323cdb6..4af1364fc 100644 --- a/src/compiler/llvm_codegen_stmt.c +++ b/src/compiler/llvm_codegen_stmt.c @@ -197,8 +197,7 @@ static void llvm_emit_cond(GenContext *c, BEValue *be_value, Expr *expr, bool bo ByteSize last_index = size - 1; for (ByteSize i = 0; i < last_index; i++) { - BEValue value; - llvm_emit_expr(c, &value, expr->cond_expr[i]); + llvm_emit_ignored_expr(c, expr->cond_expr[i]); } // Emit the last element. diff --git a/src/compiler/llvm_codegen_value.c b/src/compiler/llvm_codegen_value.c index 7035b11d9..9ffb8e884 100644 --- a/src/compiler/llvm_codegen_value.c +++ b/src/compiler/llvm_codegen_value.c @@ -129,6 +129,10 @@ void llvm_value_rvalue(GenContext *c, BEValue *value) void llvm_emit_jump_to_optional_exit(GenContext *c, LLVMValueRef opt_value) { + if (!c->catch.block) + { + puts("foekf"); + } ASSERT_AT(c->last_emitted_loc, c->catch.block && "unexpected emit"); bool is_constant_opt = llvm_is_const(opt_value); diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index 61651d8ed..d0a9ccca9 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -1121,7 +1121,9 @@ static inline bool sema_analyse_cond_list(SemaContext *context, Expr *expr, Cond // 2. Walk through each of our declarations / expressions as if they were regular expressions. for (unsigned i = 0; i < entries - 1; i++) { - if (!sema_analyse_expr_rvalue(context, dexprs[i])) return false; + Expr *dexpr = dexprs[i]; + if (!sema_analyse_expr_rvalue(context, dexpr)) return false; + if (!sema_expr_check_discard(context, dexpr)) return false; } if (!sema_analyse_last_cond(context, dexprs[entries - 1], cond_type, result)) return false; diff --git a/test/test_suite/errors/discard_in_cond_valid.c3t b/test/test_suite/errors/discard_in_cond_valid.c3t new file mode 100644 index 000000000..3e11925d2 --- /dev/null +++ b/test/test_suite/errors/discard_in_cond_valid.c3t @@ -0,0 +1,8 @@ +module main; + +fn int? may_fault() @maydiscard => 2; + +fn void main() +{ + if (may_fault(), true); +} \ No newline at end of file diff --git a/test/test_suite/errors/optional_discard_in_cond.c3 b/test/test_suite/errors/optional_discard_in_cond.c3 new file mode 100644 index 000000000..433dd3a03 --- /dev/null +++ b/test/test_suite/errors/optional_discard_in_cond.c3 @@ -0,0 +1,8 @@ +module main; + +fn int? may_fault() => 2; + +fn void main() +{ + if (may_fault(), true); // #error: You can either assign it to a variable +} diff --git a/test/test_suite/errors/try_with_chained_unwrap_errors.c3 b/test/test_suite/errors/try_with_chained_unwrap_errors.c3 index 4265d5f53..c21847db3 100644 --- a/test/test_suite/errors/try_with_chained_unwrap_errors.c3 +++ b/test/test_suite/errors/try_with_chained_unwrap_errors.c3 @@ -59,7 +59,7 @@ fn void test8() { int? a; int e; - if (e == 0, try c = a && try d = a && e > 0) {} + if (e = 3, try c = a && try d = a && e > 0) {} if (try b = a && try c = a && e > 0) {} if (try c = a && try d = a) { c++; } }