# SE-0377: borrow and take parameter ownership modifiers

**URL:** <https://forums.swift.org/t/se-0377-borrow-and-take-parameter-ownership-modifiers/61020>\
**Category:** Proposal Reviews\
**Created:** [October 25, 2022, 5:38pm UTC](https://forums.swift.org/t/se-0377-borrow-and-take-parameter-ownership-modifiers/61020 "2022-10-25T17:38:43Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![ben-cohen](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ben-cohen/32/296_2.png) [@ben-cohen](https://forums.swift.org/u/ben-cohen)\
**Post date:** [October 25, 2022, 5:38pm UTC](https://forums.swift.org/t/se-0377-borrow-and-take-parameter-ownership-modifiers/61020/1 "2022-10-25T17:38:43Z")

</div>

Hi Swift community,

The review of [SE-0377: `borrow` and `take` parameter ownership modifiers](https://github.com/apple/swift-evolution/blob/main/proposals/0377-parameter-ownership-modifiers.md) begins now and runs through November 8, 2022.

Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, [directly to the review manager](mailto:ben_cohen@apple.com). When emailing the review manager directly, please keep the proposal link at the top of the message.

This proposal is closely related to [SE-0366: `take` operator to end the lifetime of a variable binding](https://github.com/apple/swift-evolution/blob/main/proposals/0366-move-function.md), the [second review](https://forums.swift.org/t/se-0366-second-review-take-operator-to-end-the-lifetime-of-a-variable-binding/) for which is running concurrently.

##### What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

- What is your evaluation of the proposal?
- Is the problem being addressed significant enough to warrant a change to Swift?
- Does this proposal fit well with the feel and direction of Swift?
- If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
- How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

More information about the Swift evolution process is available at

> [https://github.com/apple/swift-evolution/blob/main/process.md](https://github.com/apple/swift-evolution/blob/main/process.md)

Thank you,

Ben Cohen  
Review Manager

---

<div class="post-metadata">

**Author:** ![JuneBash](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/junebash/32/19323_2.png) [@JuneBash](https://forums.swift.org/u/JuneBash)\
**Post date:** [October 25, 2022, 6:32pm UTC](https://forums.swift.org/t/se-0377-borrow-and-take-parameter-ownership-modifiers/61020/2 "2022-10-25T18:32:09Z")

</div>

+1. I like this direction. My work currently makes use of a `BlockConfigurable` marker protocol that adds this method:

```swift
extension BlockConfigurable {
  func configure(_ apply: (inout Self) -> Void) -> Self {
    var copy = self 
    apply(&copy)
    return copy
  }
}

```

The copy that gets made there is, theoretically at least, not necessary. If I understand correctly, this proposal can make this more efficient.

```swift
extension BlockConfigurable {
  taking func configure(_ apply: (inout Self) -> Void) -> Self {
    apply(&self)
    return self
  }
}

```

---

<div class="post-metadata">

**Author:** ![cbarrett](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/cbarrett/32/7007_2.png) [@cbarrett](https://forums.swift.org/u/cbarrett)\
**Post date:** [October 25, 2022, 6:37pm UTC](https://forums.swift.org/t/se-0377-borrow-and-take-parameter-ownership-modifiers/61020/3 "2022-10-25T18:37:53Z")

</div>

Glad to see this work on move-only types start to make it towards shipping. I have a naming suggestion to throw onto the pile: Instead of borrow/borrowing and take/taking, spell them "use"/"using" and "own"/"owning" (not "owned"). ~~The SE-0366 proposal would probably have to use a different verb though (perhaps drop?).~~ Edit: I read the other proposal too hastily, I retract this bit.

---

<div class="post-metadata">

**Author:** ![masters3d](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@masters3d](https://forums.swift.org/u/masters3d)\
**Post date:** [October 25, 2022, 7:29pm UTC](https://forums.swift.org/t/se-0377-borrow-and-take-parameter-ownership-modifiers/61020/4 "2022-10-25T19:29:41Z")

</div>

> [@cbarrett](#):
>
> "own"/"owning"

+1 I like own/owning much better than take/taking

---

<div class="post-metadata">

**Author:** ![1-877-547-7272](https://avatars.discourse-cdn.com/v4/letter/1/278dde/32.png) [@1-877-547-7272](https://forums.swift.org/u/1-877-547-7272)\
**Post date:** [October 26, 2022, 6:35am UTC](https://forums.swift.org/t/se-0377-borrow-and-take-parameter-ownership-modifiers/61020/5 "2022-10-26T06:35:09Z")

</div>

This functionality is definitely needed for Swift, and it's good to see this being addressed.

That being said, I don't really like the use of 'take' for this kind of modifier. It feels weird to me that `take x` would end a variable's lifetime, while passing `x` to a `take` parameter wouldn't. Additionally, as Dave Abrahams [pointed out on the last thread](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581/130), function parameters are already described as 'taking': a function of type `(Int) -> Void` is described as **taking** an `Int`.

---

<div class="post-metadata">

**Author:** ![ebg](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ebg/32/23208_2.png) [@ebg](https://forums.swift.org/u/ebg)\
**Post date:** [October 26, 2022, 2:19pm UTC](https://forums.swift.org/t/se-0377-borrow-and-take-parameter-ownership-modifiers/61020/6 "2022-10-26T14:19:44Z")

</div>

I think the naming `take` and `borrow` are too simple, and should better convey that these are not features that should be regularly used and instead devs should continue to trust ARC in the vast majority of cases, similar to how dropping down to raw pointer APIs have "unsafe" prepended.

My worry is that with simple names there is an implication that we should be manually managing ownership because ARC is not able to optimize adequately, and we'll see this proliferate in codebases because obviously we should all want better memory usage, and then we're slowly (or quickly) drifting back to the pre-ARC retain/release days.

---

<div class="post-metadata">

**Author:** ![juliand665](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/juliand665/32/14212_2.png) [@juliand665](https://forums.swift.org/u/juliand665)\
**Post date:** [October 27, 2022, 3:00am UTC](https://forums.swift.org/t/se-0377-borrow-and-take-parameter-ownership-modifiers/61020/7 "2022-10-27T03:00:46Z")

</div>

I wonder if this could be helped by an `@` prefix, bringing it more inline with other features you should only use after looking up how they work.

---

<div class="post-metadata">

**Author:** ![lukasa](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lukasa/32/1232_2.png) [@lukasa](https://forums.swift.org/u/lukasa)\
**Post date:** [October 27, 2022, 10:40am UTC](https://forums.swift.org/t/se-0377-borrow-and-take-parameter-ownership-modifiers/61020/8 "2022-10-27T10:40:57Z")

</div>

I'm a +1 on this proposal. Having read it through I think it addresses a useful hole in the language, and we'd use it in a number of places throughout SwiftNIO.

---

<div class="post-metadata">

**Author:** ![Joannis\_Orlandos](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joannis_orlandos/32/732_2.png) [@Joannis\_Orlandos](https://forums.swift.org/u/Joannis_Orlandos)\
**Post date:** [October 27, 2022, 11:40am UTC](https://forums.swift.org/t/se-0377-borrow-and-take-parameter-ownership-modifiers/61020/9 "2022-10-27T11:40:52Z")

</div>

+1 from me, I've had a fair few use cases where I'd love to have more control over Swift making copies (or explicitly not). I think that `take` and `borrow` clearly state their intentions by themselves.

---

<div class="post-metadata">

**Author:** ![Max\_Desiatov](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/max_desiatov/32/20654_2.png) [@Max\_Desiatov](https://forums.swift.org/u/Max_Desiatov)\
**Post date:** [October 27, 2022, 12:21pm UTC](https://forums.swift.org/t/se-0377-borrow-and-take-parameter-ownership-modifiers/61020/10 "2022-10-27T12:21:40Z")

</div>

> [@ben-cohen](#):
>
> - What is your evaluation of the proposal?

+0.75, I like `borrow` naming, but I find `take` too broad and potentially confusing as a keyword. Maybe `own` is a better counterpart?

> [@](#):
>
> - Is the problem being addressed significant enough to warrant a change to Swift?
> - Does this proposal fit well with the feel and direction of Swift?

Yes, especially as a part of the Ownership Manifesto.

> [@](#):
>
> - If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

As far as I understand, this is not as advanced as the ownership model that Rust has. At the same time, I don't think there's a consensus that all of the decisions that Rust made in this area are overwhelmingly positive. The piecemeal and cautious approach that Swift takes feels right to me.

> [@](#):
>
> - How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

I've been following the Ownership Manifesto as it evolved and some of the pitch threads that were published prior to the proposal review.

---

<div class="post-metadata">

**Author:** ![asdf\_bro](https://avatars.discourse-cdn.com/v4/letter/a/8c91f0/32.png) [@asdf\_bro](https://forums.swift.org/u/asdf_bro)\
**Post date:** [October 27, 2022, 5:13pm UTC](https://forums.swift.org/t/se-0377-borrow-and-take-parameter-ownership-modifiers/61020/11 "2022-10-27T17:13:56Z")

</div>

I'm a -1 on this proposal. I think that it would result in the unnecessary proliferation of "borrow" and "take" throughout codebases. Most Swift developers don't know anything about parameter ownership today (excluding `inout`), but will start using "borrow" and "take" because they aren't scary, making many codebases slower because with copyable types the non-optimal passing convention still compiles.

In my view, a better design is:

- By default, all parameters are passed at +0 / shared to all functions, including initializers and setters

- A single new modifier, `sink`, which changes the passing convention to +1 / owned and makes the parameter mutable

Automatic memberwise initializers will use `sink` for every parameter. When explicitly writing initializers, IDEs will issue a warning when a parameter is simply stored to a member, but isn't marked `sink`. A similar warning will exist for setters too.

This may be source breaking, but I think it's worth it. Let's limit this to Swift 6 if necessary.

---

<div class="post-metadata">

**Author:** ![dabrahams](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dabrahams/32/9815_2.png) [@dabrahams](https://forums.swift.org/u/dabrahams)\
**Post date:** [October 27, 2022, 6:06pm UTC](https://forums.swift.org/t/se-0377-borrow-and-take-parameter-ownership-modifiers/61020/12 "2022-10-27T18:06:27Z")

</div>

I’ll just repeat something I’ve tried to say before: we should find our way to a future where “borrow” doesn’t need to be written at all. For copyable types there’s no difference between borrowing and pass-by-copying-a-value, and for noncopyable types the latter doesn’t exist. When do you ever want to pass by implicit copy? I say never.

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [October 27, 2022, 8:33pm UTC](https://forums.swift.org/t/se-0377-borrow-and-take-parameter-ownership-modifiers/61020/13 "2022-10-27T20:33:21Z")

</div>

> [@dabrahams](#):
>
> I’ll just repeat something I’ve tried to say before: we should find our way to a future where “borrow” doesn’t need to be written at all. For copyable types there’s no difference between borrowing and pass-by-copying-a-value, and for noncopyable types the latter doesn’t exist. When do you ever want to pass by implicit copy? I say never.

`borrow` will still be the default in almost all cases, so you shouldn't have to write it much. The alternative to `borrow` isn't pass-by-copying, it's pass-by-ownership-transfer (what we call `take` in the proposal). Whether the caller makes a copy or not is an orthogonal decision made by the caller, and there are reasons we'd do so for both borrowed and taken parameters—to avoid aliasing writes to shared mutable state in the former case, or to preserve the lifetime of a value the caller either still needs to keep around for itself, or doesn't have ownership of in the first place, in the latter. Stay tuned for future proposals if you want to hear about controlling or preventing implicit copies.

---

<div class="post-metadata">

**Author:** ![dabrahams](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dabrahams/32/9815_2.png) [@dabrahams](https://forums.swift.org/u/dabrahams)\
**Post date:** [October 28, 2022, 5:00pm UTC](https://forums.swift.org/t/se-0377-borrow-and-take-parameter-ownership-modifiers/61020/14 "2022-10-28T17:00:11Z")

</div>

> `borrow` will still be the default in almost all cases

Huh, maybe I have misunderstood all along. I didn't think `borrow` was currently the default; my understanding was that retains are omitted but for small types, bits might be copied. I guess that's not distinguishable from `borrow` for copiable types which I guess is what I was saying.

> so you shouldn't have to write it much

So the only place you'd be writing it is, e.g. for initializer parameters that you don't want to consume?

That sounds pretty good!

> to avoid aliasing writes to shared mutable state in the former case

Sorry, I don't quite see how that plays out. We're talking about copies implicitly generated by the compiler, but a `borrowed` variable is immutable, so you can only mutate a different variable; if there's a copy involved it seems like it would have to be made explicitly by the user. And if you mean it's sharing state behind-the-scenes, no amount of copying will avoid the aliasing. Could you explain?

> to preserve the lifetime of a value the caller either still needs to keep around for itself, or doesn't have ownership of in the first place, in the latter

That makes total sense; it's a place we'd be telling the user to make an explicit copy in Val (unless they turn on `@implicitcopy`). Maybe the models are closer than I thought. /cc @Alvae

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [October 28, 2022, 7:02pm UTC](https://forums.swift.org/t/se-0377-borrow-and-take-parameter-ownership-modifiers/61020/15 "2022-10-28T19:02:44Z")

</div>

> [@dabrahams](#):
>
> Huh, maybe I have misunderstood all along. I didn't think `borrow` was currently the default; my understanding was that retains are omitted but for small types, bits might be copied. I guess that's not distinguishable from `borrow` for copiable types which I guess is what I was saying.

> [@dabrahams](#):
>
> Sorry, I don't quite see how that plays out. We're talking about copies implicitly generated by the compiler, but a `borrowed` variable is immutable, so you can only mutate a different variable; if there's a copy involved it seems like it would have to be made explicitly by the user. And if you mean it's sharing state behind-the-scenes, no amount of copying will avoid the aliasing. Could you explain?

You are right that, from the callee's perspective, the borrowed parameter value is always an immutable value (well, shared-borrow, which is the same most of the time). The "do we retain/copy or not" negotiation happens primarily on the caller side, though. If the argument is known to untouched by anyone else for the duration of a call, then the caller can pass its value along without any copies or retains, which should happen for unescaped local variables, parameters, and `let` constants:

```swift
class Foo {}

func callee(_: Foo) {}

let globalLet = Foo()

func caller(param: Foo) {
  let local = Foo()
  var localVar = Foo()

  // We shouldn't need to retain/release for any of these calls:
  callee(local)
  callee(param)
  callee(globalLet)
  callee(localVar)
}

```

If there's a potential for the argument to be modified during a call, though, then we have to copy or retain in order to safely maintain the illusion of pass-by-value. This happens with mutable globals and class ivars, since we don't usually know whether the callee turns around and calls something that touches those, as well as if you try to pass a mutable variable by-value and by-inout simultaneously:

```swift
class FooBox {
  var foo: Foo
}

var globalVar = Foo()

func mixedCallee(_: Foo, _: inout Foo) {}

func caller2(boxParam: FooBox) {
  var localVar = Foo()
  // This has to retain, to resolve the exclusive/shared conflict
  mixedCallee(localVar, &localVar)
  // These probably retain (but might not with enough effects analysis…)
  callee(boxParam.foo)
  callee(globalVar)
}

```

For copyable types, `borrow` vs. `take` on the parameter doesn't have a huge effect on whether these copies are necessary or not; `take` introduces the ability to forward ownership for the last use of a value, but conversely, requires a caller to also copy for any non-final uses of the value. In Swift, we've already made our bed more or less with how copyable types work, so the way I see to eliminate these kinds of implicit copies is to provide ways for the code in the caller to opt out of implicit copying, and require explicit copies in situations like `mixedCallee(localVar, &localVar)` that obviously violate exclusivity without a copy, and/or specify that we aren't concerned about aliasing writes to objects or global variables at certain call sites, and it's OK to borrow their values in place (and trap if someone does come and try to rewrite the value during the access).

---

<div class="post-metadata">

**Author:** ![Nobody1707](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nobody1707/32/2169_2.png) [@Nobody1707](https://forums.swift.org/u/Nobody1707)\
**Post date:** [October 28, 2022, 9:41pm UTC](https://forums.swift.org/t/se-0377-borrow-and-take-parameter-ownership-modifiers/61020/16 "2022-10-28T21:41:42Z")

</div>

+1 This looks good to me. I like the new `borrow`/`take`/`taking` naming scheme.

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [November 7, 2022, 2:10am UTC](https://forums.swift.org/t/se-0377-borrow-and-take-parameter-ownership-modifiers/61020/17 "2022-11-07T02:10:39Z")

</div>

I’m generally in favor of this and can already think of a few specific locations where this would improve performance in a meaningful way (when coupled with `take` expressions), even without any further language changes. Also very excited about the general progress towards move-only types.

> Inside of a function or closure body, `take` parameters may be mutated, as can the `self` parameter of a `taking func` method.

I feel like this isn’t necessarily justified; while it is just as _reasonable_ to mutate a `take` parameter as a local `var`, I don’t think it makes sense for that to be the default. With locals we still encourage `let` over `var`, and `take` doesn’t imply “mutation” to me. Certainly the implicit uses of the `take` convention today aren’t about mutating the value; they’re about storing it. Similarly, the use case I have in mind is purely about allowing the parameter to be destroyed sooner, avoiding having to wait for a deep stack to return.

I suppose you can always convert from one form to another by `take`ing into a local, but I don’t think `take` should imply mutability like `var` and `inout` do. I’d rather see a (separate) proposal to revert SE-0003 and revive `var` on parameters if we think this is interesting, noting that SE-0031 moved `inout` to the “type” side of the parameter declaration since SE-0003 was reviewed.

> `take` cannot be applied to parameters of nonescaping closure type, which by their nature are always borrowed

The full form of a non-optional `take` closure parameter would thus be `callback: take @escaping () -> Void`, which is pretty verbose. (Or is it `@escaping take () -> Void`?) Given that escaping pretty much implies that a copy will be made anyway, does it make sense for `take` to _imply_ `@escaping`, as `inout` already does today? That still leaves the occasional `borrow @escaping () -> Void` for where an escaping closure parameter might normally be `take`n, but that seems pretty rare to me; the main place where I could see it being useful is if the closure is only escaped _some_ of the time.

On the implementation side: are non-escaping closure parameters passed `borrow` or `take` to initializers today? I would hope `borrow` even though the usual convention for initializer parameters is `take`, for the reasons discussed in this proposal, but if not this could be a good opportunity to fix some conventions (where not ABI-breaking).

Additionally, I remember the first implementation of ` __owned` and `__ shared` affecting a function’s mangled name even if the convention matches the implicit default for that parameter. Does that behavior extend to `take` and `borrow`, and if not…I guess there’ll be a special opt-out or shim for the stdlib, to use the explicit mangling where an implicit one would have done?

Again, very excited about all this! Thank you Michael, Joe, and everyone working on this.

---

<div class="post-metadata">

**Author:** ![FranzBusch](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/franzbusch/32/19447_2.png) [@FranzBusch](https://forums.swift.org/u/FranzBusch)\
**Post date:** [November 7, 2022, 10:15am UTC](https://forums.swift.org/t/se-0377-borrow-and-take-parameter-ownership-modifiers/61020/18 "2022-11-07T10:15:36Z")

</div>

I am +1 on this proposal. But I have one open question about closure capture lists. Is it possible to have `take/borrow` modifiers on capture list elements? We had this discussion over in [this thread](https://forums.swift.org/t/passing-asynciterator-to-an-async-method/61267/) where we were talking about a safe way to pass `AsyncIterator`s between `Task`s while retaining the 1:1 relation ship.

---

<div class="post-metadata">

**Author:** ![SwiftButLazy](https://avatars.discourse-cdn.com/v4/letter/s/f17d59/32.png) [@SwiftButLazy](https://forums.swift.org/u/SwiftButLazy)\
**Post date:** [November 7, 2022, 10:33am UTC](https://forums.swift.org/t/se-0377-borrow-and-take-parameter-ownership-modifiers/61020/19 "2022-11-07T10:33:02Z")

</div>

> [@dabrahams](#):
>
> I’ll just repeat something I’ve tried to say before: we should find our way to a future where “borrow” doesn’t need to be written at all. For copyable types there’s no difference between borrowing and pass-by-copying-a-value, and for noncopyable types the latter doesn’t exist. When do you ever want to pass by implicit copy? I say never.

I agree with this, the default should be borrow and Swift code with the borrow keyword everywhere would be unbearably ugly. However, don't we need some attribute declaring if it is a mutable or immutable borrow or is this covered by inout? Take passing is more rare and you also appreciate that badging because then you know that the function will take hold of that resource.

Is there a way to declare per function or even entire files that you want to use the borrow/take feature?

---

<div class="post-metadata">

**Author:** ![ibex](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ibex/32/30439_2.png) [@ibex](https://forums.swift.org/u/ibex)\
**Post date:** [November 7, 2022, 12:15pm UTC](https://forums.swift.org/t/se-0377-borrow-and-take-parameter-ownership-modifiers/61020/20 "2022-11-07T12:15:51Z")

</div>

> ```swift
> struct Foo {
> taking func foo() // `take` ownership of self
> borrowing func foo() // `borrow` self
> mutating func foo() // `modify` self with `inout` semantics
> }
> 
> ```

Yuck! ☹

This looks much better:

```swift
struct Foo {
   func foo() takes // `take` ownership of self
   func foo() borrows // `borrow` self
   func foo() mutates // `modify` self with `inout` semantics
}

```

[Next page](https://forums.swift.org/t/se-0377-borrow-and-take-parameter-ownership-modifiers/61020.md?page=2)
