mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-19 22:10:33 +00:00
Improve semchecking for duplicate cases in case statements (#7176)
* Improve semchecking for duplicate cases in case statements * Revert to previous solution * Improve test
This commit is contained in:
committed by
Andreas Rumpf
parent
ba6e11fc88
commit
e4515f304a
@@ -151,6 +151,11 @@ proc complement*(a: PNode): PNode =
|
||||
for i in countup(0, high(x)): x[i] = not x[i]
|
||||
result = toTreeSet(x, a.typ, a.info)
|
||||
|
||||
proc deduplicate*(a: PNode): PNode =
|
||||
var x: TBitSet
|
||||
toBitSet(a, x)
|
||||
result = toTreeSet(x, a.typ, a.info)
|
||||
|
||||
proc cardSet(s: PNode): BiggestInt =
|
||||
# here we can do better than converting it into a compact set
|
||||
# we just count the elements directly
|
||||
|
||||
@@ -497,8 +497,8 @@ proc semCaseBranchSetElem(c: PContext, t, b: PNode,
|
||||
|
||||
proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
|
||||
covered: var BiggestInt) =
|
||||
|
||||
for i in countup(0, sonsLen(branch) - 2):
|
||||
let lastIndex = sonsLen(branch) - 2
|
||||
for i in 0..lastIndex:
|
||||
var b = branch.sons[i]
|
||||
if b.kind == nkRange:
|
||||
branch.sons[i] = b
|
||||
@@ -516,14 +516,21 @@ proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
|
||||
branch.sons[i] = skipConv(fitNode(c, t.sons[0].typ, r, r.info))
|
||||
inc(covered)
|
||||
else:
|
||||
if r.kind == nkCurly:
|
||||
r = r.deduplicate
|
||||
|
||||
# first element is special and will overwrite: branch.sons[i]:
|
||||
branch.sons[i] = semCaseBranchSetElem(c, t, r[0], covered)
|
||||
|
||||
# other elements have to be added to ``branch``
|
||||
for j in 1 ..< r.len:
|
||||
branch.add(semCaseBranchSetElem(c, t, r[j], covered))
|
||||
# caution! last son of branch must be the actions to execute:
|
||||
var L = branch.len
|
||||
swap(branch.sons[L-2], branch.sons[L-1])
|
||||
swap(branch.sons[^2], branch.sons[^1])
|
||||
checkForOverlap(c, t, i, branchIndex)
|
||||
|
||||
# Elements added above needs to be checked for overlaps.
|
||||
for i in lastIndex.succ..(sonsLen(branch) - 2):
|
||||
checkForOverlap(c, t, i, branchIndex)
|
||||
|
||||
proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||
|
||||
50
tests/casestmt/tduplicates.nim
Normal file
50
tests/casestmt/tduplicates.nim
Normal file
@@ -0,0 +1,50 @@
|
||||
discard """
|
||||
output: '''
|
||||
OK
|
||||
OK
|
||||
OK
|
||||
'''
|
||||
"""
|
||||
|
||||
type Kind = enum A, B
|
||||
var k = A
|
||||
|
||||
template reject(b) =
|
||||
static: doAssert(not compiles(b))
|
||||
|
||||
reject:
|
||||
var i = 2
|
||||
case i
|
||||
of [1, 1]: discard
|
||||
else: discard
|
||||
|
||||
reject:
|
||||
var i = 2
|
||||
case i
|
||||
of 1, { 1..2 }: discard
|
||||
else: discard
|
||||
|
||||
reject:
|
||||
var i = 2
|
||||
case i
|
||||
of { 1, 1 }: discard
|
||||
of { 1, 1 }: discard
|
||||
else: discard
|
||||
|
||||
reject:
|
||||
case k
|
||||
of [A, A]: discard
|
||||
|
||||
var i = 2
|
||||
case i
|
||||
of { 1, 1 }: discard
|
||||
of { 2, 2 }: echo "OK"
|
||||
else: discard
|
||||
|
||||
case i
|
||||
of { 10..30, 15..25, 5..15, 25..35 }: discard
|
||||
else: echo "OK"
|
||||
|
||||
case k
|
||||
of {A, A..A}: echo "OK"
|
||||
of B: discard
|
||||
Reference in New Issue
Block a user