Two arrays of the same size and element type but with different index boundaries seem to be distinct types for the purpose of (polymorphic) proc definitions, so this compiles:
proc p(a: array[10, int]) = discard
proc p(a: array[-1 .. 8, int]) = discard
but they seem to be treated as identical when attempt to call this proc is made, so this:
var a: array[10, int]
p(a)
fails to compile with the following error message:
test.nim(6, 2) Error: ambiguous call; both test.p(a: array[0..9, int])[declared in test.nim(1, 5)] and test.p(a: array[-1..8, int])[declared in test.nim(2, 5)] match for: (array[0..9, int])
Nim compiler version:
> nim -v
Nim Compiler Version 0.17.2 (2017-09-07) [Windows: amd64]
Copyright (c) 2006-2017 by Andreas Rumpf
git hash: 811fbdafd958443ddac98ad58c77245860b38620
active boot switches: -d:release
I understand that this example may seem rather synthetic (though I actually run into this while testing an idea of providing two different indexing schemes for C-array used in some external C DLL call), but the situation when you can declare something that you cannot later call looks rather strange and inconsistent.I can definitely report this on Github, but before doing this I'd like to better understand this inconsistency.
It seems that for array initialization to work as expected, array types that differ only in index boundaries should be treated as equal. Otherwise this:
var b: array[-1 .. 8, int] = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8]
won't be possible (because of type mismatch), which is bad.
This means that at least in some important contexts only size of array should matter, not its boundaries. But maybe there are contexts (or parts of the language) in which differentiating between types array[10, int] and array[-1 .. 8, int] is useful or even required?
I'm new to nim, so I cannot easily answer this question. Any ideas? Any links to prevoius discussions?
You can try to search forum for if there were previous discussions... Just
the situation when you can declare something that you cannot later call
seems to be not intended.
Regarding assignment, it doesn't have to depend on types being indistinguishable. E.g.:
proc p(x: int) = echo "int"
proc p(x: int8) = echo "int8"
var x: int8
x=3 # implicit conversion
p x # int8
p 3 # int
overloading works here, while allowing literal's assignment with implicit conversion.