# Building Safer Swift Code with Noncopyable Types


### **What Are Noncopyable Types?**

In Swift, most types are copyable by default. When you assign one variable to another or pass a value to a function, Swift creates a copy. However, some resources should have exactly one owner - think of a file handle, database connection, or unique system resource.

Noncopyable types enforce single ownership at compile time, preventing accidental duplication of resources that should remain unique.

### **The Problem They Solve**

Consider managing a file handle. With regular Swift types, you might accidentally create multiple references to the same file, leading to bugs when the file is closed multiple times. Noncopyable types prevent this at compile time.

### **Basic Syntax**

```swift
struct FileHandler: ~Copyable {
    private let fileDescriptor: Int32
    
    init(path: String) throws {
        fileDescriptor = open(path, O_RDONLY)
        guard fileDescriptor >= 0 else {
            throw FileError.cannotOpen
        }
    }
    
    deinit {
        close(fileDescriptor)
    }
}
```

The `~Copyable` constraint means "not copyable". This type:
- Has value semantics but cannot be copied
- Guarantees single ownership
- Automatically cleans up resources
- Provides compile-time safety

## Core Concepts

### **Ownership and Movement**

With noncopyable types, you don't copy values - you move them:

```swift
var file1 = try FileHandler(path: "data.txt")
var file2 = file1  // Error: Cannot copy noncopyable type

// To transfer ownership, you must use it:
func processFile(_ file: FileHandler) {
    // Function now owns the file
}

processFile(file1)  // file1 is no longer valid after this
```

### **Borrowing vs Consuming**

Swift provides two ways to work with noncopyable values:

**Borrowing**: Temporary access without taking ownership
**Consuming**: Taking ownership permanently

## Practical Examples

### **Example 1: Database Transaction**

A database transaction is a perfect candidate for noncopyable types. You want exactly one owner who can commit or rollback:

```swift
struct DatabaseTransaction: ~Copyable {
    private let connection: DatabaseConnection
    private let transactionID: String
    private var isActive = true
    
    init(connection: DatabaseConnection) throws {
        self.connection = connection
        self.transactionID = try connection.beginTransaction()
    }
    
    // Borrowing: Check status without consuming
    borrowing func executeQuery(_ sql: String) throws -> QueryResult {
        guard isActive else {
            throw DatabaseError.transactionInactive
        }
        return try connection.execute(sql, in: transactionID)
    }
    
    // Consuming: Commit consumes the transaction
    consuming func commit() throws {
        try connection.commit(transactionID)
        isActive = false
    }
    
    // Consuming: Rollback also consumes the transaction
    consuming func rollback() throws {
        try connection.rollback(transactionID)
        isActive = false
    }
    
    deinit {
        // Auto-rollback if not committed
        if isActive {
            try? connection.rollback(transactionID)
        }
    }
}

// Usage:
func updateUserData() throws {
    var transaction = try DatabaseTransaction(connection: db)
    
    // Can execute multiple queries (borrowing)
    try transaction.executeQuery("UPDATE users SET active = true WHERE id = 1")
    try transaction.executeQuery("INSERT INTO logs (action) VALUES ('user_activated')")
    
    // Must explicitly commit or rollback (consuming)
    try transaction.commit()
    // transaction is no longer usable here
}
```

### **Example 2: Unique Network Request Token**

For network requests, you might want a token that can only be used once:

```swift
struct RequestToken: ~Copyable {
    private let id: String
    private let endpoint: URL
    
    init(endpoint: URL) {
        self.id = UUID().uuidString
        self.endpoint = endpoint
    }
    
    // Borrowing: Check token info without consuming
    borrowing func info() -> (id: String, endpoint: URL) {
        return (id, endpoint)
    }
    
    // Consuming: Using the token invalidates it
    consuming func performRequest() async throws -> Data {
        var request = URLRequest(url: endpoint)
        request.setValue(id, forHTTPHeaderField: "X-Request-Token")
        
        let (data, _) = try await URLSession.shared.data(for: request)
        return data
    }
}

// Usage:
func fetchUserData() async throws {
    let token = RequestToken(endpoint: URL(string: "https://api.example.com/user")!)
    
    // Can inspect token (borrowing)
    print("Request ID: \(token.info().id)")
    
    // Perform request (consuming)
    let userData = try await token.performRequest()
    // token is no longer valid - prevents accidental reuse
}
```

### **Example 3: Generic Container with Conditional Copyability**

Sometimes you want a container that's only copyable when its contents are copyable:

```swift
struct SecureBox<T: ~Copyable>: ~Copyable {
    private var content: T
    
    init(_ content: consuming T) {
        self.content = content
    }
    
    // Borrowing: Read access
    borrowing func peek<R>(_ operation: (borrowing T) -> R) -> R {
        operation(content)
    }
    
    // Consuming: Take the content out
    consuming func unwrap() -> T {
        content
    }
}

// The box becomes copyable when T is copyable
extension SecureBox: Copyable where T: Copyable {}

// Usage with noncopyable type:
let fileBox = SecureBox(try FileHandler(path: "data.txt"))
// let copy = fileBox  // Error: Cannot copy

// Usage with copyable type:
let stringBox = SecureBox("Hello")
let copy = stringBox  // OK: String is copyable, so SecureBox<String> is copyable
```

## Key Takeaways

### **When to Use Noncopyable Types**

**Perfect for:**
- System resources (files, sockets, locks)
- Unique tokens or sessions
- Transactions that must complete exactly once
- RAII (Resource Acquisition Is Initialization) patterns

**Avoid for:**
- Simple data that needs to be shared
- Types used frequently in collections
- When copyability is a natural expectation


## Conclusion

Noncopyable types provide compile-time guarantees about resource ownership, eliminating entire classes of bugs. While they require thinking differently about value movement, the safety and performance benefits make them invaluable for systems programming and resource management in Swift.
