diff --git a/compiler/nimsets.nim b/compiler/nimsets.nim index 94507adf0..bda753e85 100644 --- a/compiler/nimsets.nim +++ b/compiler/nimsets.nim @@ -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 diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index df274c7db..50c2e287e 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -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, diff --git a/tests/casestmt/tduplicates.nim b/tests/casestmt/tduplicates.nim new file mode 100644 index 000000000..f9fc1cc26 --- /dev/null +++ b/tests/casestmt/tduplicates.nim @@ -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 \ No newline at end of file