# \`borrow\` and \`take\` parameter ownership modifiers

**URL:** <https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581>\
**Category:** Pitches\
**Created:** [August 11, 2022, 1:43am UTC](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581 "2022-08-11T01:43:12Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [August 13, 2022, 7:43pm UTC](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581/42 "2022-08-13T19:43:49Z")

</div>

> [@michelf](#):
>
> This implies an error if the function declares parameter `x` as `borrow`, right? The other possibility is that it ends the lifetime of variable `x` immediately after the call stops borrowing it, which I think is what `move x` would have done in the earlier proposal. I think the distinction is important. Call-side `take` is anchored at the call site and must align with the function declaration, whereas `move` can occur anywhere regardless of whether it makes sense in relation to the function call.

> [@Andrew\_Trick](#):
>
> Yes, that design is the most straightforward and consistent with the source compatibility goals. For copyable types, that _will_ end up passing a copy of the variable to the callee. Some have objected to this behavior though because it probably wasn't the author's intention.

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:

```swift
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`:

```swift
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.

---

<div class="post-metadata">

**Author:** ![jayton](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jayton/32/5592_2.png) [@jayton](https://forums.swift.org/u/jayton)\
**Post date:** [August 14, 2022, 11:25am UTC](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581/43 "2022-08-14T11:25:56Z")

</div>

It seems reasonable for `borrow` to be able to fulfil _both_ `take` and `inout`, since there’s a trivial meaning to it that doesn’t abandon any information, and Swift introduces implicit thunks between basically-compatible-but-technically-different function types all over the place.

`inout` shouldn’t be able to fulfil `take` or `borrow` because the output value would be silently discarded, as if it was `@discardableResult`.

`take` could trivially fulfil `borrow` or `inout` today (with a thunk adding an implicit copy), but that will break with move-only types.

---

<div class="post-metadata">

**Author:** ![michelf](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/michelf/32/1180_2.png) [@michelf](https://forums.swift.org/u/michelf)\
**Post date:** [August 14, 2022, 12:00pm UTC](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581/44 "2022-08-14T12:00:51Z")

</div>

> [@jayton](#):
>
> `take` could trivially fulfil `borrow` or `inout` today (with a thunk adding an implicit copy), but that will break with move-only types.

I think `take x` should produce a temporary move-only value.

For instance, a `take x` expression could produce a `@moveonly X`, where `@moveonly` is a type modifier preventing `X`–which is copiable–from being implicitly copied. The `@moveonly` modifier disappears when assigned to a variable, and it also disappears once passed to another function. It's simply a flag attached to the return value that would prevent the compiler from making a copy before the value is passed somewhere else, as if the returned `X` was, for a moment, a move-only type.

This way the expectation that `take x` will prevent copying is fulfilled.

(A precedent would be `X!` which is in reality type `X?` with a special behavior attached to it, but where the behavior isn't otherwise propagated with the type.)

---

<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:** [August 15, 2022, 6:10pm UTC](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581/45 "2022-08-15T18:10:41Z")

</div>

> [@michelf](#):
>
> This implies an error if the function declares parameter `x` as `borrow`, right? The other possibility is that it ends the lifetime of variable `x` immediately after the call stops borrowing it, which I think is what `move x` would have done in the earlier proposal. I think the distinction is important. Call-side `take` is anchored at the call site and must align with the function declaration, whereas `move` can occur anywhere regardless of whether it makes sense in relation to the function call.

I don't think we want to have too many different modifiers here, so it'd be good to pick one name and one semantics. I can see how it's appealing to require `take x` in an expression to match a `take T` parameter, though I am concerned about the added source breakage hazard this creates for source-only packages that want to adjust their API conventions. Possibly one compromise we could make is to have it so that using `take x` as an argument to a function in the same module that isn't explicitly `take` becomes a warning, since that's more likely to be in the developer's control to change.

Note also that passing `take x` as an argument that happens to be borrowed should still always avoid copying, since if `x` is a valid operand to `take`, we can end its lifetime in the caller immediately after the call regardless. The only inefficiency in this case is that the destruction of the argument has to happen in the caller after the call. (Conversely, passing an intended borrow to a `take` parameter would necessitate a copy, since the callee wants to consume the parameter but the caller wants to keep the value alive for its own continued use.)

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [August 15, 2022, 6:41pm UTC](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581/46 "2022-08-15T18:41:58Z")

</div>

> [@Joe\_Groff](#):
>
> Note also that passing `take x` as an argument that happens to be borrowed should still always avoid copying, since if `x` is a valid operand to `take`, we can end its lifetime in the caller immediately after the call regardless. The only inefficiency in this case is that the destruction of the argument has to happen in the caller after the call.

a lot of times the callee wants to mutate the argument like

```swift
func renderCitiesList(_ cities:__shared [City.ID: City]) -> HTML 
{
    var cities:[City.ID: City] = _move cities
        cities.removeValue(forKey: self.hometown)
    return HTML.render(cities: cities)
}

```

so calling `renderCitiesList(_:)` makes a copy even if you remember to `_move`

```swift
self.html = context.renderCitiesList(_move cities)

```

of course this is not `_move`’s fault it is `renderCitiesList(_:)`’s fault because it is ` __shared` when it should be `__ owned` but `__shared` is the default, and a lot of times i write `_move` and i think i solved the problem when in fact i did not which is why i feel like it is a footgun.

* * *

UPDATE: this example is now [forbidden](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581/56) by the compiler, so it is no longer an issue. it might still happen if you do not use `_move` and rely on the compiler to optimize the local variables, which it will not. but the `_move` will generate an error and tell you that the `__shared` is wrong, which helps.

---

<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:** [August 15, 2022, 6:57pm UTC](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581/47 "2022-08-15T18:57:54Z")

</div>

> [@taylorswift](#):
>
> of course this is not `_move`’s fault it is `renderCitiesList(_:)`’s fault because it is ` __shared` when it should be `__ owned` but `__shared` is the default, and a lot of times i write `_move` and i think i solved the problem when in fact i did not which is why i feel like it is a footgun.

This seems like a reasonable situation to warn/error about too, since in this case the source of the mismatch is even more localized than the case where you're trying to call some other function with an uncooperative convention.

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [August 15, 2022, 7:27pm UTC](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581/48 "2022-08-15T19:27:57Z")

</div>

I wish it was possible writing that efficiently without "move", but with some sort of "lazy", or similar to "drop", so there is no copy done at any point. Pseudocode of simplified version ahead:

```swift
func render(cities: TBD) {
    cities.forEach {
        ... /* doesn't contain hometown */
    }
}

func renderCitiesList(cities: [ID: City]) {
    render(cities.lazy.removingValue(forKey: hometown))
    // alternatively:
    render(cities.droppingValue(forKey: hometown))
}

let cities: [ID: City] = ...
renderCitiesList(cities)

```

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [August 15, 2022, 7:38pm UTC](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581/49 "2022-08-15T19:38:10Z")

</div>

this will be slower if `City.ID.==(_:_:)` is expensive because instead of hashing and comparing expected O(1)’nce you are comparing `cities.count` times. but you are right if `City.ID` is `Int` or something this would be preferable and have less mutation.

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [August 15, 2022, 8:05pm UTC](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581/50 "2022-08-15T20:05:29Z")

</div>

Presumably "render(cities: TBD)" is O(N) anyway? (it wasn't shown so I've guesstimated). So the resulting algorithm O-big complexity is unchanged. You are correct that with slow hash/EQ it's inferior (still O(n) just with an extra big factor for N).

---

<div class="post-metadata">

**Author:** ![disc0infern0](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/disc0infern0/32/22597_2.png) [@disc0infern0](https://forums.swift.org/u/disc0infern0)\
**Post date:** [August 15, 2022, 10:18pm UTC](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581/51 "2022-08-15T22:18:37Z")

</div>

I type this as a relative novice with Swift, though earlier in my career I may have been considered somewhat expert in 'C'.  
To begin, I cannot disagree objectively with anything written above, though much of it goes further into the workings of the compiler than I typically care to venture.

One thing strikes me though, and that is that this proposal adds a fine degree of control to how code will be run by the compiler, at the expense of adding low level complexity to the language.  
Coming from C, one thing I have appreciated about Swift is that it mostly made sense - and looking at someone else's code, it was generally possible to get a good understanding of what it was doing. C can be justly criticised for making it far too easy to write wonderfully obfuscated code that would take an awful lot of deciphering. I fear, it is now becoming all too easy in Swift also.

As time has moved on, Swift has adopted many language features from .. other languages, because developers used them in those other languages, and want those features in Swift. That's not unreasonable, but .. and this is a big but.. is there a body in [Swift.org](http://Swift.org) that is looking at how to keep Swift "simple" or "compact", and in fact looking at ways to reduce the language by improving the compiler decisions? [Aside: Who is Swift's intended audience? Do we want to cover all the bases for everyone from high level designers to assembly language programmers ?]

On a site like medium, I read a post recently from a C# developer who was despairing of the language evolution, where more and more complexity was being added, with the result that there were now so many corners of the language that debugging and supporting someone else's code could be nightmarish. I wouldn't want that to happen to Swift, which has started out life with a wonderful elegance, whilst still being performant.

So in summary, I understand the desire for this feature, however I wanted to raise the burden of language complexity that we might be layering on.  
I also wanted to make a plea for the group to keep, if not simplicity (incredibly hard to define) but perhaps 'compactness' as a design goal, so that there aren't too many dark corners of the language that barely anyone knows are there, let alone understands.

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [August 15, 2022, 10:44pm UTC](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581/52 "2022-08-15T22:44:57Z")

</div>

> [@Joe\_Groff](#):
>
> This seems like a reasonable situation to warn/error about too, since in this case the source of the mismatch is even more localized than the case where you're trying to call some other function with an uncooperative convention.

Right, this should just be illegal because you can't move from a non-owning binding.

---

<div class="post-metadata">

**Author:** ![Michael\_Gottesman](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/michael_gottesman/32/280_2.png) [@Michael\_Gottesman](https://forums.swift.org/u/Michael_Gottesman)\
**Post date:** [August 16, 2022, 12:43am UTC](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581/53 "2022-08-16T00:43:34Z")

</div>

FYI, You do get an error here today with the shared argument:

```swift
test.swift:13:34: error: _move applied to value that the compiler does not support checking
    var cities:[City.ID: City] = _move cities
                                 ^

```

which is due to the shared. Now the error msg could be improved, but still it isn't accepted today.

---

<div class="post-metadata">

**Author:** ![Dmitriy\_Ignatyev](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dmitriy_ignatyev/32/11340_2.png) [@Dmitriy\_Ignatyev](https://forums.swift.org/u/Dmitriy_Ignatyev)\
**Post date:** [August 16, 2022, 6:41am UTC](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581/54 "2022-08-16T06:41:40Z")

</div>

> [@Joe\_Groff](#):
>
> When you take implicit copying away, the parameter not just _can_ take the argument, it _must_.

> [@Jon\_Shier](#):
>
> I like `own` instead of `take`, so wouldn't this be `own / borrow` and `ownable / borrowable` or `owned / borrowed`? Personally I don't think the correctness of the grammar is the issue here, so a single set of modifiers would be fine to me.

+1. I like the idea of owned / borrowed words for parameter modifiers. Own is more understandable because:

- `own` word is rarely used, while `take` is a common name – take(prefix:), take(while:), take(until:), take(after:)...
- `own` more precisely describe what it does

In my opinion this also solves great what @beccadax posted above. At the call site we write own / borrow.

`func foo(_ val: own T)`  
`foo(owned x)`

---

<div class="post-metadata">

**Author:** ![michelf](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/michelf/32/1180_2.png) [@michelf](https://forums.swift.org/u/michelf)\
**Post date:** [August 16, 2022, 12:49pm UTC](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581/55 "2022-08-16T12:49:40Z")

</div>

> [@Joe\_Groff](#):
>
> I don't think we want to have too many different modifiers here, so it'd be good to pick one name and one semantics. I can see how it's appealing to require `take x` in an expression to match a `take T` parameter, though I am concerned about the added source breakage hazard this creates for source-only packages that want to adjust their API conventions.

I agree. I was not suggesting having both `move` (general expression) and `take` (call-site modifier only), only pointing out the broken expectations of either approaches. I think I managed to find a solution [a bit later](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581/44): an expression producing a temporary move-only value.

---

<div class="post-metadata">

**Author:** ![Michael\_Gottesman](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/michael_gottesman/32/280_2.png) [@Michael\_Gottesman](https://forums.swift.org/u/Michael_Gottesman)\
**Post date:** [August 16, 2022, 11:31pm UTC](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581/56 "2022-08-16T23:31:43Z")

</div>

Question. Can you edit this post above to say that this is actually not an issue since move doesn't work on shared? Otherwise I am worried that my response (that it can't happen) will get lost in the thread and create confusion.

---

<div class="post-metadata">

**Author:** ![viktorcode](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/viktorcode/32/7737_2.png) [@viktorcode](https://forums.swift.org/u/viktorcode)\
**Post date:** [August 17, 2022, 12:43pm UTC](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581/57 "2022-08-17T12:43:27Z")

</div>

There's no mention on how would we change setters with the modifiers. Are setters must always adhere to default `take` behaviour?

---

<div class="post-metadata">

**Author:** ![Alvae](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/alvae/32/37012_2.png) [@Alvae](https://forums.swift.org/u/Alvae)\
**Post date:** [August 17, 2022, 4:00pm UTC](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581/58 "2022-08-17T16:00:03Z")

</div>

That's a very interesting pitch!

I'd like to throw here that I'm working with @dabrahams and a handful of other people on a Swift-inspired language that adopted this approach at its core: [Val](https://www.val-lang.dev/pages/language-tour.html#parameter-passing-conventions).

Val has four passing conventions: `inout`, which works almost exactly like Swift, `let` and `sink`, which correspond to this pitch's `borrow` and `take`, respectively, and `set`. We found that the latter completes the calculus when we consider accessors in subscripts, or the convention of `self` in an initializer. A `set` parameter is considered uninitialized at the beginning of the function/subscript and must be guaranteed initialized before the function/subscript returns.

There are a couple of observations we made with Val that I think are relevant to the current discussion.

> It could alternatively be argued that explicitly stating the convention for a value argument indicates that the developer is interested in guaranteeing that the optimization occurs [...] We believe that it is better to keep the behavior of the call in expressions independent of the declaration [...], and that explicit operators on the call site can be used in the important, but relatively rare, cases where the default optimizer behavior is insufficient to get optimal code.

I am not thrilled at the idea to use operators at the call site to just help the optimizer do something I believe it can do on its own if the language gives reasonable guarantees.

Val has a very transparent cost model that actually frees the user from constantly worrying about what the optimizer will be able to do. That transparency is based on the fact that an API documents a clear intent. I argue that it's likely that API consumers will want to leverage that intent rather than guessing how to best guide the optimizer at the call site (see the example at the end).

Val predictably choses how to pass arguments depending on the way they are used in the caller. Perhaps that philosophy clashes with the goals of [SE-0366](https://github.com/apple/swift-evolution/blob/main/proposals/0366-move-function.md), but I worry that multiplying operators will unjustifiably make writing efficient Swift more complex.

> Alternatively, we could explore schemes to allow the `self` parameter to be declared explicitly, which would allow for the `take` and `borrow` modifiers as proposed for other parameters to also be applied to an explicit `self` parameter declaration.

We've done that with Val. It turns out `take` methods are very interesting in the context of value semantics, as a way to "destructure" non-copyable types.

> [...] it may be a reasonable default to have it so that `take` parameters are internally mutable.

We've had that discussion during the development of Val. As it turns out, making `take` parameters mutable in the callee makes a lot of sense in terms of the calculus. The parameter passing conventions offer different, escalating levels of privileges:

1. `borrow` parameters just let you read a value;
2. `inout` parameters let you modify it; and
3. `take` parameters let you do whatever you want with it, including having them escape.

> [A protocol] requirement may still be satisfied by an implementation that uses different conventions for parameters of copyable types

> Function values can also be implicitly converted to function types that change the convention of parameters of copyable types among unspecified, `borrow`, or `take`

Parameter conventions relate to the correspondence between functional updates (e.g., `x = f(x)`) and in-place updates (e.g., `f'(&x)`). Because of that relationship, it is easy to synthesize an in-place operation from a functional update, and vice-versa. So I believe function values could also convert a `take` convention to an `inout` one, and vice-versa, even for non-copyable types. That's what Val does in [method bundles](https://www.val-lang.dev/pages/language-tour.html#method-bundles).

Finally, the pitch points out that, by carefully choosing the parameter convention that we use, we can also avoid unnecessary allocations without relying on optimizer heroics. It follows that it might be interesting to implement the same operation with different conventions and let the user (but ideally the compiler) choose the most appropriate version depending on the context in which the operation is used.

To illustrate, consider this program:

```swift
typealias Vec2 = (x: Double, y: Double)
struct Polygon {
  var vertices: [Vec2]
}

func offset(_ shape: borrow Polygon, by delta: Vec2) -> Polygon { ... }
func offset(_ shape: take Polygon, by delta: Vec2) -> Polygon { ... }

let ngon = Polygon(vertices: ...)
print(offset(take ngon, by: (x: 10, y: 10)))

```

Here, we're better off using the first `offset` function to avoid leaving to the optimizer the task to eliminate the unnecessary allocation that would be caused by the first one.

It would be nice if we didn't have to add a `take` operator at the call site though. The compiler could select the right implementation on its own by realizing that `ngon` is no longer used after the call.

---

<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:** [August 17, 2022, 4:27pm UTC](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581/59 "2022-08-17T16:27:58Z")

</div>

Thanks for your insights @Alvae!

> [@Alvae](#):
>
> Val has four passing conventions: `inout`, which works almost exactly like Swift, `let` and `sink`, which correspond to this pitch's `borrow` and `take`, respectively, and `set`. We found that the latter completes the calculus when we consider accessors in subscripts, or the convention of `self` in an initializer. A `set` parameter is considered uninitialized at the beginning of the function/subscript and must be guaranteed initialized before the function/subscript returns.

`set` seems like it's isomorphic to a return value. In Swift, `self` in an initializer is effectively a named return slot, and indirect returns are implemented at the ABI level by destination-passing, so that a caller can pass the intended destination for a return value directly. Are there reasons to have syntactically `out` parameters that aren't returns?

> [@Alvae](#):
>
> I am not thrilled at the idea to use operators at the call site to just help the optimizer do something I believe it can do on its own if the language gives reasonable guarantees.
> 
> Val has a very transparent cost model that actually frees the user from constantly worrying about what the optimizer will be able to do. That transparency is based on the fact that an API documents a clear intent. I argue that it's likely that API consumers will want to leverage that intent rather than guessing how to best guide the optimizer at the call site (see the example at the end).

Nothing here prevents us from making the optimizer better too, and nothing obligates you to use the operators if you trust the compiler to do the right thing. Swift does have to deal with the reality of heavily object-oriented APIs, so we have some incidental complexity that prevents us from making absolute no-exceptions guarantees we'd like to, but I think we can still do pretty well in the end. We are also working out the model that allows for the most implicit optimization for value-oriented code without breaking people's ability to work naturally with objects.

Note that, even if you do have hard optimization guarantees, it is still often useful to make guarantees that you're relying on explicit. Most functional languages guarantee tail call optimization when a call is in tail position, but developers still make the mistake of assuming a call is in tail position when it isn't and breaking the intended complexity of the algorithm they wrote. So many of those languages also have an explicit `tail` annotation (or their users pine hopelessly for it in the face of their language designers' purity). Explicit moves are basically the data analog to tail call optimization for code.

---

<div class="post-metadata">

**Author:** ![ksluder](https://avatars.discourse-cdn.com/v4/letter/k/eada6e/32.png) [@ksluder](https://forums.swift.org/u/ksluder)\
**Post date:** [August 17, 2022, 4:42pm UTC](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581/60 "2022-08-17T16:42:37Z")

</div>

> [@Joe\_Groff](#):
>
> Explicit moves are basically the data analog to tail call optimization for code.

But must the sentinel be built into the language? There are possible designs in which the sentinel is delivered as an API—whether a standard library function or otherwise. That’s why I kept harping on `move(_:)`-as-function in the previous review thread.

---

<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:** [August 17, 2022, 5:00pm UTC](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581/61 "2022-08-17T17:00:31Z")

</div>

> [@Alvae](#):
>
> I am not thrilled at the idea to use operators at the call site to just help the optimizer do something I believe it can do on its own if the language gives reasonable guarantees.
> 
> Val has a very transparent cost model that actually frees the user from constantly worrying about what the optimizer will be able to do. That transparency is based on the fact that an API documents a clear intent. I argue that it's likely that API consumers will want to leverage that intent rather than guessing how to best guide the optimizer at the call site (see the example at the end).

The overall direction I see in this pitch and [SE-0366](https://github.com/apple/swift-evolution/blob/main/proposals/0366-move-function.md) seems to reflect an effort to give the beginning programmer an illusion that the difference between `borrow` and `take` is not fundamental (despite the very real need for `@escaping`). IMO that will result in a more complex language overall, reflected in part by the spurious distinctions `take` vs. `@escaping` and `borrow` vs. ordinary pass-by-value, and in the use of call-site annotations in “expert” code.

Question for Swift designers: is it useful for us to discuss Val's approach in these forums? I think we're onto something that _could_ benefit Swift greatly, but we don't want to just be a distraction.

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

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