Streaming is available in most browsers,
and in the Developer app.
-
Consume noncopyable types in Swift
Get started with noncopyable types in Swift. Discover what copying means in Swift, when you might want to use a noncopyable type, and how value ownership lets you state your intentions clearly.
Chapters
- 0:00 - Introduction
- 0:30 - Agenda
- 0:50 - Copying
- 7:05 - Noncopyable Types
- 11:50 - Generics
- 19:12 - Extensions
- 21:24 - Wrap up
Resources
- Copyable
- Forum: Programming Languages
- Swift Evolution: Borrowing and consuming pattern matching for noncopyable types
- Swift Evolution: Noncopyable Generics
- Swift Evolution: Noncopyable Standard Library Primitives
Related Videos
WWDC19
-
DownloadArray
-
-
0:52 - Player as a struct
struct Player { var icon: String } func test() { let player1 = Player(icon: "🐸") var player2 = player1 player2.icon = "🚚" assert(player1.icon == "🐸") }
-
1:55 - Player as a class
class PlayerClass { var icon: String init(_ icon: String) { self.icon = icon } } func test() { let player1 = PlayerClass("🐸") let player2 = player1 player2.icon = "🚚" assert(player1.icon == "🐸") }
-
3:00 - Deeply copying a PlayerClass
class PlayerClass { var data: Icon init(_ icon: String) { self.data = Icon(icon) } init(from other: PlayerClass) { self.data = Icon(from: other.data) } } func test() { let player1 = PlayerClass("🐸") var player2 = player1 player2 = PlayerClass(from: player2) player2.data.icon = "🚚" assert(player1.data.icon == "🐸") } struct Icon { var icon: String init(_ icon: String) { self.icon = icon } init(from other: Icon) { self.icon = other.icon } }
-
5:10 - Copyable BankTransfer
class BankTransfer { var complete = false func run() { assert(!complete) // .. do it .. complete = true } deinit { if !complete { cancel() } } func cancel() { /* ... */ } } func schedule(_ transfer: BankTransfer, _ delay: Duration) async throws { if delay < .seconds(1) { transfer.run() } try await Task.sleep(for: delay) transfer.run() } func startPayment() async { let payment = BankTransfer() log.append(payment) try? await schedule(payment, .seconds(3)) } let log = Log() final class Log: Sendable { func append(_ transfer: BankTransfer) { /* ... */ } }
-
7:46 - Copying FloppyDisk
struct FloppyDisk: ~Copyable {} func copyFloppy() { let system = FloppyDisk() let backup = consume system load(system) // ... } func load(_ disk: borrowing FloppyDisk) {}
-
8:18 - Missing ownership for FloppyDisk
struct FloppyDisk: ~Copyable { } func newDisk() -> FloppyDisk { let result = FloppyDisk() format(result) return result } func format(_ disk: FloppyDisk) { // ... }
-
9:00 - Consuming ownership
struct FloppyDisk: ~Copyable { } func newDisk() -> FloppyDisk { let result = FloppyDisk() format(result) return result } func format(_ disk: consuming FloppyDisk) { // ... }
-
9:26 - Borrowing ownership
struct FloppyDisk: ~Copyable { } func newDisk() -> FloppyDisk { let result = FloppyDisk() format(result) return result } func format(_ disk: borrowing FloppyDisk) { var tempDisk = disk // ... }
-
9:55 - Inout ownership
struct FloppyDisk: ~Copyable { } func newDisk() -> FloppyDisk { var result = FloppyDisk() format(&result) return result } func format(_ disk: inout FloppyDisk) { var tempDisk = disk // ... disk = tempDisk }
-
10:28 - Noncopyable BankTransfer
struct BankTransfer: ~Copyable { consuming func run() { // .. do it .. discard self } deinit { cancel() } consuming func cancel() { // .. do the cancellation .. discard self } }
-
11:10 - Schedule function for noncopyable BankTransfer
func schedule(_ transfer: consuming BankTransfer, _ delay: Duration) async throws { if delay < .seconds(1) { transfer.run() return } try await Task.sleep(for: delay) transfer.run() }
-
12:12 - Overview of conformance constraints
struct Command { } protocol Runnable { consuming func run() } extension Command: Runnable { func run() { /* ... */ } } func execute1<T>(_ t: T) {} func execute2<T>(_ t: T) where T: Runnable { t.run() } func test(_ cmd: Command, _ str: String) { execute1(cmd) execute1(str) execute2(cmd) execute2(str) // expected error: 'execute2' requires that 'String' conform to 'Runnable' }
-
15:50 - Noncopyable generics: 'execute' function
protocol Runnable: ~Copyable { consuming func run() } struct Command: Runnable { func run() { /* ... */ } } struct BankTransfer: ~Copyable, Runnable { consuming func run() { /* ... */ } } func execute2<T>(_ t: T) where T: Runnable { t.run() } func execute3<T>(_ t: consuming T) where T: Runnable, T: ~Copyable { t.run() } func test() { execute2(Command()) execute2(BankTransfer()) // expected error: 'execute2' requires that 'BankTransfer' conform to 'Copyable' execute3(Command()) execute3(BankTransfer()) }
-
18:05 - Conditionally Copyable
struct Job<Action: Runnable & ~Copyable>: ~Copyable { var action: Action? } func runEndlessly(_ job: consuming Job<Command>) { while true { let current = copy job current.action?.run() } } extension Job: Copyable where Action: Copyable {} protocol Runnable: ~Copyable { consuming func run() } struct Command: Runnable { func run() { /* ... */ } }
-
19:27 - Extensions of types with noncopyable generic parameters
extension Job { func getAction() -> Action? { return action } } func inspectCmd(_ cmdJob: Job<Command>) { let _ = cmdJob.getAction() let _ = cmdJob.getAction() } func inspectXfer(_ transferJob: borrowing Job<BankTransfer>) { let _ = transferJob.getAction() // expected error: method 'getAction' requires that 'BankTransfer' conform to 'Copyable' } struct Job<Action: Runnable & ~Copyable>: ~Copyable { var action: Action? } extension Job: Copyable where Action: Copyable {} protocol Runnable: ~Copyable { consuming func run() } struct Command: Runnable { func run() { /* ... */ } } struct BankTransfer: ~Copyable, Runnable { consuming func run() { /* ... */ } }
-
20:14 - Cancellable for Jobs with Copyable actions
protocol Cancellable { mutating func cancel() } extension Job: Cancellable { mutating func cancel() { action = nil } }
-
21:00 - Cancellable for all Jobs
protocol Cancellable: ~Copyable { mutating func cancel() } extension Job: Cancellable where Action: ~Copyable { mutating func cancel() { action = nil } }
-
-
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.