Skip to content

Commit ae5ab7b

Browse files
committed
templateutils: remove cpp workaround and enable lent only in newer Nim
1 parent b3b3760 commit ae5ab7b

File tree

5 files changed

+87
-24
lines changed

5 files changed

+87
-24
lines changed

stew/lentutils.nim

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# stew
2+
# Copyright 2026 Status Research & Development GmbH
3+
# Licensed under either of
4+
#
5+
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
6+
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
7+
#
8+
# at your option. This file may not be copied, modified, or distributed except according to those terms.
9+
10+
## Enable `lent` usage in newer Nim versions where it's known to work well.
11+
12+
# Based on https://github.com/arnetheduck/nim-results/blob/df8113dda4c2d74d460a8fa98252b0b771bf1f27/results.nim#L380
13+
const useLent* =
14+
(NimMajor, NimMinor, NimPatch) >= (2, 2, 0) or
15+
(defined(gcRefc) and ((NimMajor, NimMinor, NimPatch) >= (2, 0, 8)))
16+
17+
when useLent:
18+
template maybeLent*(T: untyped): untyped =
19+
## Generate `lent T` in newer Nim versions, generate `T` otherwise.
20+
lent T
21+
else:
22+
template maybeLent*(T: untyped): untyped =
23+
T

stew/templateutils.nim

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
type CppVar[T] = distinct ptr T
1+
# stew
2+
# Copyright 2026 Status Research & Development GmbH
3+
# Licensed under either of
4+
#
5+
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
6+
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
7+
#
8+
# at your option. This file may not be copied, modified, or distributed except according to those terms.
29

3-
iterator evalTemplateParamOnceImpl[T](x: T): lent T =
4-
yield x
10+
import ./lentutils
511

6-
when defined(cpp):
7-
# TODO `nim cpp` miscompiles iterators returning `var`,
8-
# so we need to emulate them in terms of pointers:
9-
iterator evalTemplateParamOnceImpl[T](x: var T): CppVar[T] =
10-
yield CppVar[T](addr(x))
12+
iterator evalTemplateParamOnceImpl[T](x: T): maybeLent T =
13+
yield x
1114

12-
template stripCppVar[T](p: CppVar[T]): var T =
13-
((ptr T)(p))[]
14-
else:
15-
iterator evalTemplateParamOnceImpl[T](x: var T): var T =
16-
yield x
15+
iterator evalTemplateParamOnceImpl[T](x: var T): var T =
16+
yield x
1717

1818
template evalTemplateParamOnce*(templateParam, newName, blk: untyped) =
1919
## This can be used in templates to avoid the problem of multiple
@@ -43,11 +43,5 @@ template evalTemplateParamOnce*(templateParam, newName, blk: untyped) =
4343
## Both limitations will be lifted in a future implementation based on
4444
## view types.
4545
block:
46-
for paramAddr in evalTemplateParamOnceImpl(templateParam):
47-
template newName: auto =
48-
when paramAddr is CppVar:
49-
stripCppVar(paramAddr)
50-
else:
51-
paramAddr
52-
46+
for newName in evalTemplateParamOnceImpl(templateParam):
5347
blk

tests/all_tests.nim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import
2727
test_interval_set,
2828
test_io2,
2929
test_keyed_queue,
30+
test_lentutils,
3031
test_macros,
3132
test_objects,
3233
test_ptrops,

tests/test_lentutils.nim

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# stew
2+
# Copyright 2026 Status Research & Development GmbH
3+
# Licensed under either of
4+
#
5+
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
6+
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
7+
#
8+
# at your option. This file may not be copied, modified, or distributed except according to those terms.
9+
10+
{.used.}
11+
12+
import
13+
unittest2,
14+
../stew/lentutils
15+
16+
iterator lenter[T](x: T): maybeLent T =
17+
yield x
18+
19+
suite "Lent utils":
20+
test "iterator yields a lent type if lent is enabled":
21+
let s = @[1, 2, 3]
22+
for x in lenter(s):
23+
when useLent:
24+
check unsafeAddr(s) == unsafeAddr(x)
25+
else:
26+
check unsafeAddr(s) != unsafeAddr(x)
27+
28+
# sanity check
29+
when (NimMajor, NimMinor, NimPatch) >= (2, 2, 4):
30+
test "iterator always yields a lent type in newer Nim":
31+
let s = @[1, 2, 3]
32+
for x in lenter(s):
33+
check unsafeAddr(s) == unsafeAddr(x)
34+
35+
# sanity check
36+
when (NimMajor, NimMinor, NimPatch) < (2, 0, 8):
37+
test "iterator never yields a lent type in older Nim":
38+
let s = @[1, 2, 3]
39+
for x in lenter(s):
40+
check unsafeAddr(s) != unsafeAddr(x)

tests/test_templateutils.nim

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import
1010
unittest2,
1111
../stew/templateutils
1212

13+
from ../stew/lentutils import useLent
14+
1315
var computations = newSeq[string]()
1416
var templateParamAddresses = newSeq[pointer]()
1517

@@ -66,7 +68,10 @@ test "Template utils":
6668

6769
check computations == ["call", "var", "let", "accessor"]
6870

69-
check:
70-
templateParamAddresses[1] == addr s1
71-
templateParamAddresses[2] == unsafeAddr s2
72-
templateParamAddresses[3] == addr o.accessSeq
71+
check templateParamAddresses[1] == addr s1
72+
check templateParamAddresses[3] == addr o.accessSeq
73+
74+
# let symbols need lent to avoid copying;
75+
# they are still computed once though
76+
when useLent:
77+
check templateParamAddresses[2] == unsafeAddr s2

0 commit comments

Comments
 (0)