diff options
author | ringabout <43030857+ringabout@users.noreply.github.com> | 2024-09-27 15:36:09 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-27 09:36:09 +0200 |
commit | d4027f25c4af0b892614ef9237c1318085516e07 (patch) | |
tree | 3f086c07868faedcf236cc51f917c5204b21716a | |
parent | 75b9d665822d87d90372f6a5a3ffded96887e3db (diff) | |
download | Nim-d4027f25c4af0b892614ef9237c1318085516e07.tar.gz |
fixes #24175; Sink parameters not copied at compile time (#24178)
fixes #24175
-rw-r--r-- | compiler/vmgen.nim | 12 | ||||
-rw-r--r-- | tests/destructor/tsink.nim | 46 |
2 files changed, 57 insertions, 1 deletions
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index d9c7cd551..0c7a49984 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -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 = @@ -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: @@ -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) diff --git a/tests/destructor/tsink.nim b/tests/destructor/tsink.nim index e214e4cca..e8750ad7c 100644 --- a/tests/destructor/tsink.nim +++ b/tests/destructor/tsink.nim @@ -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() |