I've got a problem calling "$" on some range type. It all looks perfectly fine to me. Atm I would tend to think it's a compiler error. Here is the simplified code:
const MAX_THREADS* = 64
const MAX_TOPICS* = 1048576
const MAX_PROCESSES* = int(4294967296'i64 div int64(MAX_THREADS * MAX_TOPICS))
type
ThreadID* = range[0'u8..uint8(MAX_THREADS-1)]
## Thread ID, within process.
ProcessID* = range[0'u16..uint16(MAX_PROCESSES-1)]
## Process ID of thread.
TopicID* = range[0'u32..uint32(MAX_TOPICS-1)]
## TopicID, within thread.
proc `$` *(id: ThreadID): string {.inline.} =
## Somehow, default `$` is ambiguous.
$uint8(id)
proc `$` *(id: ProcessID): string {.inline.} =
## Somehow, default `$` is ambiguous.
$uint16(id)
proc `$` *(id: TopicID): string {.inline.} =
## Somehow, default `$` is ambiguous.
$uint32(id)
type
QueueID* = distinct uint32
## The complete queue ID, containing the process ID, thread ID and topic ID.
proc tid*(queue: QueueID): ThreadID {.inline, noSideEffect.} =
## Dummy simplified impl!
ThreadID(uint8(queue))
proc pid*(queue: QueueID): ProcessID {.inline, noSideEffect.} =
## Dummy simplified impl!
ProcessID(uint16(queue))
proc cid*(queue: QueueID): TopicID {.inline, noSideEffect.} =
## Dummy simplified impl!
TopicID(uint32(queue))
proc `$` *(queue: QueueID): string =
## String representation of a QueueID.
let p = $pid(queue)
let tt: ThreadID = tid(queue)
let t = $tt # ERROR LINE
let c = $cid(queue)
p & "." & t & "." & c
And it fails to compile with:
kueues.nim(356, 13) Error: ambiguous call; both kueues.$(id: ThreadID)[declared in kueues.nim(130, 5)]
and kueues.$(id: ProcessID)[declared in kueues.nim(134, 5)] match for: (ThreadID)
ThreadID is a range of uint8, and ProcessID is a range of uint16. I do not see how I could possibly be more explicit than I already am, which is IMO already "too" explicit. The original (working) code, used to look like this:
const MAX_THREADS* = 64
const MAX_TOPICS* = 1048576
# ...
const MAX_PROCESSES* = int(4294967296'i64 div int64(MAX_THREADS * MAX_TOPICS))
type
ThreadID* = range[0..MAX_THREADS-1]
## Thread ID, within process.
ProcessID* = range[0..MAX_PROCESSES-1]
## Process ID of thread.
TopicID* = range[0..MAX_TOPICS-1]
## TopicID, within thread.
type
QueueID* = distinct uint32
## The complete queue ID, containing the process ID, thread ID and topic ID.
proc tid*(queue: QueueID): ThreadID {.inline, noSideEffect.} =
## Dummy simplified impl!
ThreadID(uint8(queue))
proc pid*(queue: QueueID): ProcessID {.inline, noSideEffect.} =
## Dummy simplified impl!
ProcessID(uint16(queue))
proc cid*(queue: QueueID): TopicID {.inline, noSideEffect.} =
## Dummy simplified impl!
TopicID(uint32(queue))
proc `$` *(queue: QueueID): string =
## String representation of a QueueID.
$pid(queue) & "." & $tid(queue) & "." & $cid(queue)
Then I decided to change ThreadID, ProcessID and TopicID from range of int, to range of appropriate specific size (uint8/uint16/uint32). That is when I got the error. First I added the explicit $(ThreadID), $(ProcessID) and $(TopicID) procs and then tried to break the $(QueueID) proc into multiple steps. But I cannot get rid of the error.
IMO, you to need to make ThreadID, ProcessID and TopicID a distinct types.
type
ThreadID* = distinct range[0..MAX_THREADS-1] ## Thread ID, within process.
ProcessID* = distinct range[0..MAX_PROCESSES-1] ## Process ID of thread.
TopicID* = distinct range[0..MAX_TOPICS-1] ## TopicID, within thread.
@cdome The distinct helped, but was not enough. It seems Nim has problems deciding how to convert an "uint" to a string, so I also needed to specify "proc $(uint)":
const MAX_THREADS* = 64
const MAX_TOPICS* = 1048576
const MAX_PROCESSES* = int(4294967296'i64 div int64(MAX_THREADS * MAX_TOPICS))
type
ThreadID* = distinct range[0'u8..uint8(MAX_THREADS-1)]
## Thread ID, within process.
ProcessID* = distinct range[0'u16..uint16(MAX_PROCESSES-1)]
## Process ID of thread.
TopicID* = distinct range[0'u32..uint32(MAX_TOPICS-1)]
## TopicID, within thread.
proc `$` *(i: uint): string {.inline.} =
$uint64(i)
proc `==` *(a, b: ThreadID): bool {.borrow.}
proc `$` *(id: ThreadID): string {.borrow.}
proc `==` *(a, b: ProcessID): bool {.borrow.}
proc `$` *(id: ProcessID): string {.borrow.}
proc `==` *(a, b: TopicID): bool {.borrow.}
proc `$` *(id: TopicID): string {.borrow.}
type
QueueID* = distinct uint32
## The complete queue ID, containing the process ID, thread ID and topic ID.
proc tid*(queue: QueueID): ThreadID {.inline, noSideEffect.} =
## Dummy simplified impl!
ThreadID(uint8(queue))
proc pid*(queue: QueueID): ProcessID {.inline, noSideEffect.} =
## Dummy simplified impl!
ProcessID(uint16(queue))
proc cid*(queue: QueueID): TopicID {.inline, noSideEffect.} =
## Dummy simplified impl!
TopicID(uint32(queue))
proc `$` *(queue: QueueID): string =
## String representation of a QueueID.
$pid(queue) & "." & $tid(queue) & "." & $cid(queue)