summary refs log tree commit diff stats
path: root/doc
diff options
context:
space:
mode:
authormetagn <metagngn@gmail.com>2024-09-18 20:27:09 +0300
committerGitHub <noreply@github.com>2024-09-18 19:27:09 +0200
commit0c3573e4a0628bbaa8b09dcd854bdc2702948bbc (patch)
tree0395872790437f6eebf2c52a8401fbbb22254d33 /doc
parent79b17b7c05f66a032949135f4d5a4a62ab9c36a0 (diff)
downloadNim-0c3573e4a0628bbaa8b09dcd854bdc2702948bbc.tar.gz
make `genericsOpenSym` work at instantiation time, new behavior in `openSym` (#24111)
alternative to #24101

#23892 changed the opensym experimental switch so that it has to be
enabled in the context of the generic/template declarations capturing
the symbols, not the context of the instantiation of the
generics/templates. This was to be in line with where the compiler gives
the warnings and changes behavior in a potentially breaking way.

However `results` [depends on the old
behavior](https://github.com/arnetheduck/nim-results/blob/71d404b314479a6205bfd050f4fe5fe49cdafc69/results.nim#L1428),
so that the callers of the macros provided by results always take
advantage of the opensym behavior. To accomodate this, we change the
behavior of the old experimental option that `results` uses,
`genericsOpenSym`, so that ignores the information of whether or not
symbols are intentionally opened and always gives the opensym behavior
as long as it's enabled at instantiation time. This should keep
`results` working as is. However this differs from the normal opensym
switch in that it doesn't generate `nnkOpenSym`.

Before it was just a generics-only version of `openSym` along with
`templateOpenSym` which was only for templates. So `templateOpenSym` is
removed along with this change, but no one appears to have used it.
Diffstat (limited to 'doc')
-rw-r--r--doc/manual_experimental.md35
1 files changed, 30 insertions, 5 deletions
diff --git a/doc/manual_experimental.md b/doc/manual_experimental.md
index 6998e313d..da51d59ad 100644
--- a/doc/manual_experimental.md
+++ b/doc/manual_experimental.md
@@ -2533,8 +2533,7 @@ renaming the captured symbols should be used instead so that the code is not
 affected by context changes.
 
 Since this change may affect runtime behavior, the experimental switch
-`openSym`, or `genericsOpenSym` and `templateOpenSym` for only the respective
-routines, needs to be enabled; and a warning is given in the case where an
+`openSym` needs to be enabled; and a warning is given in the case where an
 injected symbol would replace a captured symbol not bound by `bind` and
 the experimental switch isn't enabled.
 
@@ -2555,7 +2554,7 @@ template oldTempl(): string =
       value # warning: a new `value` has been injected, use `bind` or turn on `experimental:openSym`
 echo oldTempl() # "captured"
 
-{.experimental: "openSym".} # or {.experimental: "genericsOpenSym".} for just generic procs
+{.experimental: "openSym".}
 
 proc bar[T](): string =
   foo(123):
@@ -2568,8 +2567,6 @@ proc baz[T](): string =
     return value
 assert baz[int]() == "captured"
 
-# {.experimental: "templateOpenSym".} would be needed here if genericsOpenSym was used
-
 template barTempl(): string =
   block:
     foo(123):
@@ -2590,6 +2587,34 @@ modified `nnkOpenSymChoice` node but macros that want to support the
 experimental feature should still handle `nnkOpenSym`, as the node kind would
 simply not be generated as opposed to being removed.
 
+Another experimental switch `genericsOpenSym` exists that enables this behavior
+at instantiation time, meaning templates etc can enable it specifically when
+they are being called. However this does not generate `nnkOpenSym` nodes
+(unless the other switch is enabled) and so doesn't reflect the regular
+behavior of the switch.
+
+```nim
+const value = "captured"
+template foo(x: int, body: untyped): untyped =
+  let value {.inject.} = "injected"
+  {.push experimental: "genericsOpenSym".}
+  body
+  {.pop.}
+
+proc bar[T](): string =
+  foo(123):
+    return value
+echo bar[int]() # "injected"
+
+template barTempl(): string =
+  block:
+    var res: string
+    foo(123):
+      res = value
+    res
+assert barTempl() == "injected"
+```
+
 
 VTable for methods
 ==================