From a3e9cc52343a54cadc7b77b783e1c8b6ba2b327f Mon Sep 17 00:00:00 2001 From: cooldome Date: Wed, 16 Sep 2020 16:26:45 +0100 Subject: [PATCH] Introduce explicit copy (#15330) --- compiler/injectdestructors.nim | 2 +- lib/system.nim | 5 +++++ tests/arc/tcopytosink_warning.nim | 22 ++++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 tests/arc/tcopytosink_warning.nim diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index 9d1f43595538a..de28c9f70329d 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -408,7 +408,7 @@ proc passCopyToSink(n: PNode; c: var Con; s: var Scope): PNode = if isLValue(n) and not isCapturedVar(n) and n.typ.skipTypes(abstractInst).kind != tyRef and c.inSpawn == 0: message(c.graph.config, n.info, hintPerformance, ("passing '$1' to a sink parameter introduces an implicit copy; " & - "if possible, rearrange your program's control flow to prevent it") % $n) + "if possible, rearrange your program's control flow to prevent it or use 'copy($1)' to hint the compiler it is intentional") % $n) else: if c.graph.config.selectedGC in {gcArc, gcOrc}: assert(not containsGarbageCollectedRef(n.typ)) diff --git a/lib/system.nim b/lib/system.nim index c05ca24dc2650..dbe0f11f720b5 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -264,6 +264,11 @@ proc move*[T](x: var T): T {.magic: "Move", noSideEffect.} = result = x wasMoved(x) +func copy*[T](x: T): T {.inline.} = + ## make explicit copy of the argument `x`, used to signal to the compiler + ## the copy is intentional + result = x + type range*[T]{.magic: "Range".} ## Generic type to construct range types. array*[I, T]{.magic: "Array".} ## Generic type to construct diff --git a/tests/arc/tcopytosink_warning.nim b/tests/arc/tcopytosink_warning.nim new file mode 100644 index 0000000000000..8ae36386a42cc --- /dev/null +++ b/tests/arc/tcopytosink_warning.nim @@ -0,0 +1,22 @@ +discard """ + cmd: "nim c --gc:arc $file" + nimout: '''tcopytosink_warning.nim(17, 7) Hint: myhint [User] +tcopytosink_warning.nim(19, 9) Hint: passing 'x' to a sink parameter introduces an implicit copy; if possible, rearrange your program's control flow to prevent it or use 'copy(x)' to hint the compiler it is intentional [Performance] +''' + output: "x" +""" +import macros + +proc test(v: var seq[string], x: sink string) = + v.add x + +var v = @["a", "b", "c"] +var x = "x" + +static: + hint("myhint") +test(v, copy(x)) # no warning +test(v, x) # produces warning + +echo x # use after sink +