Skip to content

Commit

Permalink
fix(sem): noreturn analysis for void exprs
Browse files Browse the repository at this point in the history
Summary
=======

`void` branches preceeding with no-return terminal branches are checked
with no-return analysis to avoid false positives.

Details
=====

The analysis is updated to recursively check `if/elif/of/except`
non-terminal branches as well as the terminal branch.
  • Loading branch information
saem committed Sep 10, 2024
1 parent 677964c commit 483afac
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 11 deletions.
23 changes: 12 additions & 11 deletions compiler/ast/ast_query.nim
Original file line number Diff line number Diff line change
Expand Up @@ -695,22 +695,23 @@ proc endsInNoReturn*(n: PNode): bool =
## etc.) or a call of a noreturn proc. This is meant to be called on a
## semmed `n`.
var it = n
while it.kind in {nkStmtList, nkStmtListExpr} and it.len > 0 or
while it.kind in {nkStmtList, nkStmtListExpr, nkElifBranch, nkElse, nkOfBranch, nkExceptBranch} and it.len > 0 or
it.kind in {nkIfStmt, nkCaseStmt, nkBlockStmt, nkTryStmt} and it.typ.isEmptyType:
case it.kind
of nkStmtList, nkStmtListExpr, nkBlockStmt:
of nkStmtList, nkStmtListExpr, nkBlockStmt, nkOfBranch, nkElifBranch, nkElse, nkExceptBranch:
it = it.lastSon
of nkIfStmt, nkCaseStmt:
it = it.lastSon.lastSon
# look through all but the last branch, which is covered after the loop
for i in 0..<(it.len - 1):
if not endsInNoReturn(it[i]):
return false
it = it.lastSon
of nkTryStmt:
it =
case it[^1].kind
of nkFinally:
it[^2]
of nkExceptBranch:
it[^1]
of nkAllNodeKinds - {nkFinally, nkExceptBranch}:
unreachable()
# look through all but the last branch, which is covered after the loop
for i in 0..<(it.len - ord(it[^1].kind == nkFinally)):
if not endsInNoReturn(it[i]):
return false
it = it.lastSon
else:
unreachable()
result = it.kind in nkLastBlockStmts or
Expand Down
16 changes: 16 additions & 0 deletions tests/lang_exprs/tnoreturn_nested_reject_void.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
discard """
description: '''
Ensure nested non-noreturn statements aren't treated as such
'''
errormsg: "expression '1' is of type 'int literal(1)' and has to be used (or discarded)"
line: 11
"""

let x =
if true:
1
else:
if true:
echo "fun" # void
else:
raise newException(Defect, "gone") # no return

0 comments on commit 483afac

Please sign in to comment.