SwiftQA Random

What are opaque return types (some) and why were they introduced?

The problem opaque types solve

Before Swift 5.1 (SE-0244), if you wanted a function to return “something conforming to protocol P” without committing to a concrete return type, your only option was returning the protocol type itself as an existential. This breaks down in two important cases:

1. Protocols with associated types (or Self requirements) can’t be used this way at all

protocol Container {
    associatedtype Item
    var items: [Item] { get }
}
func makeContainer() -> Container { ... } // ❌ compile error

2. Even when it compiles, returning the protocol type erases useful information — and costs performance

Every caller only knows “this is some Shape” — type identity is lost (can’t compare two Shape existentials even if both concrete types are the same and comparable), and existentials require witness tables and possibly heap-boxing.

The some solution: opaque types

func makeShape() -> some Shape {
    return Circle()
}
  • The compiler knows the concrete type at the definition site — compiles down the generics path, direct calls, no witness-table indirection.
  • The caller does not know the concrete type, but relies on it consistently.
  • Type identity is preserved across calls to the same function — two calls to makeShape() always return the same underlying concrete type.
  • It unlocks associated-type protocols as return typessome Container works even though -> Container doesn’t.

Concrete motivating example — SwiftUI

var body: some View {
    VStack {
        Text("Hello")
        Image(systemName: "star")
    }
}

View has an associated type (Body), so -> View isn’t even expressible as an existential in general.

Comparison table

-> Shape (existential)-> some Shape (opaque)
Concrete type known to compiler?No (erased)Yes, at definition site
Concrete type known to caller?NoNo
Same type guaranteed across calls?NoYes
Works with associated-type protocols?Often noYes
PerformanceWitness table, possible heap boxSame as concrete type
Can compare with Equatable?No (unless same concrete type provably)Yes

One-liner if pressed: “Opaque types (some) let a function hide its concrete return type from callers while still giving the compiler full knowledge of it internally — you get the abstraction of a protocol return type without the existential’s cost or its associated-type limitations, because the compiler treats it like specialized generic code rather than a boxed existential.”