Skip to content

Commit

Permalink
fixes #24175; Sink parameters not copied at compile time (#24178)
Browse files Browse the repository at this point in the history
fixes #24175
  • Loading branch information
ringabout authored Sep 27, 2024
1 parent 75b9d66 commit d4027f2
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 1 deletion.
12 changes: 11 additions & 1 deletion compiler/vmgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ type
gfNode # Affects how variables are loaded - always loads as rkNode
gfNodeAddr # Affects how variables are loaded - always loads as rkNodeAddr
gfIsParam # do not deepcopy parameters, they are immutable
gfIsSinkParam # deepcopy sink parameters
TGenFlags = set[TGenFlag]

proc debugInfo(c: PCtx; info: TLineInfo): string =
Expand Down Expand Up @@ -620,10 +621,17 @@ proc genCall(c: PCtx; n: PNode; dest: var TDest) =
let fntyp = skipTypes(n[0].typ, abstractInst)
for i in 0..<n.len:
var r: TRegister = x+i
c.gen(n[i], r, {gfIsParam})
if i >= fntyp.signatureLen:
c.gen(n[i], r, {gfIsParam})
internalAssert c.config, tfVarargs in fntyp.flags
c.gABx(n, opcSetType, r, c.genType(n[i].typ))
else:
if fntyp[i] != nil and fntyp[i].kind == tySink and
fntyp[i].skipTypes({tySink}).kind in {tyObject, tyString, tySequence}:
c.gen(n[i], r, {gfIsSinkParam})
else:
c.gen(n[i], r, {gfIsParam})

if dest < 0:
c.gABC(n, opcIndCall, 0, x, n.len)
else:
Expand Down Expand Up @@ -1740,6 +1748,8 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
c.gABx(n, opcLdGlobalAddr, dest, s.position)
elif isImportcVar:
c.gABx(n, opcLdGlobalDerefFFI, dest, s.position)
elif gfIsSinkParam in flags:
genAsgn(c, dest, n, requiresCopy = true)
elif fitsRegister(s.typ) and gfNode notin flags:
var cc = c.getTemp(n.typ)
c.gABx(n, opcLdGlobal, cc, s.position)
Expand Down
46 changes: 46 additions & 0 deletions tests/destructor/tsink.nim
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,49 @@ block: # bug #23902

proc foo(a: sink string) =
var x = (a, a)

block: # bug #24175
block:
func mutate(o: sink string): string =
o[1] = '1'
result = o

static:
let s = "999"
let m = mutate(s)
doAssert s == "999"
doAssert m == "919"

func foo() =
let s = "999"
let m = mutate(s)
doAssert s == "999"
doAssert m == "919"

static:
foo()
foo()

block:
type O = object
a: int

func mutate(o: sink O): O =
o.a += 1
o

static:
let x = O(a: 1)
let y = mutate(x)
doAssert x.a == 1
doAssert y.a == 2

proc foo() =
let x = O(a: 1)
let y = mutate(x)
doAssert x.a == 1
doAssert y.a == 2

static:
foo()
foo()

0 comments on commit d4027f2

Please sign in to comment.