Description
This problem is a bit tricky to understand, so please read carefully.
Let's imagine we have a library featuring generic functions that mixes in some symbols from the caller scope:
generic_library.nim
proc libraryFunc*[T](x: T) =
mixin mixedIn, indirectlyMixedIn
echo mixedIn()
echo indirectlyMixedIn()
This library is used from another module that provides the needed symbols. mixedIn
is defined locally, while indirectlyMixedIn
is imported from yet another module:
module_using_generic_library.nim
import
generic_library, helper_module
proc mixedIn: int = 100
proc makeUseOfLibrary*[T](x: T) =
libraryFunc(x)
when isMainModule:
makeUseOfLibrary "test"
helper_module.nim
proc indirectlyMixedIn*: int =
200
So far, so good. If we compile module_using_generic_library
, it will produce the expected output.
But let's introduce another module that imports and uses module_using_generic_library
:
main.nim
import
module_using_generic_library
makeUseOfLibrary "test"
If we try to compile it, we'll get the following error:
module_using_generic_library.nim(4, 6) Hint: 'mixedIn' is declared but not used [XDeclaredButNotUsed]
main.nim(4, 18) template/generic instantiation of `makeUseOfLibrary` from here
module_using_generic_library.nim(7, 14) template/generic instantiation of `libraryFunc` from here
generic_library.nim(3, 8) Error: undeclared identifier: 'mixedIn'
Why did this happen?
Please notice that the makeUseOfLibrary
proc in the module_using_generic_library
module is also generic. It is instantiated in main
, but ultimately it consumes another generic defined in generic_library
. Its scope is "sandwiched" between the main
scope and the inner-most generic_library
scope. At the moment mixin
fails to recognise this and attempts to look for symbols in the outer-most scope (the one of main
). This is highly surprising behavior for the user, because if you examine the lexical scopes, libraryFunc
seems instantiated properly in the sandwiched module.
We've hit this problem multiple times during the development of nimcrypto, chronicles and nim-serialization. I've been asked to explain it on multiple occasions by almost everyone on our team, so it's an ongoing source of confusion and wasted time even for Nim experts. For this reason, I'm assigning high priority to the issue.