From 587f90a81678508c1a20469dad1a9ea842590b40 Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Sat, 13 Jun 2026 16:17:59 +0800 Subject: [PATCH] fixes #22122; Unclear error message for raise of a complex expression (#25899) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixes #22122 The commit fixes a bug in Nim's effects checker where raise statements with case/if expressions (commonly from template expansion) failed to track exception types from individual branches. Problem: addRaiseEffect only saw the outermost expression. When a template like getTransportError(err) expanded to a case expression raising 3 different exception types, the compiler only registered the top-level call — missing the branch-level exceptions. Fix (2 files): - compiler/sempass2.nim: Added skipHiddenConv to strip implicit type coercion nodes (nkHiddenStdConv/nkHiddenSubConv) that hide the control flow structure. Added addRaiseEffectsFromExpr that recursively walks into case/if/block/stmtlist expressions to find raise effects in each branch body. Changed the nkRaiseStmt handler to use this new function. - tests/effects/tcase_raises.nim: Test with templates that expand to case expressions raising different exception types, verified via {.raises: [].} pragma. --- compiler/sempass2.nim | 29 ++++++++++++- tests/effects/tcase_raises.nim | 74 ++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 tests/effects/tcase_raises.nim diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 7b2be510f9..0d32930472 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -497,6 +497,33 @@ proc addRaiseEffect(a: PEffects, e, comesFrom: PNode) = if not isDefectException(e.typ): throws(a.exc, e, comesFrom) +proc skipHiddenConv(n: PNode): PNode = + result = n + while true: + case result.kind + of nkHiddenStdConv, nkHiddenSubConv: + result = result[1] + else: break + +proc addRaiseEffectsFromExpr(a: PEffects, e, comesFrom: PNode) = + if e.isNil: + return + case e.kind + of nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr: + if e.len > 0: + addRaiseEffectsFromExpr(a, e.lastSon.skipHiddenConv, comesFrom) + of nkIfExpr, nkIfStmt: + for branch in items(e): + if branch.len > 0: + addRaiseEffectsFromExpr(a, branch.lastSon.skipHiddenConv, comesFrom) + of nkCaseStmt: + for i in 1.. 0: + addRaiseEffectsFromExpr(a, branch.lastSon.skipHiddenConv, comesFrom) + else: + addRaiseEffect(a, e, comesFrom) + proc addTag(a: PEffects, e, comesFrom: PNode) = var aa = a.tags for i in 0..