mirror of
https://github.com/nim-lang/Nim.git
synced 2026-09-17 18:44:53 +00:00
Supersedes #26120 (https://github.com/nim-lang/Nim/pull/26120), which fixed the reported case but left the `tfShallow` half of the same condition open. Since #25860 array literals are materialized into temporaries so that `lent` results keep valid backing storage. In an async proc such a temporary is lifted into the closure environment, and the environment is filled with an `nkFastAsgn`, i.e. without `needToCopy`. `genGenericAsgn` then emitted `genericShallowAssign` from the static const array, and for the `string` elements that ends in `unsureAsgnRef` -> `incRef(usrToCell(literal))` on memory that has no GC header: proc f() {.async.} = for ip in ["::1", "2001:db8::", "::"]: await sleepAsync(1) `OnStatic` sources must therefore always take the `genericAssign` path. Note that the guard has to dominate the `tfShallow` test as well, not just the `needToCopy` one: a `{.shallow.}` destination assigned from a `const` crashes in exactly the same way. This is the precedence `genOptAsgnTuple` and `genOptAsgnObject` already use, so `genGenericAsgn` now agrees with its two siblings instead of contradicting them. refc only; the other GCs do not reference count in `unsureAsgnRef`. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
38 lines
843 B
Nim
38 lines
843 B
Nim
discard """
|
|
matrix: "--mm:refc; --mm:orc"
|
|
output: "ok"
|
|
"""
|
|
|
|
# the loop temp lifted into the env must be deep-copied: a shallow assign from
|
|
# the static const array made refc incRef string literals in static memory
|
|
|
|
import std/asyncdispatch
|
|
|
|
const ips = ["::1", "2001:db8::", "::"]
|
|
|
|
proc overLiteral(): Future[int] {.async.} =
|
|
var n = 0
|
|
for ip in ["::1", "2001:db8::", "::"]:
|
|
await sleepAsync(1)
|
|
n += ip.len
|
|
return n
|
|
|
|
proc overConst(): Future[int] {.async.} =
|
|
var n = 0
|
|
for ip in ips:
|
|
await sleepAsync(1)
|
|
n += ip.len
|
|
return n
|
|
|
|
proc overNested(): Future[int] {.async.} =
|
|
var n = 0
|
|
for x in [(1, "::1"), (2, "2001:db8::"), (3, "::")]:
|
|
await sleepAsync(1)
|
|
n += x[1].len
|
|
return n
|
|
|
|
doAssert waitFor(overLiteral()) == 15
|
|
doAssert waitFor(overConst()) == 15
|
|
doAssert waitFor(overNested()) == 15
|
|
echo "ok"
|