Skip to content

Commit

Permalink
remove repeated logic and add test for range based case
Browse files Browse the repository at this point in the history
  • Loading branch information
saem committed Sep 13, 2024
1 parent de0e34d commit b887f42
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 17 deletions.
14 changes: 5 additions & 9 deletions compiler/ast/ast_query.nim
Original file line number Diff line number Diff line change
Expand Up @@ -711,19 +711,15 @@ proc endsInNoReturn*(n: PNode): bool =
result = endsInNoReturn(n[i])
if not result:
break
# xxx: this duplicates logic in `semstmts.semCase`, this should eventually
# be combined
let
caseType = n[0].typ.skipTypes(abstractInst - {tyTypeDesc})
caseType = n[0].typ.skipTypes(abstractRange)
requiresElse =
case caseType.kind
of tyCaseExhaustive:
false
of tyRange:
not (caseType[0].skipTypes(abstractInst).kind in tyCaseExhaustive)
else:
of tyFloat..tyFloat64, tyString:
true
result = result and (not requiresElse or n[^1].kind == nkElse)
else:
false
result = result and (n[^1].kind == nkElse or not requiresElse)
of nkTryStmt:
# ignore the 'finally' -- it doesn't contribute to the type
for i in 0..<(n.len - ord(n[^1].kind == nkFinally)):
Expand Down
4 changes: 0 additions & 4 deletions compiler/ast/ast_types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -593,10 +593,6 @@ const
## type-bound operations are attached to. User type-classes are also
## unconditionally included in this set

tyCaseExhaustive* = {tyInt..tyInt64, tyChar, tyEnum, tyUInt..tyUInt64,
tyBool}
## types that need exhaustiveness checking for case statement selectors

type
TTypeKinds* = set[TTypeKind]

Expand Down
7 changes: 3 additions & 4 deletions compiler/sem/semstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1641,14 +1641,13 @@ proc semCase(c: PContext, n: PNode; flags: TExprFlags): PNode =
var covered: Int128 = toInt128(0)
var typ = commonTypeBegin
var hasElse = false
# xxx: the exhaustiveness logic is duplicated in `ast_query.endsInNoReturn`,
# this should eventually be combined.
let caseTyp = skipTypes(selector, abstractInst-{tyTypeDesc})
const shouldChckCovered = {tyInt..tyInt64, tyChar, tyEnum, tyUInt..tyUInt64, tyBool}
case caseTyp.kind
of tyCaseExhaustive:
of shouldChckCovered:
chckCovered = true
of tyRange:
if skipTypes(caseTyp[0], abstractInst).kind in tyCaseExhaustive:
if skipTypes(caseTyp[0], abstractInst).kind in shouldChckCovered:
chckCovered = true
of tyFloat..tyFloat64, tyString:
discard "not all possible values have to be covered"
Expand Down
11 changes: 11 additions & 0 deletions tests/lang_exprs/tnoreturn_nested.nim
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,17 @@ block nested_in_case:

doAssert x is int

block nested_in_case_range:
type Foo = range[1..1]
let x =
if true:
0
else:
let y: Foo = 1
case y
of 1:
raise newException(CatchableError, "error")

block nested_in_block:
let x =
if true:
Expand Down

0 comments on commit b887f42

Please sign in to comment.