Skip to content

Commit ecdcffe

Browse files
ZoomRmcringabout
andauthored
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>
1 parent 58b1f28 commit ecdcffe

File tree

3 files changed

+14
-15
lines changed

3 files changed

+14
-15
lines changed

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ errors.
3434
- `std/math` The `^` symbol now supports floating-point as exponent in addition to the Natural type.
3535

3636
- `system.substr` implementation now uses `copymem` (wrapped C `memcpy`) for copying data, if available at compilation.
37+
- `system.newStringUninit` is now considered free of side-effects allowing it to be used with `--experimental:strictFuncs`.
3738

3839
## Language changes
3940

lib/pure/strutils.nim

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2356,8 +2356,7 @@ func multiReplace*(s: openArray[char]; replacements: varargs[(set[char], char)])
23562356
# Sanitize a filename with Windows-incompatible characters
23572357
const file = "a/file:with?invalid*chars.txt"
23582358
doAssert file.multiReplace(WinSanitationRules) == "a-file-with_invalid_chars.txt"
2359-
{.cast(noSideEffect).}:
2360-
result = newStringUninit(s.len)
2359+
result = newStringUninit(s.len)
23612360
for i in 0..<s.len:
23622361
var nextChar = s[i]
23632362
for subs, by in replacements.items:

lib/system.nim

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1685,7 +1685,7 @@ when not defined(js):
16851685
else:
16861686
{.error: "The type T cannot contain managed memory or have destructors".}
16871687
1688-
proc newStringUninit*(len: Natural): string =
1688+
proc newStringUninit*(len: Natural): string {.noSideEffect.} =
16891689
## Returns a new string of length `len` but with uninitialized
16901690
## content. One needs to fill the string character after character
16911691
## with the index operator `s[i]`.
@@ -1696,15 +1696,16 @@ when not defined(js):
16961696
result = newString(len)
16971697
else:
16981698
result = newStringOfCap(len)
1699-
when defined(nimSeqsV2):
1700-
let s = cast[ptr NimStringV2](addr result)
1701-
if len > 0:
1699+
{.cast(noSideEffect).}:
1700+
when defined(nimSeqsV2):
1701+
let s = cast[ptr NimStringV2](addr result)
1702+
if len > 0:
1703+
s.len = len
1704+
s.p.data[len] = '\0'
1705+
else:
1706+
let s = cast[NimString](result)
17021707
s.len = len
1703-
s.p.data[len] = '\0'
1704-
else:
1705-
let s = cast[NimString](result)
1706-
s.len = len
1707-
s.data[len] = '\0'
1708+
s.data[len] = '\0'
17081709
else:
17091710
proc newStringUninit*(len: Natural): string {.
17101711
magic: "NewString", importc: "mnewString", noSideEffect.}
@@ -2794,8 +2795,7 @@ proc substr*(a: openArray[char]): string =
27942795
assert a.toOpenArray(2, 5).substr() == "cdef"
27952796
assert a.toOpenArray(2, high(a)).substr() == "cdefgh" # From index 2 to `high(a)`
27962797
doAssertRaises(IndexDefect): discard a.toOpenArray(5, 99).substr()
2797-
{.cast(noSideEffect).}:
2798-
result = newStringUninit(a.len)
2798+
result = newStringUninit(a.len)
27992799
when NotJSnotVMnotNims:
28002800
if a.len > 0:
28012801
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`
28302830
first = max(first, 0)
28312831
last = min(last, high(s))
28322832
L = max(last - first + 1, 0)
2833-
{.cast(noSideEffect).}:
2834-
result = newStringUninit(L)
2833+
result = newStringUninit(L)
28352834
when NotJSnotVMnotNims:
28362835
if L > 0:
28372836
copyMem(result[0].addr, s[first].unsafeAddr, L)

0 commit comments

Comments
 (0)