Sorry to ask a noob question, but I have the following code:
type
TileIndex* = range[1..13]
# ...
proc findSet(): seq[TileIndex] =
var tfSubset: seq[TileIndex] = newSeq[TileIndex](3) ## Line 30
This results in the messages:
/Users/Chris/hacks/nim/find_sets.nim(30, 50) template/generic instantiation of `newSeq` from here/usr/local/Cellar/nim/1.4.2/nim/lib/system.nim(656, 10) Warning: Cannot prove that 'result' is initialized. This will become a compile time error in the future. [ProveInit]
And I don't understand this at all, and googling hasn't been much help.
I can replace that line with:
var tfSubset: seq[TileIndex] = @[]
tfSubset.add(1) ## And why does the forum indent these lines more than the 'var' line?
tfSubset.add(1)
tfSubset.add(1)
and get no messages at all, but that's just sad.
Any clues appreciated!
For me your example compiles with latest stable Nim 1.4.2 and no error messages.
Also maybe what you want is this?
proc findSet*(): seq[TileIndex] =
result = newSeq[TileIndex](3) ## Line 30
And be careful with default values, although type is range[1..13], the default value is 0
Wacky. My nim -v output:
> nim -v
Nim Compiler Version 1.4.2 [MacOSX: amd64]
Compiled at 2020-12-01
Copyright (c) 2006-2020 by Andreas Rumpf
active boot switches: -d:release -d:nimUseLinenoise
And no, tfSubset isn't the result, it's used to build the result.
Thanks for the reply anyway...
it's warning you that tfSubset has been initialized with zeros, which are invalid values for a TileIndex variable.
instead you should
var tfSubset = newSeqWith(3,1.TileIndex)
Thanks for the reply, shirleyquirk and xigoi.
Unfortunately, I get the same result:
/Users/Chris/hacks/nim/rc_find_sets.nim(31, 38) template/generic instantiation of `newSeqWith` from here
/Users/Chris/hacks/nim/Nim/lib/pure/collections/sequtils.nim(1049, 36) template/generic instantiation of `newSeq` from here
/Users/Chris/hacks/nim/Nim/lib/system.nim(656, 10) Warning: Cannot prove that 'result' is initialized. This will become a compile time error in the future. [ProveInit]
Note that this is with the compiler built locally from source, in case the brew version of nim was out of date. I get the same with the brew version.
Since greenfork doesn't get it, maybe it's fixed in a later version...?
You're correct that doesn't silence the warning
I was going to suggest silencing the warning manually, with {.push warning[ProveInit]:off.} ... {.pop.} but while that does turn the warning off, the pop doesn't seem to work.
I don't think newSeq can do anything differently, but maybe newSeqWith could turn that warning off and on again (once that bug is fixed.)
ok, so i was wrong about there being a bug, the problem is kinda subtle
ProveInit is triggered when a proc is instantiated, so will only ever display once. if the warning is turned off for that version of the (generic)proc, it can't be turned back on.
import sequtils
type TileIndex = range[1..13]
{.push warning[ProveInit]:off.}
discard newSeqWith(3, low(TileIndex)) # no longer warns, nor should it
{.pop.}
discard newSeq[range[1..3]](3) # this warns, great!
discard newSeq[range[1..13]](3) # this warning has still been turned off
so @chris_st you're fine to use {.push warning[ProveInit]:off.} .. {.pop.} but be aware of that caveat
changing``newSeqWith`` to do the same wouldn't be safe in general
Something like this helps with ranges and enums, but not objects:
type
Foo = range[1..3]
Bar = enum a = 1,b,c
Baz = object
a: Foo
b: Bar
HasLowButNoZero = concept a, type T
low(T)
not compiles(T(0))
proc newSeq[T: HasLowButNoZero](len: Natural): seq[T] =
{.push warning[ProveInit]: off.}
#system.newSeq(result,x) #this still warns!!!
result = system.newSeq[T](x)
{.pop.}
#newSeqWith(low(T)) would infinitely recur, hence the system.newSeq above so just copy it below:
for i in 0..<len:
result[i] = low(T)
assert newSeq[Foo](1)[0] == 1.Foo
assert newSeq[Bar](1)[0] == 1.Bar
#unfortunately doesn't work for ranges within objects
#newSeq[Baz](1)[0] == Baz(a: 0, b: 0)