From d783cda67187df23d3458a7a884bb56670ad2556 Mon Sep 17 00:00:00 2001 From: shove Date: Mon, 15 Jan 2024 21:04:30 +0800 Subject: [PATCH] cgen: fix code generation wrong, when '?foo.array or {}' as a 'for-in' condition (fix #20528) (#20542) --- vlib/v/gen/c/for.v | 2 +- vlib/v/tests/for_in_option_test.v | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/vlib/v/gen/c/for.v b/vlib/v/gen/c/for.v index fc6b800379..0b31998259 100644 --- a/vlib/v/gen/c/for.v +++ b/vlib/v/gen/c/for.v @@ -235,7 +235,7 @@ fn (mut g Gen) for_in_stmt(node_ ast.ForInStmt) { } mut cond_var := '' if (node.cond is ast.Ident && !node.cond_type.has_flag(.option)) - || node.cond is ast.SelectorExpr { + || (node.cond is ast.SelectorExpr && node.cond.or_block.kind == .absent) { cond_var = g.expr_string(node.cond) } else { cond_var = g.new_tmp_var() diff --git a/vlib/v/tests/for_in_option_test.v b/vlib/v/tests/for_in_option_test.v index ff00a82130..bddf72aa73 100644 --- a/vlib/v/tests/for_in_option_test.v +++ b/vlib/v/tests/for_in_option_test.v @@ -6,3 +6,23 @@ fn test_for_in_option() { } assert true } + +// for issue 20528 +// phenomenon: when the cond expr is SelectorExpr and the type is an array, cgen fails. +struct Foo { + data ?[]int +} + +fn (f Foo) get_first() ?int { + for d in f.data or { return none } { + return d + } + return none +} + +fn test_cond_is_selector_array_and_with_or_block() { + foo := Foo{ + data: [1, 2, 3] + } + assert foo.get_first()? == 1 +}