Standard Library Overview

This section documents the Swift 6 language mode as shipped by Swift 6.3, as published in The Swift Programming Language at docs.swift.org, which is the reference these pages are written and verified against. 6.4-beta-only features are always flagged as such — never presented as baseline.

This content was generated with the assistance of AI and should be verified against docs.swift.org before being relied on in production.

This section’s bibliography lists the reference material consulted while preparing these pages.

The Swift module — imported implicitly into every Swift file — is where the language’s built-in types (Int, String, Array, Optional, …​) and the protocols that give them a common vocabulary actually live. This page is a map of that module: what the core protocol families are for and how they relate, with detail pages elsewhere covering the types built on top of them in depth.

Numeric Protocols

Protocol What it adds

Numeric

+, -, *, a magnitude, and creation from an integer literal — the floor for anything number-like.

BinaryInteger

Integer semantics: division and remainder truncate toward zero, bitwise operators, and conversion between integer types.

FixedWidthInteger

Refines BinaryInteger with a fixed bitWidth, min/max, and overflow-reporting operations — every concrete integer type (Int, UInt8, …​) conforms.

FloatingPoint

IEEE 754-style semantics: NaN, infinities, rounding rules, ulp, and exact representability concerns.

SignedNumeric / SignedInteger / UnsignedInteger

Narrow a generic parameter to only signed, or only unsigned, numeric types.

func sum<T: Numeric>(_ values: [T]) -> T {
    values.reduce(0, +)                     // works for Int, Double, Decimal, or any custom Numeric type
}

func isEven<T: BinaryInteger>(_ value: T) -> Bool {
    value % 2 == 0                          // works for any integer type, signed or unsigned
}

See Advanced Operators for BinaryInteger and FixedWidthInteger used in bit-manipulation code, and Generics for constraining type parameters to protocols in general.

Equatable, Hashable, Comparable, Identifiable

Protocol Requirement Typically

Equatable

static func == (lhs: Self, rhs: Self) → Bool

Synthesized automatically for structs/enums whose members are all Equatable.

Hashable

func hash(into: inout Hasher), refines Equatable

Synthesized alongside Equatable; lets a type be a Set element or Dictionary key.

Comparable

static func < (lhs: Self, rhs: Self) → Bool, refines Equatable

Unlocks <, , >, >=, sorted(), and min/max.

Identifiable

var id: ID { get }

A stable identity distinct from equality — two values can be Identifiable-equal (same id) while their contents differ.

struct User: Identifiable, Comparable {
    let id: Int
    var name: String

    static func < (lhs: User, rhs: User) -> Bool {
        lhs.name < rhs.name
    }
}

let users = [User(id: 2, name: "Bo"), User(id: 1, name: "Ada")]
users.sorted()                              // sorted by name, via Comparable
Set(users.map(\.id))                        // Hashable Int ids, not the User itself

Identifiable is deliberately independent of Equatable/Hashable: a UI list keyed by id can still detect content changes separately by also conforming to Equatable.

CustomStringConvertible and Friends

Protocol Used by

CustomStringConvertible

String(describing:), string interpolation, print — provide description.

CustomDebugStringConvertible

debugPrint, the debugger’s po — provide debugDescription, typically more detailed.

LosslessStringConvertible

Refines CustomStringConvertible and adds init?(_ description: String) —  round-trips through a string (Int, Double, Bool all conform).

TextOutputStream / TextOutputStreamable

The other direction: a custom destination print can write into.

struct Point: CustomStringConvertible {
    var x: Double, y: Double
    var description: String { "(\(x), \(y))" }
}

print(Point(x: 1, y: 2))                    // "(1.0, 2.0)" -- print uses `description` automatically

ExpressibleBy…​Literal

A type that conforms to one of these can be constructed directly from a literal in source, with the compiler inferring which init to call:

struct Fraction: ExpressibleByIntegerLiteral {
    var numerator: Int
    var denominator: Int = 1

    init(integerLiteral value: Int) {
        numerator = value
    }
}

let half: Fraction = 1                      // calls init(integerLiteral:) -- no explicit constructor call

ExpressibleByStringLiteral, ExpressibleByBooleanLiteral, ExpressibleByArrayLiteral, ExpressibleByDictionaryLiteral and ExpressibleByNilLiteral follow the same shape for their respective literal forms; Optional’s conformance to `ExpressibleByNilLiteral is what makes bare nil type-check as any optional type.

Sequence and Collection

Sequence requires only makeIterator() → some IteratorProtocol, which is enough to support for…​in and every lazy, one-pass algorithm (map, filter, reduce, …​); Collection refines it with random-access indices (startIndex, endIndex, subscript), letting a value be traversed more than once and indexed directly. See Collections for the concrete Array, Set and Dictionary types built on these protocols, and Control Flow for for…​in over any Sequence.

Optional and Result

Optional<Wrapped> and Result<Success, Failure> are ordinary enums in the standard library, not compiler magic — Optional has cases none and some(Wrapped); Result has success(Success) and failure(Failure). See Optionals for Optional in depth, and Error Handling for Result alongside throws.

Ranges and Stride

let closed = 1...10                         // ClosedRange<Int>
let halfOpen = 1..<10                       // Range<Int>
let partial = 1...                          // PartialRangeFrom<Int>

for value in stride(from: 0, to: 10, by: 2) {   // 0, 2, 4, 6, 8 -- `to` excludes the end
    print(value)
}
for value in stride(from: 10, through: 0, by: -2) {   // 10, 8, ..., 0 -- `through` includes the end
    print(value)
}

Range/ClosedRange model a span between two bounds; stride(from:to:by:)/stride(from:through:by:) produce a Sequence stepping by an arbitrary amount, which a plain range (whose implicit step is always 1) cannot express. See Operators for the …​/..< range operators themselves.

print, readLine and Random Numbers

print("value:", 42, separator: " ", terminator: "\n")   // configurable separator/terminator
let line = readLine()                       // String?, nil at end-of-input

let roll = Int.random(in: 1...6)
let coin = Bool.random()
let card = ["clubs", "diamonds", "hearts", "spades"].randomElement()   // Element?, nil if empty

Int.random(in:), Double.random(in:), Bool.random() and Collection.randomElement()/shuffled() all draw from the system’s default random source; a type conforming to RandomNumberGenerator can be passed explicitly (Int.random(in: 1…​6, using: &myGenerator)) for reproducible sequences in tests.

Codable, in Overview

Codable (Encodable & Decodable) lets a type convert to and from an external representation such as JSON, with conformance synthesized automatically when every stored property is itself Codable. This page stops at that overview — see Codable and Serialization for CodingKeys, custom init(from:)/encode(to:), and JSONEncoder/JSONDecoder in depth.

UniqueArray and Ref are Swift 6.4-beta only. UniqueArray<Element> is a noncopyable, uniquely-owned array (no reference-counting overhead, no accidental sharing); Ref<Value> is a lightweight, non-atomic reference wrapper for giving a noncopyable value reference semantics inside a single isolation domain. Neither has shipped in a stable Swift release as of 6.3; treat both as subject to change until they do.

Never

func fatalErrorExample() -> Never {
    fatalError("unreachable")
}

func processOrCrash(_ value: Int?) -> Int {
    guard let value else {
        fatalError("value must not be nil")   // return type Never unifies with Int here
    }
    return value
}

Never is an enum with no cases, so no value of type Never can ever exist; a function returning Never therefore can never return normally — it must trap, loop forever, or throw. The type checker exploits this: Never unifies with any other type, which is why a guard/switch branch calling a Never-returning function type-checks against whatever the surrounding function actually returns.

See Also