Symbol lookup in generics
Open and Closed symbols
The symbol binding rules in generics are slightly subtle: There are “open” and “closed” symbols. A “closed” symbol cannot be re-bound in the instantiation context, an “open” symbol can. Per default, overloaded symbols are open and every other symbol is closed.
Open symbols are looked up in two different contexts: Both the context at definition and the context at instantiation are considered:
type
Index = distinct int
proc `==` (a, b: Index): bool {.borrow.}
var a = (0, 0.Index)
var b = (0, 0.Index)
echo a == b # works!
In the example, the generic `==` for tuples (as defined in the system module) uses the \== operators of the tuple’s components. However, the \== for the Index type is defined after the \== for tuples; yet the example compiles as the instantiation takes the currently defined symbols into account too.