From 13efcad6cbb4d0befb3c464e0edef18d6623aa8f Mon Sep 17 00:00:00 2001 From: Swastik Baranwal Date: Mon, 27 Oct 2025 12:55:47 +0530 Subject: [PATCH] parser,checker: smart detect `or {}` inside loop when using `c <-val` (fix #24550) (#25435) --- vlib/v/checker/checker.v | 8 +++++ vlib/v/parser/expr.v | 11 +++++++ .../inout/for_channel_or_expr_block.out | 1 + .../inout/for_channel_or_expr_block.vv | 31 +++++++++++++++++++ 4 files changed, 51 insertions(+) create mode 100644 vlib/v/slow_tests/inout/for_channel_or_expr_block.out create mode 100644 vlib/v/slow_tests/inout/for_channel_or_expr_block.vv diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 38f632320..a6b446460 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2339,6 +2339,14 @@ fn (mut c Checker) stmt(mut node ast.Stmt) { c.error('unused expression', node.pos) } } + if node.expr.op == .arrow { + if mut node.expr.right is ast.CallExpr { + if node.expr.right.return_type.has_flag(.result) { + node.expr.or_block.err_used = node.expr.or_block.scope.known_var('err') + node.expr.right.or_block = node.expr.or_block + } + } + } } } if !c.inside_return { diff --git a/vlib/v/parser/expr.v b/vlib/v/parser/expr.v index d6bb02c01..a82aacdd3 100644 --- a/vlib/v/parser/expr.v +++ b/vlib/v/parser/expr.v @@ -827,6 +827,17 @@ fn (mut p Parser) infix_expr(left ast.Expr) ast.Expr { mut or_scope := &ast.Scope(unsafe { nil }) // allow `x := <-ch or {...}` to handle closed channel if op == .arrow { + if mut right is ast.SelectorExpr { + or_kind = right.or_block.kind + or_stmts = right.or_block.stmts.clone() + right.or_block = ast.OrExpr{} + } + if mut right is ast.CallExpr { + or_kind = right.or_block.kind + or_stmts = right.or_block.stmts.clone() + or_scope = right.or_block.scope + right.or_block = ast.OrExpr{} + } if p.tok.kind == .key_orelse { or_kind = .block or_stmts, or_pos, or_scope = p.or_block(.with_err_var) diff --git a/vlib/v/slow_tests/inout/for_channel_or_expr_block.out b/vlib/v/slow_tests/inout/for_channel_or_expr_block.out new file mode 100644 index 000000000..5feb36d0a --- /dev/null +++ b/vlib/v/slow_tests/inout/for_channel_or_expr_block.out @@ -0,0 +1 @@ +[vlib/v/slow_tests/inout/for_channel_or_expr_block.vv:22] a.any(it in [i64(1), 2, 3, 4, 5, 6, 7]): true diff --git a/vlib/v/slow_tests/inout/for_channel_or_expr_block.vv b/vlib/v/slow_tests/inout/for_channel_or_expr_block.vv new file mode 100644 index 000000000..0b48302ee --- /dev/null +++ b/vlib/v/slow_tests/inout/for_channel_or_expr_block.vv @@ -0,0 +1,31 @@ +import time + +fn writer(c chan i64, delay i64) { + for { + time.sleep(delay) + + c <- time.now().day_of_week() or { + break + } + } +} + +fn reader(c chan i64, max int) { + mut a := []i64{} + for { + a << <-c + if a.len > max { + c.close() + break + } + } + dump(a.any(it in [i64(1), 2, 3, 4, 5, 6, 7])) +} + +fn main() { + c := chan i64{} + mut t := []thread{} + t << spawn reader(c, 0) + t << spawn writer(c, 10 * time.millisecond) + t.wait() +} -- 2.39.5