Ok, so I was wrong with my explanation of `sink`. I was under the impression that the code: proc a(x : var X, y : sink Y) = x.v = y proc b(x : var X, y : sink Y) = a(x, y) proc test() = var y = Y() var x : X b(x, y) Run
would compile to the following (shortened for readability) C code: void a(X* x, Y* y) { eqsink(x.v, y); } void b(X* x, Y* y) { a(x, y); } void test() { Y y; X x; // ... b(&x, &y); // ... } Run While in reality this code gets generated: void a(X* x, Y* y) { eqsink(x.v, y); } void b(X* x, Y* y) { Y blitTmp; blitTmp = *y; a(x, &blitTmp); } void test() { Y y; X x; Y blitTmp; // ... blitTmp = y; b(&x, &blitTmp); // ... } Run I did some testing and from what I gathered, it seems like gcc is, in some very simple cases, able to optimize the blit temporaries aways and do a direct copy. In more complex cases however this seems to not be the case. Example: type Y = object s : string a : array[30, int] X = object v : X # using `a` and `b` function from sample above proc test() = var y = Y(s : "abcd") var x : X b(x, y) Run The gcc optimizer fails to elide the blit temporaries in this case, which results in two extra unnecessary memset/memcpy pairs. Compiler info: * Nim 1.6.0 * gcc version 11.1.0 (MinGW x86_64-posix-seh) Command line: `nim c --gc:arc -d:release`