From ecdcffed4b4c3bf1e016d62ceae49009fc8b125c Mon Sep 17 00:00:00 2001 From: Zoom Date: Fri, 28 Mar 2025 18:06:22 +0400 Subject: [PATCH] Mark `system.newStringUninit` sideeffect-free (#24813) - Allows using with `--experimental:strictFuncs` - `{.cast(noSideEffect).}:` inside the proc was required to mutate `s.len`, same as used in `newSeqImpl`. - Removed now unnecessary `noSideEffect` casts in `system.nim` - Closes #24811 Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com> --- changelog.md | 1 + lib/pure/strutils.nim | 3 +-- lib/system.nim | 25 ++++++++++++------------- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/changelog.md b/changelog.md index f3cc3fee4d..08c4bd097d 100644 --- a/changelog.md +++ b/changelog.md @@ -34,6 +34,7 @@ errors. - `std/math` The `^` symbol now supports floating-point as exponent in addition to the Natural type. - `system.substr` implementation now uses `copymem` (wrapped C `memcpy`) for copying data, if available at compilation. +- `system.newStringUninit` is now considered free of side-effects allowing it to be used with `--experimental:strictFuncs`. ## Language changes diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index c941afd085..4e2ae306f8 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -2356,8 +2356,7 @@ func multiReplace*(s: openArray[char]; replacements: varargs[(set[char], char)]) # Sanitize a filename with Windows-incompatible characters const file = "a/file:with?invalid*chars.txt" doAssert file.multiReplace(WinSanitationRules) == "a-file-with_invalid_chars.txt" - {.cast(noSideEffect).}: - result = newStringUninit(s.len) + result = newStringUninit(s.len) for i in 0.. 0: + {.cast(noSideEffect).}: + when defined(nimSeqsV2): + let s = cast[ptr NimStringV2](addr result) + if len > 0: + s.len = len + s.p.data[len] = '\0' + else: + let s = cast[NimString](result) s.len = len - s.p.data[len] = '\0' - else: - let s = cast[NimString](result) - s.len = len - s.data[len] = '\0' + s.data[len] = '\0' else: proc newStringUninit*(len: Natural): string {. magic: "NewString", importc: "mnewString", noSideEffect.} @@ -2794,8 +2795,7 @@ proc substr*(a: openArray[char]): string = assert a.toOpenArray(2, 5).substr() == "cdef" assert a.toOpenArray(2, high(a)).substr() == "cdefgh" # From index 2 to `high(a)` doAssertRaises(IndexDefect): discard a.toOpenArray(5, 99).substr() - {.cast(noSideEffect).}: - result = newStringUninit(a.len) + result = newStringUninit(a.len) when NotJSnotVMnotNims: if a.len > 0: copyMem(result[0].addr, a[0].unsafeAddr, a.len) @@ -2830,8 +2830,7 @@ proc substr*(s: string; first, last: int): string = # A bug with `magic: Slice` first = max(first, 0) last = min(last, high(s)) L = max(last - first + 1, 0) - {.cast(noSideEffect).}: - result = newStringUninit(L) + result = newStringUninit(L) when NotJSnotVMnotNims: if L > 0: copyMem(result[0].addr, s[first].unsafeAddr, L)