type
A = object
val: int
B = object
val: A
proc `=sink`*(dest: var A, source: A) =
echo "sink A"
dest.val = source.val
proc `=`*(dest: var A, source: A) =
echo "copy A"
`=destroy`(dest)
dest.val = source.val
proc dupB(b: var B) =
var b2 = b
proc main() =
var b: B
dupB(b)
main()
When I run the above program, it outputs nothing. Is this expected behavior of compiler?
I am a little confused. Of course, the following program runs as expected:
type
A = object
val: int
B = object
val: A
proc `=sink`*(dest: var A, source: A) =
echo "sink A"
dest.val = source.val
proc `=`*(dest: var A, source: A) =
echo "copy A"
`=destroy`(dest)
dest.val = source.val
proc `=sink`*(dest: var B, source: B) =
echo "sink B"
dest.val = source.val
proc `=`*(dest: var B, source: B) =
echo "copy B"
`=destroy`(dest)
dest.val = source.val
proc dupB(b: var B) =
var b2 = b
proc main() =
var b: B
dupB(b)
main()
It outputs:
copy B
copy
Another non-expert here: The doc says
The = hook is called for assignments that couldn't be transformed into =sink operations.
Could that be the case (or even falsely assumed by the compiler) here?
I saw this in the Nim Destructors and Move Semantics :
proc `=sink`*[T](a: var myseq[T]; b: myseq[T]) =
# move assignment, optional.
# Compiler is using `=destroy` and `copyMem` when not provided
`=destroy`(a)
a.len = b.len
a.cap = b.cap
a.data = b.data
So, =destroy and copyMem will be the default behavior.
I am sorry about the generic example, which was a clerical error. var b: B[int] should be var b: B[A], and that outputs a correct result.
I don't believe this is an incorrect output, on the contrary: the fact that there's nothing output in the devel compiler should be celebrated as the consequence of all the hard optimization work going on
you can force b2 to be actually copied from b rather than having that copy elided by initializing it to a value before the copy
proc dupB[T](b: var B[T]) =
var b2 = B[T]()
b2 = b
Adds =sink and = for B[T], there's still nothing in the output when using the devel-latest compiler (1.3.5).
type
A = object
val: int
B[T] = object
val: T
proc `=sink`*(dest: var A, source: A) =
echo "sink A"
dest.val = source.val
proc `=`*(dest: var A, source: A) =
echo "copy A"
`=destroy`(dest)
dest.val = source.val
proc `=sink`*[T](dest: var B[T], source: B[T]) =
echo "sink B"
dest.val = source.val
proc `=`*[T](dest: var B[T], source: B[T]) =
echo "copy B"
`=destroy`(dest)
dest.val = source.val
proc dupB[T](b: var B[T]) =
var b2 = b
proc main() =
var b: B[A]
dupB(b)
main()