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:

  1. type
  2. Index = distinct int
  3. proc `==` (a, b: Index): bool {.borrow.}
  4. var a = (0, 0.Index)
  5. var b = (0, 0.Index)
  6. 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.