Skip to content

parser: fix match-arm !/? propagation when a match is used as a block value (fix #28000) - #28002

Open
medvednikov wants to merge 1 commit into
masterfrom
fix-match-if-expr-propagation-28000
Open

parser: fix match-arm !/? propagation when a match is used as a block value (fix #28000)#28002
medvednikov wants to merge 1 commit into
masterfrom
fix-match-if-expr-propagation-28000

Conversation

@medvednikov

Copy link
Copy Markdown
Member

Fix #28000

A match whose arms use !/? error-propagation, when the match is used as the value of an if-expression (e.g. an if value := opt { … } else { … } option-guard assigned to a variable), emitted invalid C:

error: expected expression
    _t4 = ;

The if-expression's result temp was never assigned the propagated value.

Root cause

Parser.mark_last_call_return_as_used (vlib/v/parser/parser.v) is called for the last statement of an assignment-RHS block and recursively descends into if branches to flag the last call's return value as used (is_return_used = true). It had a case for IfExpr but no case for MatchExpr, so calls in match arms kept is_return_used == false.

In cgen (vlib/v/gen/c/fn.v), the branch that emits the unwrapped value of a propagated call (_t4 = (*(int*)_t5.data);) is guarded by node.is_return_used || is_gen_or_and_assign_rhs. With neither set, cgen wrote only _t4 = followed by nothing.

Fix

Add a MatchExpr case symmetric to the existing IfExpr one, marking the last statement of each match branch.

Reproduction (from the issue)

fn select_value(node ?Node) !int {
	result := if value := node {
		match value {
			First { lower_first(value)! }
			Second { lower_second(value)! }
		}
	} else {
		0
	}
	return result
}

Now compiles and runs correctly.

Tests

  • vlib/v/tests/match_as_if_expr_value_with_propagation_test.v — covers ! and ? propagation for a match inside an if-guard, as a direct return value, and assigned to a variable.
  • vlib/v3/tests/match_as_if_expr_value_propagation_codegen_test.v — the v3 backend already handled this case correctly; a regression test is added to keep it covered.

Existing vlib/v/compiler_errors_test.v (1617 checker snapshots) and the related match/option/result/or-block test suites pass unchanged.

…alue (fix #28000)

A `match` whose arms use `!`/`?` error-propagation, when the match is used
as the value of an if-expression (or directly as a block value), emitted
invalid C: the if-expression result temp was assigned an empty expression
(`_t4 = ;`), giving "expected expression".

`mark_last_call_return_as_used` recursively descended into `if` branches to
flag the last call's return value as used, but had no case for `match`, so
calls in match arms kept `is_return_used == false`. cgen then skipped
emitting the unwrapped propagated value.

Add a `MatchExpr` case symmetric to the existing `IfExpr` one, marking the
last statement of each match branch. The v3 backend already handled this
case; a regression test is added there too.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@medvednikov

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cgen: match with !-propagating arms used as an if-expression value emits _t4 = ; (expected expression)

1 participant