Skip to content

Commit

Permalink
evaluate all hidden conversions in case branches (#24187)
Browse files Browse the repository at this point in the history
fixes #11422, refs #8336/#8333, refs #20130

The compiler generates conversion nodes *after* evaluating the branches
of case statements as constants, the reasoning is that case branches
accept constants of different types, like arrays or sets. But this means
that conversion nodes that need to be evaluated like converter calls
don't get evaluated as a constant for codegen. #8336 fixed this by
re-evaluating the node if an `nkHiddenCallConv` was created, and in
#20130 this logic also had to be added for `nkHiddenStdConv` for
cstrings. This logic was only for single case elements, it has now been
added to range elements as well to fix #11422. Additionally, all
conversion nodes are now evaluated for simplicity, but maybe this won't
pass CI.
  • Loading branch information
metagn authored Sep 27, 2024
1 parent 7cccf36 commit 56a3dd5
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 5 deletions.
15 changes: 10 additions & 5 deletions compiler/semtypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -586,9 +586,14 @@ proc semBranchRange(c: PContext, n, a, b: PNode, covered: var Int128): PNode =
let bc = semConstExpr(c, b)
if ac.kind in {nkStrLit..nkTripleStrLit} or bc.kind in {nkStrLit..nkTripleStrLit}:
localError(c.config, b.info, "range of string is invalid")
let at = fitNode(c, n[0].typ, ac, ac.info).skipConvTakeType
let bt = fitNode(c, n[0].typ, bc, bc.info).skipConvTakeType

var at = fitNode(c, n[0].typ, ac, ac.info).skipConvTakeType
var bt = fitNode(c, n[0].typ, bc, bc.info).skipConvTakeType
# the calls to fitNode may introduce calls to converters
# mirrored with semCaseBranch for single elements
if at.kind in {nkHiddenCallConv, nkHiddenStdConv, nkHiddenSubConv}:
at = semConstExpr(c, at)
if bt.kind in {nkHiddenCallConv, nkHiddenStdConv, nkHiddenSubConv}:
bt = semConstExpr(c, bt)
result = newNodeI(nkRange, a.info)
result.add(at)
result.add(bt)
Expand Down Expand Up @@ -636,8 +641,8 @@ proc semCaseBranch(c: PContext, n, branch: PNode, branchIndex: int,
checkMinSonsLen(n, 1, c.config)
var tmp = fitNode(c, n[0].typ, r, r.info)
# the call to fitNode may introduce a call to a converter
if tmp.kind == nkHiddenCallConv or
(tmp.kind == nkHiddenStdConv and n[0].typ.kind == tyCstring):
# mirrored with semBranchRange
if tmp.kind in {nkHiddenCallConv, nkHiddenStdConv, nkHiddenSubConv}:
tmp = semConstExpr(c, tmp)
branch[i] = skipConv(tmp)
inc(covered)
Expand Down
5 changes: 5 additions & 0 deletions tests/casestmt/tcasestmt.nim
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ block t8333:
case 0
of 'a': echo 0
else: echo 1
block: # issue #11422
var c: int = 5
case c
of 'a' .. 'c': discard
else: discard


block emptyset_when:
Expand Down

0 comments on commit 56a3dd5

Please sign in to comment.