diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index f53bda0ea8..558b450da9 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -527,16 +527,24 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode = result = newNodeI(nkBracket, n.info) result.typ = newTypeS(tyArray, c) rawAddSon(result.typ, nil) # index type + var + firstIndex, lastIndex: BiggestInt = 0 + indexType = getSysType(c.graph, n.info, tyInt) + lastValidIndex = lastOrd(c.config, indexType) if sonsLen(n) == 0: rawAddSon(result.typ, newTypeS(tyEmpty, c)) # needs an empty basetype! + lastIndex = -1 else: var x = n.sons[0] - var lastIndex: BiggestInt = 0 - var indexType = getSysType(c.graph, n.info, tyInt) if x.kind == nkExprColonExpr and sonsLen(x) == 2: var idx = semConstExpr(c, x.sons[0]) - lastIndex = getOrdValue(idx) + if not isOrdinalType(idx.typ): + localError(c.config, idx.info, "expected ordinal value for array " & + "index, got '$1'" % renderTree(idx)) + firstIndex = getOrdValue(idx) + lastIndex = firstIndex indexType = idx.typ + lastValidIndex = lastOrd(c.config, indexType) x = x.sons[1] let yy = semExprWithType(c, x) @@ -544,6 +552,12 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode = addSon(result, yy) #var typ = skipTypes(result.sons[0].typ, {tyGenericInst, tyVar, tyLent, tyOrdinal}) for i in 1 ..< sonsLen(n): + if lastIndex == lastValidIndex: + let validIndex = makeRangeType(c, firstIndex, lastValidIndex, n.info, + indexType) + localError(c.config, n.info, "size of array exceeds range of index " & + "type '$1' by $2 elements" % [typeToString(validIndex), $(n.len-i)]) + x = n.sons[i] if x.kind == nkExprColonExpr and sonsLen(x) == 2: var idx = semConstExpr(c, x.sons[0]) @@ -561,7 +575,8 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode = addSonSkipIntLit(result.typ, typ) for i in 0 ..< result.len: result.sons[i] = fitNode(c, typ, result.sons[i], result.sons[i].info) - result.typ.sons[0] = makeRangeType(c, 0, sonsLen(result) - 1, n.info) + result.typ.sons[0] = makeRangeType(c, firstIndex, lastIndex, n.info, + indexType) proc fixAbstractType(c: PContext, n: PNode) = for i in 1 ..< n.len: diff --git a/tests/array/tarray.nim b/tests/array/tarray.nim index b40c8757c5..6fa3050648 100644 --- a/tests/array/tarray.nim +++ b/tests/array/tarray.nim @@ -548,3 +548,12 @@ block t3899: x.a[i] const c = O(a: [1.0,2.0]) echo c[2] + +block arrayLiterals: + type ABC = enum A, B, C + template Idx[IdxT, ElemT](arr: array[IdxT, ElemT]): untyped = IdxT + doAssert [A: 0, B: 1].Idx is range[A..B] + doAssert [A: 0, 1, 3].Idx is ABC + doAssert [1: 2][1] == 2 + doAssert [-1'i8: 2][-1] == 2 + doAssert [-1'i8: 2, 3, 4, 5].Idx is range[-1'i8..2'i8] diff --git a/tests/array/tidx_lit_err1.nim b/tests/array/tidx_lit_err1.nim new file mode 100644 index 0000000000..b1823e5a31 --- /dev/null +++ b/tests/array/tidx_lit_err1.nim @@ -0,0 +1,6 @@ +discard """ + errormsg: "size of array exceeds range of index type 'range 1..2(Color)' by 3 elements" + line: 6 +""" +type Color = enum Red, Green, Blue +let y = [Green: 0, 1, 2, 3, 4] diff --git a/tests/array/tidx_lit_err2.nim b/tests/array/tidx_lit_err2.nim new file mode 100644 index 0000000000..75f5f227b2 --- /dev/null +++ b/tests/array/tidx_lit_err2.nim @@ -0,0 +1,5 @@ +discard """ + errormsg: "expected ordinal value for array index, got '\"string\"'" + line: 5 +""" +let x = ["string": 0, "index": 1] diff --git a/tests/array/tidx_lit_err3.nim b/tests/array/tidx_lit_err3.nim new file mode 100644 index 0000000000..95922bc504 --- /dev/null +++ b/tests/array/tidx_lit_err3.nim @@ -0,0 +1,5 @@ +discard """ + errormsg: "size of array exceeds range of index type 'range 2147483646..2147483647(int32)' by 1 elements" + line: 5 +""" +echo [high(int32)-1: 1, 2, 3]