What do guaranteed and owned parameters mean, and what do borrowing and consuming add?

3.6.2 · L5 · Learning

Predict first

What does this print?

func take(_ s: consuming String) {}
let s = "hello"
take(s)
print(s)
  • hello
  • Compile error: s is consumed

Mental model. Lending a book for the afternoon costs nothing. Giving it away means the library has to update its records.

The compiler decides ownership at each call boundary. By default a function borrows its parameters: the caller keeps ownership and guarantees the value lives for the call, so passing a class reference costs no retain at all. A parameter that the callee stores (an initialiser, a setter, an append) is passed owned, which means the caller transfers a +1 reference. Results are returned owned. So passing and borrowing are cheap, while storing and returning are where counts change.

Swift 5.9 lets you state this in the source: borrowing promises the callee only reads, and consuming says the callee takes ownership and may move the value into storage without an extra copy. For ordinary copyable types the caller can still use its value afterwards (an implicit copy is made if needed). For noncopyable types they are enforced: the value is really gone after a consuming call.

For a copyable type like String the compiler copies the value if you keep using it. Only noncopyable types make consuming final for the caller.

Common traps

  • Assuming every function argument is retained. Borrowed parameters are not, which is what makes ordinary calls cheap.
  • Marking everything consuming for speed. It only helps where the callee really stores or moves the value.

They might follow up with

  • What did __owned and __shared do? They were the underscored spellings of the same conventions before the official modifiers.
  • Why do initialisers take their arguments owned? Because they usually store them, which transfers ownership without a copy.

Related questions

  • 3.6.1 Where do hidden retains and releases come from, and how do you reduce them?
  • 1.8.5 What are consume, borrowing, and noncopyable types, at a high level?

← Where do hidden retains and releases come from, and how do you reduce…   What is Unmanaged, and what do takeRetainedValue and… →