mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-14 15:43:45 +00:00
Fixes #19240. The Manual's "Delegating bind statements" example didn't compile (module B didn't import A, type `O` wasn't exported, and `x: T` couldn't bind to `var O`), and once those were fixed it compiled *without* the `bind` statement — so it didn't demonstrate delegating bind at all. This replaces it with a minimal example that genuinely requires `bind init`: `module main` imports A and B but not C, so `init` is not in scope at the final instantiation of `genericA`; the open `mixin` symbol fails to resolve without `bind init` forwarding it from module B. Verified to fail without `bind` and compile with `bind` under Nim 2.2.10. --- Disclosure: I work with Claude as a co-processor. I understand what I'm submitting and I verified the example against the compiler myself. If you prefer human-only contributions, just say so and I'll close without friction.
This commit is contained in:
@@ -6123,40 +6123,48 @@ instantiations cross multiple different modules:
|
||||
|
||||
```nim
|
||||
# module A
|
||||
type O* = object
|
||||
|
||||
proc genericA*[T](x: T) =
|
||||
mixin init
|
||||
init(x)
|
||||
```
|
||||
|
||||
```nim
|
||||
# module C
|
||||
import A
|
||||
|
||||
proc init*(x: O) = discard
|
||||
```
|
||||
|
||||
```nim
|
||||
import C
|
||||
|
||||
# module B
|
||||
import A, C
|
||||
|
||||
proc genericB*[T](x: T) =
|
||||
# Without the `bind init` statement C's init proc is
|
||||
# not available when `genericB` is instantiated:
|
||||
# Without the `bind init` statement, C's `init` proc is not
|
||||
# available when `genericA` is instantiated through `genericB`
|
||||
# from `module main`, which does not import C:
|
||||
bind init
|
||||
genericA(x)
|
||||
```
|
||||
|
||||
```nim
|
||||
# module C
|
||||
type O = object
|
||||
proc init*(x: var O) = discard
|
||||
```
|
||||
|
||||
```nim
|
||||
# module main
|
||||
import B, C
|
||||
import A, B
|
||||
|
||||
genericB O()
|
||||
genericB(O())
|
||||
```
|
||||
|
||||
In module B has an `init` proc from module C in its scope that is not
|
||||
taken into account when `genericB` is instantiated which leads to the
|
||||
instantiation of `genericA`. The solution is to `forward`:idx: these
|
||||
symbols by a `bind` statement inside `genericB`.
|
||||
Because `genericA` uses `mixin init`, `init` is an open symbol that is
|
||||
resolved when `genericA` is instantiated. Here `genericA` is instantiated
|
||||
through `genericB`, whose final instantiation happens in `module main`.
|
||||
Since `module main` does not import `module C`, `init` is not in scope at
|
||||
that point, and the instantiation fails with ``undeclared identifier: 'init'``.
|
||||
The `bind init` statement inside `genericB` forwards the `init` symbol that
|
||||
is visible in `module B` into the instantiation of `genericA`, which makes
|
||||
the example compile. This `bind`, which re-exposes a symbol to a nested
|
||||
generic instantiation, is a `delegating bind`:idx:.
|
||||
|
||||
|
||||
Templates
|
||||
|
||||
Reference in New Issue
Block a user