# Selective control of implicit copying behavior: \`take\`, \`borrow\`, and \`copy\` operators, \`@noImplicitCopy\`

**URL:** <https://forums.swift.org/t/selective-control-of-implicit-copying-behavior-take-borrow-and-copy-operators-noimplicitcopy/60168>\
**Category:** Pitches\
**Created:** [September 7, 2022, 5:40pm UTC](https://forums.swift.org/t/selective-control-of-implicit-copying-behavior-take-borrow-and-copy-operators-noimplicitcopy/60168 "2022-09-07T17:40:48Z")\
**Posts on this page:** 20\
**Page:** 1

<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:** [September 7, 2022, 5:40pm UTC](https://forums.swift.org/t/selective-control-of-implicit-copying-behavior-take-borrow-and-copy-operators-noimplicitcopy/60168/1 "2022-09-07T17:40:48Z")

</div>

During the [first review of SE-0366](https://forums.swift.org/t/se-0366-move-function-use-after-move-diagnostic/59202), we got a lot of feedback asking for more context about where it fits in our broader plans for ownership and performance control. I recently began a [pitch for ownership modifiers on function parameters](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581), which fill out our ability to control ownership across function boundaries, and I'd like to re-pitch the take/move operator as part of a collection of mechanisms for controlling ownership and copying within a function body:

- the `take` operator, which explicitly ends the lifetime of a parameter or local variable (which was reviewed as `move` in SE-0366)
- the `borrow` operator, which explicitly passes a property or variable by borrow without copying
- an attribute for suppressing all implicit copying when working with a parameter or local variable, which I'll call `@noImplicitCopy` to begin with

The `take` and `borrow` operators provide tools for refining Swift's implicit behavior in common isolated situations, without changing the overall programming model in surrounding code. `@noImplicitCopy`, by contrast, fully suppresses implicit copying and requires working with affected values like a move-only type, maximizing control but requiring a more drastic shift in the programming model.

Note that we're not proposing these features to be a replacement for move-only types or for other systems programming features, nor will we stop improving optimization and solidifying the language model to make stronger guarantees about copying behavior. Even if future implementation improvements make these explicit controls less necessary to get optimal behavior, the annotations will still serve a useful purpose as a tool for performance sensitive developers to check their work, and for readers and maintainers of code to understand performance sensitivities in code that they should preserve. We also want to ensure that these features can be deployed to fine-tune sensitive parts of a codebase without virally reshaping the programming model of surrounding Swift code, allowing for other developers to continue being productive even if they aren't familiar with the fine details of ARC and implicit copying.

### `take` operator

Proposal: [SE-0366](https://github.com/apple/swift-evolution/blob/main/proposals/0366-move-function.md)

it is useful to have an operator that explicitly ends the lifetime of a variable before the end of its scope. This allows the compiler to reliably destroy the value of the variable or transfer ownership of the value at the point of its last use, without depending on optimization and vague ARC optimizer rules. Consider this example:

```swift
func test() {
  var x: [Int] = getArray()
  
  // x is appended to. After this point, we know that x is unique.
  // We want to preserve that property.
  x.append(5)
  
  // We create a new variable y so we can write an algorithm
  // where we may change the value of y (causing a COW copy
  // of the buffer shared with x).
  var y = x
  longAlgorithmUsing(&y)
  consumeFinalY(y)

  // We no longer use y after this point. Ideally, x would
  // be guaranteed unique so we know we can append again
  // without copying.
  x.append(7)
}

```

In the example above, `y`'s formal lifetime extends to the end of scope. When we go back to using `x`, although the compiler may optimize the actual lifetime of `y` to release it after its last use, there isn't a strong guarantee that it will. Even if the optimizer does what we want, programmers modifying this code in the future may introduce new references to `y` that inadvertently extend its lifetime and break our attempt to keep `x` unique. There isn't any indication in the source code that that the end of `y`'s use is important to the performance characteristics of the code. We can introduce an operator to make that explicit:

```swift
func test() {
  var x: [Int] = getArray()
  
  // x is appended to. After this point, we know that x is unique.
  // We want to preserve that property.
  x.append(5)
  
  // We create a new variable y so we can write an algorithm
  // where we may change the value of y (causing a COW copy
  // of the buffer shared with x).
  var y = x
  longAlgorithmUsing(&y)
  // We no longer use y after this point, so we tell the
  // last use to take ownership.
  consumeFinalY(take y)

  // x will be unique again here.
  x.append(7)
}

```

Note that `take y` does not directly correspond to a retain or release of `y`. By shortening the lifetime of the value of `y`, the compiler is allowed to avoid retains and releases it might otherwise have made to keep a copy of `y` available in the caller. The compiler may or may not release the value of `y` at the point of `take y`, depending on whether the use site is able to take ownership of the value or not.

The `take y` operator syntax deliberately mirrors the proposed [ownership modifier](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581) parameter syntax, `(x: take T)`, because the caller-side behavior of the operator is analogous to the callee’s behavior receiving the parameter: the `take y` operator forces the caller to give up ownership of the value of `x` in the caller, and the `take T` parameter will assume ownership of the argument in the callee. They can be used in tandem to forward ownership of a value across call boundaries:

```swift
func +(_ a: take String, _ b: String) -> String {
  // Transfer ownership of the `self` parameter to a
  // mutable variable
  var result = take a
  // Modify it in-place, taking advantage of
  // uniqueness if possible
  result += b
  return result
}

// Since each result should be uniquely-referenced,
// this append chain will run in linear rather than
// quadratic time
"hello " + "cruel " + "world"

```

Using `take` in a callee’s function parameter declaration doesn’t by itself force the caller to let it take ownership, so this definition of `+` can also still be used in normal Swift code, which will still copy values as needed to keep them alive. `take` can be used in expressions involving `+` to require the ownership forwarding chain to continue:

```swift
var foo = "hello "
// Copies `foo` to keep the existing value alive for further access
var bar = foo + "cruel " + "world"
foo += "beautiful " + "world"
// forward ownership of the final `foo` value
var bas = take foo + ", i felt the rain on my shoulder"

```

### `borrow` operator

When performing reads of shared mutable state, such as class stored properties, global or static variables, or escaped closure captures, the compiler defaults to copying when it is theoretically possible to borrow. The compiler does this to maintain memory safety and minimize the opportunity for the law of exclusivity to trip, in case other code tries to write to the same objects or global variables while a call is ongoing. For example:

```swift
var global = Foo()

func useFoo(x: Foo) {
  // We would need exclusive access to `global` to do this:
  
  /*
  global = Foo()
   */
}

func callUseFoo() {
  // callUseFoo doesn't know whether `useFoo` accesses global,
  // so we want to avoid imposing shared access to it for longer
  // than necessary. So by default the compiler will
  // pass a copy instead, and this:
  useFoo(x: global)

  // will compile more like:

  /*
  let copyOfGlobal = copy(global)
  useFoo(x: copyOfGlobal)
  destroy(copyOfGlobal)
   */
}

```

Although the compiler is allowed to eliminate the defensive copy inside `callUseFoo` if it proves that `useFoo` doesn't try to write to the `global` variable, it is unlikely to do so in practice. The developer however knows that `useFoo` doesn't modify `global`, and may want to suppress this copy in the call site. An explicit `borrow` operator lets the developer communicate this to the compiler:

```swift
var global = Foo()

func useFoo(x: Foo) {
  /* global not used here */
}

func callUseFoo() {
  // The programmer knows that `useFoo` won't
  // touch `global`, so we'd like to pass it without copying
  useFoo(x: borrow global)
}

```

`borrow global` suppresses the local copy of `global` and passes the reference as-is to `useFoo`. If `useFoo` did in fact attempt to mutate `global` while the caller was borrowing it, the attempt would trigger an exclusivity failure trap at runtime.

It is useful to be able to `borrow` parts of an object, such as a reference to an instance property, or a struct field within a property (by contrast with `take x`, which passes ownership of an entire value, and therefore only makes sense to apply to variables):

```swift
final class A {
  var x: B
}

struct B {
  var y: String
}

foo(borrow a.x.y) // borrow access to a.x, then borrow .y out of it

```

When working with local variables, the compiler can statically tell when borrowing in place is safe, so `borrow` isn’t strictly necessary. It can still be used as an annotation to guarantee that in-place borrowing occurs, and to have the compiler raise errors in cases where it isn’t possible:

```swift
func read(_: borrow String, andModify: inout String) {}

func doStuff() {
  var x = "foo"
  read(x, andModify: &x) // will copy x to avoid exclusivity error passing the first argument
  
  read(borrow x, andModify: &x) // error: nonexclusive use of &x
}

```

The `borrow expr` syntax intentionally aligns with the proposed [ownership modifier](https://forums.swift.org/t/borrow-and-take-parameter-ownership-modifiers/59581) syntax for parameters, `(x: borrow T)`, because the caller-side behavior of `borrow expr` is analogous to the callee’s handling of the parameter value. A `borrow T` parameter declares that the callee will borrow the value it is passed from the caller, but does not by itself prevent callers from using a copy as the passed value. Using `borrow expr` at the call site forces the caller to pass the borrowed argument in-place.

### `@noImplicitCopy` attribute

There are many circumstances when it’s desirable to suppress implicit copying altogether, and treat particular values as being move-only without making their type completely uncopyable. We could provide an attribute that can be applied to function parameters and variables to mark that variable as not being copyable:

```swift
func update(@noImplicitCopy array: inout [String]) {
  array.append("hello")
  array.append("world")
  
  let x = array // error: forces a copy of `array`
  array.append("oh no")
}

```

If a type is copyable, but copying the type is expensive or otherwise best avoided (because it’s large, contains a lot of reference-counted fields, involves C++ copy constructors, etc.), it could be useful to tag a type as no-implicit-copy, to make all variables that are (concretely) of the type no-implicit-copy:

```swift
@noImplicitCopy struct Gigantic {
  var fee, fie, fo, fum: String
}

func operate(on value: Gigantic) {
  var newValue = value
  newValue.fee += newValue.fie
  operate(on: value, and: newValue) // error: forces a copy of `value`
}

```

Or you might want to suppress copies generally within a scope, such as a hot loop:

```swift
for item in items {
  @noImplicitCopy do {
    ...
  }
}

```

Note that, unlike true move-only types, all of these would be local, non-transitive restrictions. A no-implicit-copy variable can still be passed to another function that may copy it:

```swift
func foo(@noImplicitCopy x: String) {
  bar(x: x)
}

func bar(x: String) {
  // OK to copy `x` in `bar`
  var y = x
  y += "bar"
  print(x, y)
}

```

And concrete types marked as no-implicit-copy would be implicitly copyable when used as generic or existential types (unless those generic values are also marked no-implicit-copy):

```swift
func duplicate<T>(_ value: T) -> (T, T) {
  // OK to copy value in a generic context
  return (value, value)
}

duplicate(Gigantic()) // this call is OK

```

This allows developers to apply `@noImplicitCopy` locally in their own code without cutting themselves off from the greater Swift ecosystem, which would need to retrofit annotations in order to support a truly transitive “move-only value” constraint, or imposing transitive constraints on their clients. Move-only types will be the language tool for transitively preventing copies.

Because the language semantics can’t copy a no-implicit-copy variable, such variables have “eager move” lifetime semantics, meaning their lifetime ends after an operation takes ownership of their value, regardless of whether the `take` operator is used:

```swift
func consume(_: take String) {}

func doStuff() {
  do {
    var x = "hello"
    x += " world"
    consume(x)
    print(x) // This is fine, we'll copy `x` to prolong the local var's lifetime
  }
  do {
    @noImplicitCopy var x = "hello"
    x += " world"
    consume(x)
    print(x) // ERROR: x used after take. we're not allowed to copy it
  }
}

```

No-implicit-copy values are also always borrowed in-place when used as borrowed arguments. So certain formulations may trigger static or dynamic exclusivity errors that would be accepted quietly for copyable values:

```swift
func read(_: borrow String, andModify _: inout String) {}

func doStuff() {
  do {
    var x = "hello"
    x += " world"
    // This is fine, we'll copy `x` to sidestep the exclusivity error that'd arise
    // from trying to simultaneously pass x by inout and by borrow
    read(x, andModify: &x)
  }
  do {
    @noImplicitCopy var x = "hello"
    x += " world"
    // ERROR: attempt to exclusively access x during a borrow
    read(x, andModify: &x)
  }
}

```

Values of move-only types would always have these “eager move” lifetime semantics as well.

### Explicit `copy` operation

Without the ability to copy implicitly, an obvious question is, how do we explicitly copy? Because `@noImplicitCopy` isn’t transitive, it is easy enough to write a function that copies on behalf of its caller:

```swift
func copy<T>(_ value: borrow T) -> T { return value }

func doStuff() {
  @noImplicitCopy var x = "hello"
  x += " world"
  read(copy(x), andModify: &x)
}

```

But by analogy to `take x` and `borrow x`, we may want to make `copy` also be a contextual operator:

```swift
func doStuff() {
  @noImplicitCopy var x = "hello"
  x += " world"
  read(copy x, andModify: &x)
}

```

---

<div class="post-metadata">

**Author:** ![filip-sakel](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/filip-sakel/32/8697_2.png) [@filip-sakel](https://forums.swift.org/u/filip-sakel)\
**Post date:** [September 7, 2022, 7:13pm UTC](https://forums.swift.org/t/selective-control-of-implicit-copying-behavior-take-borrow-and-copy-operators-noimplicitcopy/60168/2 "2022-09-07T19:13:54Z")

</div>

Thank you for writing this up! I think the design has come a long way from the originally proposed move function.

In terms of naming, is there a reason we went for `@noImplicitCopy` instead of something more straightforward such as `@explicitCopy`? I guess if we followed Val’s precedent (who have `@implicitCopy`), the proposed naming would make sense.

Another suggestion would be to have an attribute that reenables implicit copies in an explicit-copy context, such as `@implicitCopy`. But I was thinking that maybe explicit copies could be automatically enforced in some contexts. For example, when users explicitly mark function parameters as `borrow` and `take`, it’s likely that they’re writing performance-critical code, where implicit copies can incur significant performance penalties. Though, I do realize that this presents problems both with how explicit is interpreted and how `borrow` and `take` relate to `inout`.

One example where explicitly writing these modifiers shouldn’t result in explicit copies is protocol witnesses. There are already protocol methods annotated with `__consuming` and other ownership modifiers in the standard library. If, after ownership modifiers are officially in the language, autocompletion honors these modifiers and presents them in protocol witnesses, a lot of library consumers that just want to conform to a protocol may get caught up in dealing with ownership. However, I think that if we allow protocol witnesses to not have the ownership modifiers of their corresponding requirements, that automatic explicit copies could work.

Another problem with automatic explicit copies is that the distinguish `borrow` and `take` from `inout`, despite all being ownership modifiers. Although they all show how values are passed between functions and bindings, inout cannot be hidden away through Swift’s implicit copies. Swift uses value-semantics at its core, which require explicit mutation through a mutable binding (var) or inout parameters/mutating methods. However, if a value cannot be taken when passed into a function or binding, an implicit copy can and is already used.

Thus, I think that most people will not and should not encounter ownership modifiers, at least when first learning Swift. Swift’s implicit copies and COW model allow for very quick prototyping and ease the language learning curve. However, people working in performance-sensitive domains should be aware of Swift’s implicit-copy behavior and its performance impact, and by extension should have knowledge of ownership modifiers to control how values are passed. Hence, it seems reasonable to have automatic explicit-copy contexts on functions that have `take` or `borrow` parameters, since the people specifying these modifiers value performance.

---

<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:** [September 7, 2022, 8:10pm UTC](https://forums.swift.org/t/selective-control-of-implicit-copying-behavior-take-borrow-and-copy-operators-noimplicitcopy/60168/3 "2022-09-07T20:10:15Z")

</div>

> [@filip-sakel](#):
>
> In terms of naming, is there a reason we went for `@noImplicitCopy` instead of something more straightforward such as `@explicitCopy`? I guess if we followed Val’s precedent (who have `@implicitCopy`), the proposed naming would make sense.

I don't think any of us is attached to the name `@noImplicitCopy`. `@explicitCopy` definitely seems nicer. We're open to other suggestions.

---

<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:** [September 7, 2022, 10:04pm UTC](https://forums.swift.org/t/selective-control-of-implicit-copying-behavior-take-borrow-and-copy-operators-noimplicitcopy/60168/4 "2022-09-07T22:04:29Z")

</div>

> [@Joe\_Groff](#):
>
> In the example above, `y`'s formal lifetime extends to the end of scope. When we go back to using `x`, although the compiler may optimize the actual lifetime of `y` to release it after its last use, there isn't a strong guarantee that it will. Even if the optimizer does what we want, programmers modifying this code in the future may introduce new references to `y` that inadvertently extend its lifetime and break our attempt to keep `x` unique. There isn't any indication in the source code that that the end of `y`'s use is important to the performance characteristics of the code. We can introduce an operator to make that explicit:

As with the previous versions of this pitch I'd like to see a word or two of explanation why lexical scope (nesting) is inappropriate here as a way of explicitly ending variable lifetime:

```swift
x.append(5)

do {  
    var y = x
    longAlgorithmUsing(&y)
    consumeFinalY(y)
    // y is guaranteed to end here
}

x.append(7)

```

---

<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:** [September 7, 2022, 10:09pm UTC](https://forums.swift.org/t/selective-control-of-implicit-copying-behavior-take-borrow-and-copy-operators-noimplicitcopy/60168/5 "2022-09-07T22:09:38Z")

</div>

It is occasionally important for performance reasons to end the lifetime of a `take` parameter before the end of the function. (I agree that this is worth mentioning explicitly, and that it's harder to justify without having explicit `take` parameters in the language yet.)

---

<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:** [September 7, 2022, 10:17pm UTC](https://forums.swift.org/t/selective-control-of-implicit-copying-behavior-take-borrow-and-copy-operators-noimplicitcopy/60168/6 "2022-09-07T22:17:29Z")

</div>

> [@tera](#):
>
> As with the previous versions of this pitch I'd like to see a word or two of explanation why lexical scope (nesting) is inappropriate here as a way of explicitly ending variable lifetime:
> 
> ```swift
> x.append(5)
> 
> do {  
> var y = x
> longAlgorithmUsing(&y)
> consumeFinalY(y)
> // y is guaranteed to end here
> }
> 
> x.append(7)
> 
> ```

There are a few reasons not to rely only on lexical scope to end value lifetimes:

- We don't want to impose "pyramid of doom" situations when you have more than one value whose lifetime you need to cut off.
- Value lifetimes don't necessarily need to nest. `var x = foo(); var y = bar(); consume(take x); consume(take y)` should be valid.
- It is useful to be able to take the current value out of a mutable variable and reinitialize it later.

Rust 1.0 originally only had strictly scoped value lifetimes, and this was a significant ergonomic constraint until "non-lexical lifetimes" were added later, which allowed for value lifetimes to shrinkwrap to their actual duration of use. (We had originally tried that same shrinkwrap-to-last-use rule in Swift, too, actually, but found that it broke idiomatic Cocoa code that makes heavy use of weak references too aggressively.)

---

<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:** [September 7, 2022, 10:55pm UTC](https://forums.swift.org/t/selective-control-of-implicit-copying-behavior-take-borrow-and-copy-operators-noimplicitcopy/60168/7 "2022-09-07T22:55:13Z")

</div>

Joe, these are great answers, thank you, please include some wording to that effect into the actual pitch once it is in the form of actual pitch.

I can see these two arguments:

- we can sort of do this today without nesting:

```swift
func test() {
    var x: [Int] = getArray()
    x.append(5)
    var y = x
    longAlgorithmUsing(&y)
    consumeFinalY(y)
    guard let y = drop() else { fatalError() }
    x.append(7)
}

func drop() -> Void? { () }

```

although I admit that this is cheating / abusing and not as ergonomic as your explicit "take x" or "drop x".

- The second one is harder to swallow – and I ask for an apology for repeating this argument from the previous discussions (just I never saw it answered) – the fears of "pyramid of doom" are understandable, just I can see how a similar line of reasoning can justify the introduction of "goto" statement _("makes language simpler"; "instead of all those "while's" / "for's", braces and scopes / "pyramids of doom" just have "if" and "goto""; "allows for an ultimate flexibility impossible to express via "structured" alternatives"; "language X has it and it works great in there".)_

I'd like to see some strong motivated example that makes the superiority of explicit "take" / "drop" approach obvious. Hopefully people here who are familiar with Rust or other language with a similar feature could come up with some killer example.

---

<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:** [September 8, 2022, 4:41pm UTC](https://forums.swift.org/t/selective-control-of-implicit-copying-behavior-take-borrow-and-copy-operators-noimplicitcopy/60168/8 "2022-09-08T16:41:40Z")

</div>

Just a short note here but I think this will be really valuable for us working on swift-nio. The number of circumstances where we really have to wrestle with ownership carefully is low, but there are a few places where we'd really benefit from giving the opportunity to our users to make their lifetimes clear, as well as in our own implementations. I think this proposal is clear and pragmatic, so I'm a strong +1.

---

<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:** [September 9, 2022, 1:24pm UTC](https://forums.swift.org/t/selective-control-of-implicit-copying-behavior-take-borrow-and-copy-operators-noimplicitcopy/60168/9 "2022-09-09T13:24:59Z")

</div>

> [@lukasa](#):
>
> Just a short note here but I think this will be really valuable for us working on swift-nio. The number of circumstances where we really have to wrestle with ownership carefully is low, but there are a few places where we'd really benefit from giving the opportunity to our users to make their lifetimes clear, as well as in our own implementations.

Looks like you are in a good position to provide that killer example..

Have a look at this one:

```swift
func test() {
    var x = ValueType(1)
    print("x.append(5) -->")
    x.append(5)
    var y = x
    longAlgorithmUsing(&y)
    consumeFinalY(y)
    print("x.append(7) --> ")
    x.append(7)
}

```

It is the same as in the pitch above, just making use of some explicit types to see the internal nuts and bolts:

> **The value / ref types used.**
>
> ```swift
> class RefType {
> var value: Int
>     
> init(_ value: Int) {
> self.value = value
> }
> }
> 
> struct ValueType {
> private var ref: RefType!
>     
> init(_ value: Int) {
> ref = RefType(value)
> }
>     
> mutating func append(_ value: Int) {
> if isKnownUniquelyReferenced(&ref) {
> print(" quick assignment")
> ref.value = value
> } else {
> print(" COW assignment")
> ref = RefType(value)
> }
> }
>     
> mutating func drop() {
> ref = nil
> }
> }
> 
> func longAlgorithmUsing(_ v: inout ValueType) {}
> func consumeFinalY(_ v: ValueType) {}
> 
> ```

As written the above example would produce the expected (and unwanted) sequence:

```swift
x.append(5) -->
  quick assignment
x.append(7) --> 
  COW assignment

```

Then we introduce this extra line:

```swift
func test() {
    var x = ValueType(1)
    print("x.append(5) -->")
    x.append(5)
    var y = x
    longAlgorithmUsing(&y)
    consumeFinalY(y)
    y.drop() // **************
    print("x.append(7) --> ")
    x.append(7)
}

```

and the log changes to the desired:

```swift
x.append(5) -->
  quick assignment
x.append(7) --> 
  quick assignment

```

Just note that in this case the "drop" is merely a function of "ValueType":

```swift
struct ValueType {
...
    mutating func drop() {
        ref = nil
    }
}

```

and no language change was needed to achieve the desired "non COW" behaviour. What am I missing? Is it not just a matter of agreement for value types to provide a function called "drop" and changing std types to adopt that convention?

---

<div class="post-metadata">

**Author:** ![Karl](https://avatars.discourse-cdn.com/v4/letter/k/34f0e0/32.png) [@Karl](https://forums.swift.org/u/Karl)\
**Post date:** [September 9, 2022, 3:14pm UTC](https://forums.swift.org/t/selective-control-of-implicit-copying-behavior-take-borrow-and-copy-operators-noimplicitcopy/60168/10 "2022-09-09T15:14:22Z")

</div>

As before, I would rather we found a different name for "copy"; it's a highly overloaded term, even in Swift. For example, "copy on write" refers to a different kind of copying, as do established Cocoa APIs such as `NSCopying` and `NSMutableCopying`.

I'm also very much -1 on the name `@noImplicit{Anything}` - Since it is phrased as an opt-out, it gives me the impression that the compiler typically does something undesirable, at least in some situations; and that I can't trust the language as it works by default. It feels like `@noNannying` or `@noHandholding`. It immediately makes you think "why would somebody _want_ to disable this?".

I think `@explicit{Copy/Lifetime/Ownership}` is preferable; I don't feel it has such a connotation that the default behaviour is incorrect or undesirable. It's very... well, explicit about what it is trying to achieve - that you want to make a value's lifetime events visible in code, even if the default behaviour happens to _also_ be correct.

At least, that's how I read it. Perhaps not everybody reads it like that.

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [September 9, 2022, 3:41pm UTC](https://forums.swift.org/t/selective-control-of-implicit-copying-behavior-take-borrow-and-copy-operators-noimplicitcopy/60168/11 "2022-09-09T15:41:52Z")

</div>

> [@Karl](#):
>
> I think `@explicit{Copy/Lifetime/Ownership}` is preferable; I don't feel it has such a connotation that the default behaviour is incorrect or undesirable. It's very... well, explicit about what it is trying to achieve - that you want to make a value's lifetime events visible in code, even if the default behaviour happens to _also_ be correct.

Counterpoint: I think it's plausible to read `@explicitCopy` as a marker _of_ an explicit copy rather than a marker that _requires_ explicit copying. IOW, in isolation, `@explicitCopy` seems like it could be another proposed spelling for the `copy` operation.

In that sense I think `@noImplicitCopy` is better at describing what it's actually doing (disabling the default implicit copy behavior).

That doesn't mean that the polarity of `@explicitCopy` is incorrect, but I think something like `@requireExplicitCopy` would more accurately describe what's going on here, even if it is a bit more verbose.

---

<div class="post-metadata">

**Author:** ![Karl](https://avatars.discourse-cdn.com/v4/letter/k/34f0e0/32.png) [@Karl](https://forums.swift.org/u/Karl)\
**Post date:** [September 9, 2022, 3:47pm UTC](https://forums.swift.org/t/selective-control-of-implicit-copying-behavior-take-borrow-and-copy-operators-noimplicitcopy/60168/12 "2022-09-09T15:47:04Z")

</div>

The reason I said `@explicit{Copy/Lifetime/Ownership}` is because I'm not a fan of the word "copy" being used to describe this operation at all. Either of the latter two - `@explicitLifetime` or `@explicitOwnership`, are what I would prefer.

Whether or not they are also confusable with the operation itself depends on what the operation ends up being called.

---

<div class="post-metadata">

**Author:** ![benlings](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/benlings/32/13011_2.png) [@benlings](https://forums.swift.org/u/benlings)\
**Post date:** [September 10, 2022, 7:17am UTC](https://forums.swift.org/t/selective-control-of-implicit-copying-behavior-take-borrow-and-copy-operators-noimplicitcopy/60168/13 "2022-09-10T07:17:19Z")

</div>

> [@Jumhyn](#):
>
> I think it's plausible to read `@explicitCopy` as a marker _of_ an explicit copy rather than a marker that _requires_ explicit copying. IOW, in isolation, `@explicitCopy` seems like it could be another proposed spelling for the `copy` operation.

That’s how `@explictCopy` sounds to me too. How about `@explictCopying` to mark explicit copying?

---

<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:** [September 10, 2022, 11:30am UTC](https://forums.swift.org/t/selective-control-of-implicit-copying-behavior-take-borrow-and-copy-operators-noimplicitcopy/60168/14 "2022-09-10T11:30:52Z")

</div>

> [@Karl](#):
>
> As before, I would rather we found a different name for "copy"; it's a highly overloaded term, even in Swift.

I agree with that sentiment.

Would it make sense if we called this operation "duplicate" instead of "copy"? The operator could be called `dup` for short:

- **`dup`** : contextual operator to create a duplicate
- **`@overtDup`** : `dup` must be explicit
- **`@noDup`** : duplications are forbidden (move-only), for a future proposal

```swift
func doStuff() {
  @overtDup var x = "hello"
  x += " world"
  read(dup x, andModify: &x)
}

```

Also, I think `dup x` should be a warning when the variable or type is not `@overtDup` (possibly with a fix-it to add `@overtDup` to the variable). I don't think there is a point in using `dup`, other than making unnecessary duplicates, when the compiler is managing it for you.

Was that hard to read? ... same thing reworded with "copy":

_Also, I think `copy x` should be a warning when the variable or type is not `@noImplicitCopy` (possibly with a fix-it to add `@noImplicitCopy` to the variable). I don't think there is a point in using `copy`, other than making unnecessary copies, when the compiler is managing it for you?_

---

<div class="post-metadata">

**Author:** ![Karl](https://avatars.discourse-cdn.com/v4/letter/k/34f0e0/32.png) [@Karl](https://forums.swift.org/u/Karl)\
**Post date:** [September 10, 2022, 3:10pm UTC](https://forums.swift.org/t/selective-control-of-implicit-copying-behavior-take-borrow-and-copy-operators-noimplicitcopy/60168/15 "2022-09-10T15:10:38Z")

</div>

The thing about the word `copy` is that we're actually talking about something even shallower than a "shallow copy". `let y = copy x` does not actually construct a new object; it constructs a new _reference_. Basically, it's a `retain`, and `@noImplicitCopy` is really "no implicit retains" -- it makes certain ARC operations, which are otherwise invisible, visible.

To underscore that point, consider that because `NSCopying` exists, we will have objects where:

```swift
someFunction(x.copy())
someFunction(copy x)

```

Have _entirely different_ semantics. NSCopying declares that it produces an "independent object", and as such we can expect it to stop the sharing of mutable state:

> a copy must be a functionally independent object with values identical to the original at the time the copy was made

[NSCopying documentation](https://developer.apple.com/documentation/foundation/nscopying)

`copy x` (the operator being discussed in this proposal) does _not_ produce an independent object, and that is not its goal - it exists to extend the lifetime of an existing object. The result of `copy x` may still share mutable state with `x`.

We also use the word `copy` in Obj-C properties in a way that aligns with NSCopying:

> `copy`
> 
> Specifies that a copy of the object should be used for assignment.  
> The previous value is sent a `release` message.  
> The copy is made by invoking the `copy` method. This attribute is valid only for object types, which must implement the `NSCopying` protocol.
> 
> `assign`
> 
> Specifies that the setter uses simple assignment. This attribute is the default.  
> You use this attribute for scalar types such as `NSInteger` and `CGRect`.
> 
> `retain`
> 
> Specifies that `retain` should be invoked on the object upon assignment.  
> The previous value is sent a `release` message.

[The Objective-C Programming Language](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html)

This is just the confusion we can expect within the Cocoa/Obj-C ecosystem, and among developers used to that terminology and way of thinking ("copy produces an independent object"). We should also consider what C++ developers will expect when writing `copy x` on an imported class (if they are managed by ARC in some way).

---

<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:** [September 10, 2022, 3:25pm UTC](https://forums.swift.org/t/selective-control-of-implicit-copying-behavior-take-borrow-and-copy-operators-noimplicitcopy/60168/16 "2022-09-10T15:25:26Z")

</div>

> [@Karl](#):
>
> `copy x` (the operator being discussed in this proposal) does _not_ produce an independent object, and that is not its goal - it exists to extend the lifetime of an existing object.

This is only true for reference types. Copying a value certainly produces an independent value.

---

<div class="post-metadata">

**Author:** ![QuinceyMorris](https://avatars.discourse-cdn.com/v4/letter/q/d26b3c/32.png) [@QuinceyMorris](https://forums.swift.org/u/QuinceyMorris)\
**Post date:** [September 10, 2022, 5:37pm UTC](https://forums.swift.org/t/selective-control-of-implicit-copying-behavior-take-borrow-and-copy-operators-noimplicitcopy/60168/17 "2022-09-10T17:37:47Z")

</div>

> [@ksluder](#):
>
> Copying a value certainly produces an independent value.

I don't think there's any escape hatch there. A value may _contain_ a reference, in which case @Karl's point is still valid.

It seems to me that this isn't _just_ about retaining objects. In principle, `@noImplicitCopy` refers to any aspect of the value that the compiler might regard as duplicative in normal use, and which might be worth expending effort to avoid.

For example, it might be that the stack-based memory for a value might be regarded as a precious resource, so that it might be undesirable make additional stack copies of some very large `struct`.

It's been a truism of Swift that values of value types (unless modified) and references to objects of reference types exist in multiple _ **interchangeable** _ copies. This proposal introduces the idea of _ **non-interchangeable** _ copies, a distinction that exists regardless of the value/reference divide.

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [September 10, 2022, 7:51pm UTC](https://forums.swift.org/t/selective-control-of-implicit-copying-behavior-take-borrow-and-copy-operators-noimplicitcopy/60168/18 "2022-09-10T19:51:39Z")

</div>

This looks great to me overall! Very nice to have a more complete picture of the ownership story related to `take`.

> [@Joe\_Groff](#):
>
> ```swift
> func test() {
> var x: [Int] = getArray()
>   
> // x is appended to. After this point, we know that x is unique.
> // We want to preserve that property.
> x.append(5)
>   
> // We create a new variable y so we can write an algorithm
> // where we may change the value of y (causing a COW copy
> // of the buffer shared with x).
> var y = x
> longAlgorithmUsing(&y)
> // We no longer use y after this point, so we tell the
> // last use to take ownership.
> consumeFinalY(take y)
> 
> // x will be unique again here.
> x.append(7)
> }
> 
> ```

This as the headline motivating example of `take` remains unsatisfying to me. The text says `take` is introduced to solve the problems that 1) there is no "strong guarantee" that the compiler will optimize the lifetime of `y` to end before the final use of `x` and 2) future modifications of the code may introduce uses of `y` that inadvertently extend its lifetime. But as far as (1) goes, it seems even _with_ take we have no such "strong guarantee":

> [@SE-0366: Move Function + "Use After Move" Diagnostic](https://forums.swift.org/t/se-0366-move-function-use-after-move-diagnostic/59202/21):
>
> As it stands, the move intrinsic does not carry any special side effects. I don't think we want to give it special side effects either. That's contrary to the intent of "just express what we intended the optimizer to do without otherwise inhibiting optimization". So I can't think of a language rule that prevents the transformation above. But I agree that it's harmful optimization behavior and should hopefully never happen in practice. The compiler does have a conservative understanding of where…

> [@SE-0366: Move Function + "Use After Move" Diagnostic](https://forums.swift.org/t/se-0366-move-function-use-after-move-diagnostic/59202/87):
>
> This also makes sense, though I wonder if it is in conflict with the proposal text. The proposal raises the point several times that `move` serves not only as a tool useful against modifications of the source, but also against optimizer behavior and future language implementation changes. If we don't have the formal language to guarantee that `move` protects against the language implementation in this way, perhaps it would be appropriate to specify `move` for now as a source-level guard, and then further specify the semantics once we flesh out the initialization semantics?

And (2) still seems problematic since it does nothing for introducing new uses of `x` that are interleaved with the 'critical section' where `y` is alive, e.g.:

```swift
func test() {
  var x: [Int] = getArray()
  x.append(5)
  
  var y = x
  longAlgorithmUsing(&y)

  x.append(6) // non-unique!

  consumeFinalY(take y)

  x.append(7)
}

```

When I [raised this](https://forums.swift.org/t/se-0366-move-function-use-after-move-diagnostic/59202/87) previously it was pointed out that the solution I was reaching for seemed similar to the [borrow variables](https://forums.swift.org/t/a-roadmap-for-improving-swift-performance-predictability-arc-improvements-and-ownership-control/54206#borrow-variables-7) discussed in the updated ownership roadmap, but that still leaves me with questions in regards to `take`. Is some form of borrow variables the intended solution here? If so, why is this example being used to motivate `take`?

> [@Joe\_Groff](#):
>
> Note that, unlike true move-only types, all of these would be local, non-transitive restrictions. A no-implicit-copy variable can still be passed to another function that may copy it:
> 
> [...]
> 
> And concrete types marked as no-implicit-copy would be implicitly copyable when used as generic or existential types (unless those generic values are also marked no-implicit-copy):

Ought we have _some_ sort of marker in these cases at the point where the non-transitivity of `@noImplicitCopy` causes us to lose its guarantees? It seems a bit silly to provide the functionality of `@noImplicitCopy` and also allow it to end up getting silently discarded.

And somewhat relatedly, is `copy` intended to _guarantee_ that the compiler really will emit a copy operation, or does it just serve to _allow_ the compiler to emit a copy when necessary? If the latter, would it make sense to just use `copy` as that marker to indicate that you _may_ end up copying the value by passing it somewhere that loses its `@noImplicitCopy`-ness?

---

<div class="post-metadata">

**Author:** ![Andrew\_Trick](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/andrew_trick/32/323_2.png) [@Andrew\_Trick](https://forums.swift.org/u/Andrew_Trick)\
**Post date:** [September 12, 2022, 9:05pm UTC](https://forums.swift.org/t/selective-control-of-implicit-copying-behavior-take-borrow-and-copy-operators-noimplicitcopy/60168/19 "2022-09-12T21:05:47Z")

</div>

> [@Jumhyn](#):
>
> The text says `take` is introduced to solve the problems that 1) there is no "strong guarantee" that the compiler will optimize the lifetime of `y` to end before the final use of `x` and 2) future modifications of the code may introduce uses of `y` that inadvertently extend its lifetime.

The example does not directly defend either of these claims...

Language rules give us strong guarantees about the static lifetimes of variables. Language rules don't give us strong guarantees about when copies that alias become unique again, because that information doesn't exist statically. Once you have separately owned aliasing references, you can't prevent someone else from introducing code that mutates one and copies the elements.

I do think the example makes it easy to understand how `take` can avoid copying CoW elements. And there's nothing wrong with relying on reasonable optimizer behavior. Of course, you could insert paranoid optimizer controls if you felt inclined:

```swift
  consumeFinalY(take y)
  withExtendedLifetime(x) {}
  x.append(7)

```

or

```swift
  consumeFinalY(take y)
  lifetimeBarrier() // DIY barrier
  x.append(7)

```

It would be interesting to talk about adding "lifetimeBarrier" to the standard library. That's entirely tangential though. Again, I don't recommend actually writing this code!

It's easy to defend the two main claims if we just focus on eliminating copies. Real-word cases frequently involve forwarding. Here, `take` is needed to avoid a reference copy (grep for ` __owned` or `__ consuming` in the stdlib code to see many places that need `take`):

```swift
  public func isSuperset<S: Sequence>(of possibleSubset: take S) -> Bool
   where S.Element == Element {
     if let s = possibleSubset as? Set<Element> {
       return isSuperset(of: take s)
     }
     //...

```

Avoiding useless copies is important enough on its own to justify the proposal. But it's more compelling if we bring it back to CoW performance. Avoiding copies in general can indirectly avoid copying all the elements in a CoW container. Here's a really terrible example off the top of my head:

```swift
func doNotCopyArray<T>(membership: inout Set<T>, array: inout [T], value: T?) {
  let subset = value != nil ? array : []
  //...
  if (!membership.isSuperset(of: take subset)) {
    array.append(value!)
  }
  //...
}

```

I'm sure someone can think of something less contrived.

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [September 12, 2022, 9:39pm UTC](https://forums.swift.org/t/selective-control-of-implicit-copying-behavior-take-borrow-and-copy-operators-noimplicitcopy/60168/20 "2022-09-12T21:39:42Z")

</div>

> [@Andrew\_Trick](#):
>
> The example does not directly defend either of these claims...  
> [...]  
> Once you have separately owned aliasing references, you can't prevent someone else from introducing code that mutates one and copies the elements.  
> [...]  
> Avoiding useless copies is important enough on its own to justify the proposal. But it's more compelling if we bring it back to CoW performance.

Sorry, I've been a bit unclear. I think we're saying very similar things. My point is more of a rhetorical one: I think using this CoW example as the primary motivating example for `take` is confusing precisely _because_ it does not directly defend either of the claims that are used to introduce it. This CoW example was the _only_ example raised in the **Motivation** section of original `take` pitch, and I think treating it as the main motivation for `take` muddies the waters.

That `take` also provides a way to avoid CoW triggering in the face of potentially-aliasing variables is a nice additional benefit, sure, but IMO it's better if the primary motivation for `take` are the situations where `take` is _needed_ to avoid pessimistic copies.

[Next page](https://forums.swift.org/t/selective-control-of-implicit-copying-behavior-take-borrow-and-copy-operators-noimplicitcopy/60168.md?page=2)
