### Case 1

`var y = x` would be elided and all further reference of y should use x instead 
in the generated code.

For stack objects this shouldn't really matter because GCC/LLVM should optimize 
those variable renaming anyway. This is because during code generation, they 
transform the code in SSA form (Static Single Assignment) meaning no variables 
are mutable and all changes in values for example `a += 1` are transformed into 
variable assignment `a1 = a0 + 1`

In `consume` the `x` is passed by hidden reference can be mutated, this is 
useful if you need destructive updates that would be costly if you did a copy 
first, for example sorting in-place.

### Case 2

It's option 2

> Arc is smart and knows how different fields should be treated. It knows that 
> it should just copy the pointer of the seq and not the seq itself to avoid 
> unneccecary copies.

### Extra

Arc does sink inference but there are still 2 cases where you might want to use 
explicit sink.

Case 1. To only allow move semantics. Some types can only be moved, in 
particular all types that represent a resource (memory like GPU memory, open 
file, socket connection, database handle, lock, message queue). You want to 
ensure that there is a single owner to those resources throughout the resource 
lifetime and so you disallow copy but allow moves.

Case 2. Overloading for optimization, to avoid copy/reuse buffers we can have 2 
versions of a procedure, one with sink and one without, for example
    
    
    proc add1(a: seq[int]): seq[int] =
      result.newSeq(a.len) # Extra allocation
      for i in 0 ..< a.len:
        result[i] = a[i] + 1
    
    proc add1(a: sink seq[int]): seq[int] =
      # No allocation, we reuse the buffer
      for i in 0 ..< a.len:
        a[i] += 1
      `=sink`(result, a)
    
    
    Run

Reply via email to