From b887f42a955f020c28582d10faf83343c9553526 Mon Sep 17 00:00:00 2001 From: saem Date: Thu, 12 Sep 2024 17:00:44 -0700 Subject: [PATCH] remove repeated logic and add test for range based case --- compiler/ast/ast_query.nim | 14 +++++--------- compiler/ast/ast_types.nim | 4 ---- compiler/sem/semstmts.nim | 7 +++---- tests/lang_exprs/tnoreturn_nested.nim | 11 +++++++++++ 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/compiler/ast/ast_query.nim b/compiler/ast/ast_query.nim index e08bb06b4cd..241bd1a9eb3 100644 --- a/compiler/ast/ast_query.nim +++ b/compiler/ast/ast_query.nim @@ -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)): diff --git a/compiler/ast/ast_types.nim b/compiler/ast/ast_types.nim index 58a48c5ff9d..ff49afbb6a1 100644 --- a/compiler/ast/ast_types.nim +++ b/compiler/ast/ast_types.nim @@ -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] diff --git a/compiler/sem/semstmts.nim b/compiler/sem/semstmts.nim index ddcee370d29..2f51a410fce 100644 --- a/compiler/sem/semstmts.nim +++ b/compiler/sem/semstmts.nim @@ -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" diff --git a/tests/lang_exprs/tnoreturn_nested.nim b/tests/lang_exprs/tnoreturn_nested.nim index 786ee54d31a..19481a0f1a7 100644 --- a/tests/lang_exprs/tnoreturn_nested.nim +++ b/tests/lang_exprs/tnoreturn_nested.nim @@ -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: