This version doesn't work
type
A = distinct int
B = distinct string
ABC =
A |
B
proc f[V1: static ABC; V2: static ABC]() = discard
f[A(10), A(20)]()
f[B("hello"), B("world")]()
# Error: cannot instantiate: 'f[A(10), B("abc")]'
f[A(10), B("abc")]()
This version works
type
A = distinct int
B = distinct string
ABC1 =
A |
B
ABC2 =
A |
B
proc f[V1: static ABC1; V2: static ABC2]() = discard
f[A(10), B("abc")]()
The question is, can I pass different types to static generic parameters in first version?
This works:
proc f[T1: ABC, T2: ABC](V1: static T1; V2: static T2) = discard
f(A(10), A(20))
f(B("hello"), B("world"))
f(A(10), B("abc"))
What's happening here is since ABC is a non-concrete type, it also gets converted into its own generic type, and implicit generics group both ABCs into the same generic (this is an intentional design choice) even with the semicolon (not sure if this is intended). Basically, one expects it to expand to this:
type
A = distinct int
B = distinct string
ABC =
A |
B
proc f[ABC1: ABC, ABC2: ABC, V1: static ABC1, V2: static ABC2]() = discard
f[A, A, A(10), A(20)]()
f[B, B, B("hello"), B("world")]()
f[A, B, A(10), B("abc")]()
While it actually expands to:
type
A = distinct int
B = distinct string
ABC =
A |
B
proc f[ABC1: ABC, V1: static ABC1, V2: static ABC1]() = discard
f[A, A(10), A(20)]()
f[B, B("hello"), B("world")]()
# error
f[A, A(10), B("abc")]()
Nim is supposed to have a workaround for this with the additional meaning of the distinct keyword for implicit generics as described in the manual, however it doesn't seem to work when combining with static here.
type
A = distinct int
B = distinct string
ABC =
A |
B
proc f[V1: static(distinct ABC), V2: static(distinct ABC)]() = discard
proc f[V1: distinct static ABC, V2: distinct static ABC]() = discard
# both give cannot instantiate here
f[A(10), A(20)]()
f[B("hello"), B("world")]()
f[A(10), B("abc")]()