# Noncopyable Generics in Swift: A Code Walkthrough

**URL:** <https://forums.swift.org/t/noncopyable-generics-in-swift-a-code-walkthrough/70862>\
**Category:** Discussion\
**Tags:** generics, swift-evolution, noncopyable, tutorial\
**Created:** [March 23, 2024, 7:06pm UTC](https://forums.swift.org/t/noncopyable-generics-in-swift-a-code-walkthrough/70862 "2024-03-23T19:06:16Z")\
**Posts on this page:** 1\
**Showing post:** 5

<div class="post-metadata">

**Author:** ![wadetregaskis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/wadetregaskis/32/8494_2.png) [@wadetregaskis](https://forums.swift.org/u/wadetregaskis)\
**Post date:** [March 23, 2024, 9:01pm UTC](https://forums.swift.org/t/noncopyable-generics-in-swift-a-code-walkthrough/70862/5 "2024-03-23T21:01:35Z")

</div>

This is superb.

It could also be the basis for a [Swift.org](http://Swift.org) blog post (probably around the time of Swift 6's release, or whenever the relevant features mainlined). I realise non-copyable types are intended to be a niche feature, but I think the audience for this kind of introductory howto is much bigger as it includes people that are simply curious.

> [@ben-cohen](#):
>
> If you were to put a copyable type into it, you could still use it at the cost of the compiler making a copy.

_Maybe_, right? If the compiler determines that the caller has no need for the value after `Box`'s `init`, it can pass it directly, no?

> [@ben-cohen](#):
>
> You might be surprised to see that you can call a `consuming` method on a `let` variable (`boxbox.move()`). Consuming methods are not like mutation. You are giving away the value, and as such, it doesn't matter that it is immutable.

Though this requires that the `let` variable be invalidatable, right? So it couldn't be e.g. a stored property (except if you're consuming it in `deinit` or equivalent?)?

> [@ben-cohen](#):
>
> ```swift
> extension Box {
> var wrapped: Wrapped { pointer.pointee }
> }
> 
> ```
> 
> This computed property returns a copy of the boxed value. This is obviously only possible when the box holds a copyable type (say an `Int` or a `String`).

Missing `where Wrapped == Copyable`?

> [@ben-cohen](#):
>
> There is a caveat here. Because of the way our list is constructed, destructing it happens by recursing all the way to the end and then calling deinitializers all the way back.

Is it an intrinsic requirement that the compiler implement that synthesised deinit as a recursive algorithm rather than an iterative one?

Or perhaps more to the point, as depth-first rather than breadth-first?

Just out of tangential curiosity.

I wouldn't expect it to special-case a singly-linked list or anything, but it does seem plausible that it could recognise cases where back-references are impossible, and delete as it goes.

> [@ben-cohen](#):
>
> Because the switch (partially) consumes `self`, it must be reinitialized on all paths, even when head turned out to be `nil` and so no "hole" existed. Again, perhaps more clever analysis by the compiler in future could allow some of this boilerplate to be omitted.

Yeah, while it makes sense as written given the current rules, I guarantee I'm going to first write the following instead, every single time:

```swift
mutating func pop() -> Element? {
    if let node = head?.move() {
        head = node.next
        return node.element
    } else {
        return nil
    }
}

```

It'll be great when that's one day supported as well, re. the partial consumption proposal etc.

> [@ben-cohen](#):
>
> So for now, we're going to do this via adding a `forEach` method to the list. As a reminder, `forEach` is bad and you should feel bad for using it on regular copyable types.

[Tangentially] Nah, because with optional chaining situations for…in loops are often worse. And I say that even though I'm increasingly growing to hate the use of trailing closures to mimic basic blocks (given the compiler's inability to reason through the control flow, and thus how it breaks even the most rudimentary features like initialisation of `let`s).

---

_[View the full topic](https://forums.swift.org/t/noncopyable-generics-in-swift-a-code-walkthrough/70862)._
