mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-02 03:02:31 +00:00
refs #23091, especially post merge comments
Unsure if `experimental` and `bind` are the perfect constructs to use
but they seem to get the job done here. Symbol nodes do not get marked
`nfOpenSym` if the `bind` statement is used for their symbol, and
`nfOpenSym` nodes do not get replaced by new local symbols if the
experimental switch is not enabled in the local context (meaning it also
works with `push experimental`). However this incurs a warning as the
fact that the node is marked `nfOpenSym` means we did not `bind` it, so
we might want to do that or turn on the experimental switch if we didn't
intend to bind it.
The experimental switch name is arbitrary and could be changed.
---------
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 4b1a841707)
51 lines
1.4 KiB
Nim
51 lines
1.4 KiB
Nim
type Xxx = enum
|
|
error
|
|
value
|
|
|
|
type
|
|
Result[T, E] = object
|
|
when T is void:
|
|
when E is void:
|
|
oResultPrivate*: bool
|
|
else:
|
|
case oResultPrivate*: bool
|
|
of false:
|
|
eResultPrivate*: E
|
|
of true:
|
|
discard
|
|
else:
|
|
when E is void:
|
|
case oResultPrivate*: bool
|
|
of false:
|
|
discard
|
|
of true:
|
|
vResultPrivate*: T
|
|
else:
|
|
case oResultPrivate*: bool
|
|
of false:
|
|
eResultPrivate*: E
|
|
of true:
|
|
vResultPrivate*: T
|
|
|
|
template valueOr[T: not void, E](self: Result[T, E], def: untyped): untyped =
|
|
let s = (self) # TODO avoid copy
|
|
case s.oResultPrivate
|
|
of true:
|
|
s.vResultPrivate
|
|
of false:
|
|
when E isnot void:
|
|
template error: untyped {.used, inject.} = s.eResultPrivate
|
|
def
|
|
|
|
proc f(): Result[int, cstring] =
|
|
Result[int, cstring](oResultPrivate: false, eResultPrivate: "f")
|
|
|
|
proc g(T: type): string =
|
|
let x = f().valueOr:
|
|
return $error #[tt.Warning
|
|
^ a new symbol 'error' has been injected during instantiation of g, however 'error' [enumField declared in tmacroinjectedsymwarning.nim(2, 3)] captured at the proc declaration will be used instead; either enable --experimental:genericsOpenSym to use the injected symbol or `bind` this captured symbol explicitly [GenericsIgnoredInjection]]#
|
|
|
|
"ok"
|
|
|
|
discard g(int)
|