Example code
from strformat import `&`
type X = distinct int
proc `=sink`(p1: var X; p2: X) = echo &"=sink {cast[int](p2)}"
proc `=copy`(p1: var X; p2: X) = echo &"=copy {cast[int](p2)}"
proc `=destroy`(p: var X) = echo &"=destroy {cast[int](p)}"
proc main =
echo "~~~~~~~~~~"
block:
proc byLet(v: int): owned X =
let x = X(v)
x
discard byLet(1)
echo "~~~~~~~~~~"
block:
proc byVar(v: int): owned X =
var x = X(v)
x
discard byVar(2)
echo "~~~~~~~~~~"
block:
proc byCast(v: int): owned X = cast[X](v)
discard byCast(3)
echo "~~~~~~~~~~"
block:
proc byConv(v: int): owned X = (X)(v)
discard byConv(4)
echo "~~~~~~~~~~"
block:
proc byVarMove(v: int): owned X =
var x = X(v)
move(x)
discard byVarMove(5)
echo "~~~~~~~~~~"
block:
proc byVarWasMoved(v: int): owned X =
var x = X(v)
result = x
wasMoved(x)
discard byVarWasMoved(6)
echo "~~~~~~~~~~"
main()
Run
$ nim r --gc:arc --expandArc:main test.nim
...
~~~~~~~~~~
=copy 1
=destroy 0
~~~~~~~~~~
=copy 2
=destroy 0
~~~~~~~~~~
=copy 3
=destroy 0
~~~~~~~~~~
=destroy 4
~~~~~~~~~~
=destroy 0
=destroy 5
~~~~~~~~~~
=copy 6
=destroy 0
~~~~~~~~~~
Output of --expandArc:main
echo ["~~~~~~~~~~"]
block :tmp:
var :tmpD
proc byLet(v: int): owned X =
result =
let x = X(v)
x
discard
:tmpD = byLet(1)
:tmpD
`=destroy`(:tmpD)
echo ["~~~~~~~~~~"]
block :tmp_1:
var :tmpD_1
proc byVar(v_1: int): owned X =
result_1 =
var x_1 = X(v_1)
x_1
discard
:tmpD_1 = byVar(2)
:tmpD_1
`=destroy`(:tmpD_1)
echo ["~~~~~~~~~~"]
block :tmp_2:
var :tmpD_2
proc byCast(v_2: int): owned X =
result_2 = cast[X](v_2)
discard
:tmpD_2 = byCast(3)
:tmpD_2
`=destroy`(:tmpD_2)
echo ["~~~~~~~~~~"]
block :tmp_3:
var :tmpD_3
proc byConv(v_3: int): owned X =
result_3 = X(v_3)
discard
:tmpD_3 = byConv(4)
:tmpD_3
`=destroy`(:tmpD_3)
echo ["~~~~~~~~~~"]
block :tmp_4:
var :tmpD_4
proc byVarMove(v_4: int): owned X =
result_4 =
var x_2 = X(v_4)
move(x_2)
discard
:tmpD_4 = byVarMove(5)
:tmpD_4
`=destroy`(:tmpD_4)
echo ["~~~~~~~~~~"]
block :tmp_5:
var :tmpD_5
proc byVarWasMoved(v_5: int): owned X =
var x_3 = X(v_5)
result_5 = x_3
wasMoved(x_3)
discard
:tmpD_5 = byVarWasMoved(6)
:tmpD_5
`=destroy`(:tmpD_5)
echo ["~~~~~~~~~~"]
I see, will do it.
@gemath thank you for the advice.
block:
proc byLet(v:int): X =
result = X(v)
let x{.byaddr.} = result
discard byLet(1)
block:
proc byVar(v:int): X =
result = X(v)
var x{.byaddr.} = result
discard byVar(2)
block:
proc byCast(v:sink int):X = move(cast[var X](v.addr))
discard byCast(3)
block:
proc byLetCastMove(v:int): X =
let x = X(v)
result = move(cast[var X](x.unsafeAddr)
discard byLetCastMove(6)
but you really shouldn't do any of those they're all horrible
i'm not being helpful
Thank you for the interesting tricks, I replace {.byaddr.} with {.cursor.} and it works.
The move after cast is kinda useful workaround.
@Araq I have report an issue on github.