`borrow` and `take` parameter ownership modifiers

i was an early adopter of _move(_:) because (like many others i’m sure) i remember the swift 4.x days when the compiler was not so good at optimizing copies, so when _move(_:) was announced i was thrilled and if you are anything like me i started spraying it everywhere.

in hindsight this was not so smart because with _move(_:) and no take/borrow, it is really easy to fool yourself into thinking you prevented a copy. because as @michelf said, if you _move(_:)/_move into a pass guaranteed function parameter, it just copies into a temporary, and most functions are pass guaranteed, so i really wish when i did this the compiler would emit a warning:

import Bar 
func foo(buffer:__owned [Int]) 
{
    var buffer:[Int] = _move buffer 
        buffer.append(0)
    Bar.bar(_move buffer)
    //            ^~~~~~
    // _move into __shared copies into a temporary; 
    // add parentheses to surpress this warning
}

and for a long time i didn’t know this was a thing because it’s not always obvious why the example before is dumb but the example below is smart usage of _move:

import Bar 
func foo(buffer:__owned [Int]) 
{
    var buffer:[Int] = _move buffer 
        buffer.append(0)
    var view:Bar = .init(_move buffer)
}

and i don’t really notice this because i use @inlinable a lot too much and more often than not the footgun gets jammed because Bar.bar(_:) is not from another module it is from the same module and the compiler can make it __owned, and also the 5.6 compiler is a lot smarter than the 4.x compiler was.

6 Likes