Claude
Skills
Sign in
Back

memory

Included with Lifetime
$97 forever

Swift 6.2 InlineArray and Span types for zero-overhead memory access, fixed-size collections, and safe pointer alternatives. Use when optimizing performance-critical code paths.

General

What this skill does


# InlineArray and Span

Guidance for Swift 6.2's low-level memory types: `InlineArray` for fixed-size inline storage without heap allocation, and `Span` for safe, zero-cost access to contiguous memory. These replace common uses of `UnsafeBufferPointer` and hand-tuned tuple storage with compiler-checked alternatives.

## When This Skill Activates

Use this skill when the user:
- Asks about **InlineArray**, **fixed-size arrays**, or **stack-allocated collections**
- Mentions **Span**, **MutableSpan**, **RawSpan**, or **UTF8Span**
- Wants to **eliminate heap allocations** in hot paths
- Is replacing **UnsafeBufferPointer** or **UnsafePointer** with safe alternatives
- Asks about **value generics** or `let count: Int` generic parameters
- Needs **zero-copy** access to collection storage
- Mentions **inline storage**, **contiguous memory**, or **memory layout**
- Is doing **binary parsing**, **signal processing**, or **embedded Swift** work
- Wants to avoid **copy-on-write overhead** for small fixed collections
- Asks about **non-escapable types** or **lifetime dependencies** in Swift

## Decision Tree

```
What memory optimization do you need?
│
├─ A fixed-size collection that never grows/shrinks
│  │
│  ├─ Size known at compile time, stored on stack
│  │  └─ InlineArray<N, Element>
│  │     ├─ No heap allocation
│  │     ├─ No reference counting
│  │     └─ No copy-on-write (eager copies)
│  │
│  └─ Size may vary at runtime
│     └─ Array<Element> (standard library)
│
├─ Safe read access to contiguous memory
│  │
│  ├─ Read-only access to typed elements
│  │  └─ Span<Element>
│  │
│  ├─ Mutable access to typed elements
│  │  └─ MutableSpan<Element>
│  │
│  ├─ Read-only access to raw bytes
│  │  └─ RawSpan
│  │
│  ├─ Mutable access to raw bytes
│  │  └─ MutableRawSpan
│  │
│  ├─ Unicode text processing
│  │  └─ UTF8Span
│  │
│  └─ Initializing a new collection's storage
│     └─ OutputSpan
│
├─ Unsafe pointer access (legacy or interop)
│  └─ UnsafeBufferPointer / UnsafeMutableBufferPointer
│     └─ Prefer Span instead for new code
│
└─ Standard dynamic collection
   └─ Array<Element>
      ├─ Heap-allocated, copy-on-write
      └─ Grows/shrinks dynamically
```

## API Availability

| API | Minimum Version | Notes |
|-----|----------------|-------|
| `InlineArray<let count: Int, Element>` | Swift 6.2 | Uses value generics; `@frozen` struct |
| `Span<Element>` | Swift 6.2 | Non-escapable, lifetime-dependent |
| `MutableSpan<Element>` | Swift 6.2 | Mutable variant of Span |
| `RawSpan` | Swift 6.2 | Untyped byte-level access |
| `MutableRawSpan` | Swift 6.2 | Mutable untyped byte access |
| `UTF8Span` | Swift 6.2 | Unicode-aware text processing |
| `OutputSpan` | Swift 6.2 | For initializing collection storage |
| `.span` property on `Array` | Swift 6.2 | Returns `Span<Element>` |
| `.span` property on `Data` | Swift 6.2 | Returns `Span<UInt8>` |

## Top 5 Mistakes

| # | Mistake | Fix |
|---|---------|-----|
| 1 | Trying to append/remove elements on `InlineArray` | `InlineArray` is fixed-size; use `Array` if you need dynamic sizing |
| 2 | Returning a `Span` from a function | `Span` is non-escapable and cannot outlive its source; restructure to process data within the same scope |
| 3 | Capturing a `Span` in a closure | `Span` cannot be captured; pass the span as a parameter or use `Array` for escaped contexts |
| 4 | Using `InlineArray` for large or frequently copied collections | `InlineArray` copies eagerly (no COW); use `Array` for large data that is shared or copied often |
| 5 | Accessing a `Span` after mutating the source container | Mutation invalidates the span; re-acquire the span after any modification |

## InlineArray

### Declaration

`InlineArray` uses Swift's value generics to encode the count in the type:

```swift
@frozen struct InlineArray<let count: Int, Element> where Element: ~Copyable
```

### Initialization

```swift
// Explicit count
let a: InlineArray<4, Int> = [1, 2, 4, 8]

// Count inferred from literal
let b: InlineArray<_, Int> = [1, 2, 4, 8]  // count = 4

// Element type inferred from literal
let c: InlineArray<4, _> = [1, 2, 4, 8]    // Element = Int

// Both inferred
let d: InlineArray = [1, 2, 4, 8]           // InlineArray<4, Int>
```

### Memory Layout

Elements are stored contiguously with no overhead. Size equals `count * MemoryLayout<Element>.stride`:

```swift
MemoryLayout<InlineArray<0, UInt16>>.size       // 0
MemoryLayout<InlineArray<0, UInt16>>.stride      // 1
MemoryLayout<InlineArray<3, UInt16>>.size        // 6  (2 bytes x 3)
MemoryLayout<InlineArray<3, UInt16>>.stride       // 6
MemoryLayout<InlineArray<3, UInt16>>.alignment   // 2  (same as UInt16)
```

### Basic Usage

```swift
var array: InlineArray<3, Int> = [1, 2, 3]

// Subscript access
array[0] = 4

// Iterate via indices
for i in array.indices {
    print(array[i])
}

// Copies are eager (no copy-on-write)
var copy = array
copy[0] = 99
// array[0] is still 4
```

### InlineArray vs Array

| Characteristic | InlineArray | Array |
|---------------|-------------|-------|
| Storage | Inline (stack or enclosing type) | Heap-allocated buffer |
| Size | Fixed at compile time | Dynamic |
| Copy semantics | Eager (full copy) | Copy-on-write |
| Reference counting | None | Yes (buffer reference) |
| Exclusivity checks | None | Yes |
| Append/remove | Not supported | Supported |

## Span Family

### Span (Read-Only)

Provides safe, direct access to contiguous typed memory. Non-escapable -- cannot outlive the source.

```swift
let array = [1, 2, 3, 4]
let span = array.span  // Span<Int>

// Access elements
let first = span[0]
let count = span.count

// Iterate
for element in span {
    print(element)
}
```

### MutableSpan

Mutable access to contiguous storage:

```swift
var array = [1, 2, 3, 4]
array.withMutableSpan { span in
    for i in span.indices {
        span[i] *= 2
    }
}
// array is now [2, 4, 6, 8]
```

### RawSpan

Untyped byte-level access for binary data:

```swift
let data = Data([0xFF, 0x00, 0xAB, 0xCD])
let rawSpan = data.span  // Span<UInt8> for byte-level access
```

### UTF8Span

Specialized for safe and efficient Unicode processing of UTF-8 encoded text.

## Safety Constraints

### Non-Escapable: Cannot Return from Functions

`Span` has a lifetime dependency on the container it was derived from. It cannot be returned:

```swift
// ❌ Wrong -- Span cannot escape the function
func getSpan() -> Span<UInt8> {
    let array: [UInt8] = Array(repeating: 0, count: 128)
    return array.span  // Compiler error
}

// ✅ Right -- process within the same scope
func processData(_ array: [UInt8]) {
    let span = array.span
    // Use span here
    let sum = span.reduce(0, +)
}
```

### Non-Escapable: Cannot Capture in Closures

```swift
// ❌ Wrong -- Span cannot be captured
func makeClosure() -> () -> Int {
    let array: [UInt8] = Array(repeating: 0, count: 128)
    let span = array.span
    return { span.count }  // Compiler error
}

// ✅ Right -- use Span within the local scope only
func countElements(_ array: [UInt8]) -> Int {
    let span = array.span
    return span.count
}
```

### Invalidation on Mutation

Modifying the source container invalidates any existing span:

```swift
// ❌ Wrong -- span is invalidated after mutation
var array = [1, 2, 3]
let span = array.span
array.append(4)        // Invalidates span
// let x = span[0]     // Undefined behavior

// ✅ Right -- re-acquire span after mutation
var array = [1, 2, 3]
array.append(4)
let span = array.span  // Fresh span after mutation
let x = span[0]        // Safe
```

## Performance Considerations

### When InlineArray Wins

- **Small, fixed-size data** (e.g., color components, matrix rows, coordinate tuples)
- **Hot loops** where heap allocation / ARC overhead is measurable
- **Embedded Swift** or contexts with no allocator
- **Struct fields** that should be stored inline rather than behind a pointer

### When Array Wins

- Collection size is unknown or variable
- Collection is large and

Related in General