That error's from compiler/lowerings.nim , where we find this test for flowVars:
proc flowVarKind(t: PType): TFlowVarKind =
if t.skipTypes(abstractInst).kind in {tyRef, tyString, tySequence}: fvGC
elif containsGarbageCollectedRef(t): fvInvalid
else: fvBlob
Run
In English: strings are OK. seqs are OK. Refs are OK. Anything not containing a
GC'd thing is not OK.
So what are Option[string]s? To simplify the code in lib/pure/options.nim
slightly,
type
Option*[T] = object
val: T
has: bool
Run
Options are objects. They are, critically, not _ref Objects_. And they contain
strings, which are GC 'd. So they get classified as fvInvalid
Here's some slightly long code that duplicates sufficient code from
lib/pure/options.nim to run the example, while using ref options so that the
example actually works:
import strformat, threadpool
import typetraits
type
SomePointer = ref | ptr | pointer
type
OptionObj*[T] = object
when T is SomePointer:
val: T
else:
val: T
has: bool
Option[T] = ref OptionObj[T]
proc some*[T](val: T): Option[T] =
when T is SomePointer:
assert(not val.isNil)
new(result)
result.val = val
else:
new(result)
result.has = true
result.val = val
proc none*[T]: Option[T] =
new(result)
when T isnot SomePointer:
result.has = false
proc get*[T](self: Option[T]): T =
if self.isNone:
raise newException(UnpackError, "Can't obtain a value from a `none`")
self.val
proc isSome*[T](self: Option[T]): bool {.inline.} =
when T is SomePointer:
result = not self.val.isNil
else:
result = self.has
proc readLineSafe(): Option[string] =
try: return some(stdin.readLine()) except EOFError: return none[string]()
while true:
let message = spawn readLineSafe()
let input = ^message
if input.isSome:
echo &"Sending \"{input.val}\""
else: break
Run