summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorTimothee Cour <timothee.cour2@gmail.com>2020-05-29 08:10:59 -0700
committerGitHub <noreply@github.com>2020-05-29 17:10:59 +0200
commit63d1a0289e872212e836559f92a785df51f4faac (patch)
tree960e19edc865d06af5225e382d4212e2ee2d6b30 /lib
parente646c16e06e95855a92c1d2453f6f927555aed7e (diff)
downloadNim-63d1a0289e872212e836559f92a785df51f4faac.tar.gz
fix #14421 items uses lent T (#14447)
* fix #14421 items uses lent T for seq + openArray
* add -d:nimWorkaround14447
* fix test
Diffstat (limited to 'lib')
-rw-r--r--lib/system/iterators.nim31
1 files changed, 28 insertions, 3 deletions
diff --git a/lib/system/iterators.nim b/lib/system/iterators.nim
index 53b287db0..5d8685e40 100644
--- a/lib/system/iterators.nim
+++ b/lib/system/iterators.nim
@@ -1,7 +1,32 @@
-iterator items*[T](a: openArray[T]): T {.inline.} =
+when defined(nimHasLentIterators) and not defined(nimWorkaround14447):
+  template lent2(T): untyped =
+    # xxx this should actually depend on T.sizeof >= thresLentSizeof
+    # with for example `thresLentSizeof ~= int.sizeof`:
+    # it may be faster to return by value for small sizes compared to
+    # forcing a deref; this could be adjusted using profiling.
+    # However, `simply using `when T.sizeof >= thresLentSizeof: lent T else: T`
+    # does not work, for a few reasons (eg importc types would cause CT error
+    # and we can't filter them out without compiles() or some magic.
+    lent T
+else:
+  template lent2(T): untyped = T
+
+iterator items*[T: not char](a: openArray[T]): lent2 T {.inline.} =
   ## Iterates over each item of `a`.
   var i = 0
-  while i < len(a):
+  let n = len(a)
+  while i < n:
+    yield a[i]
+    inc(i)
+
+iterator items*[T: char](a: openArray[T]): T {.inline.} =
+  ## Iterates over each item of `a`.
+  # a VM bug currently prevents taking address of openArray[char]
+  # elements converted from a string (would fail in `tests/misc/thallo.nim`)
+  # in any case there's no performance advantage of returning char by address.
+  var i = 0
+  let n = len(a)
+  while i < n:
     yield a[i]
     inc(i)
 
@@ -179,7 +204,7 @@ iterator mpairs*(a: var cstring): tuple[key: int, val: var char] {.inline.} =
       yield (i, a[i])
       inc(i)
 
-iterator items*[T](a: seq[T]): T {.inline.} =
+iterator items*[T](a: seq[T]): lent2 T {.inline.} =
   ## Iterates over each item of `a`.
   var i = 0
   let L = len(a)