What Apple's Swift Team Said in the WWDC26 Lab
Apple published the WWDC26 Swift Group Lab as an hour of unscripted Q&A with four engineers from the Swift, Foundation, and server-networking teams, and then shipped it without captions.1 We ran the video through a local transcription pass to read what they actually said. The polished sessions tell you what a feature does. The lab is where Holly admits she was wrong about a core concurrency decision, where Corey explains the cleanup pattern that silently fails in cancelled code, and where the panel keeps repeating one piece of advice the marketing never will: stop collecting language features. The candid version lives here.
A note on sourcing: Apple released no official transcript for the lab. Every quote below is a paraphrase from a local transcription of the published video, with approximate timestamps. Speakers are attributed by first name and team as the transcript gives them: Holly (Swift language team, generics and concurrency), Corey (Swift server networking team), Tony (Foundation and standard library), and Doug (Swift language team).1
TL;DR
- Holly said if the team designed Swift concurrency today, nonisolated async functions would run in the caller’s context from day one. She held the opposite belief “for a very long time” and changed her mind on real-world evidence. Swift 6.2 made the caller-context default the standard.1
- The repeated guidance: make types non-
Sendableon purpose.~Sendable(SE-0518, implemented in Swift 6.4) gives a cleaner spelling, and Foundation is re-annotating types it had marked off-limits, with UserDefaults gaining a Sendable conformance on the global instance.21 - Corey’s async-cleanup pattern: cancelled contexts silently skip async cleanup, so audit every
async deferfor suspendingawaitcalls and wrap them in a cancellation shield. SE-0493 (asyncdefer) and SE-0504 (withTaskCancellationShield) both land in Swift 6.4.34 - Roadmap candor: the
Disconnectedtype is an active forums pitch, tuple conformances are “almost there” but formally back in revision,UniqueArrayis accepted in principle, Subprocess 1.0 is releasing, and SwiftPM is unifying on Swift Build.5678 - The panel’s recurring theme: “language features aren’t collectibles.” Profile first, adopt the narrow tool the profiler points you at, and leave the rest alone.1
The concurrency decision Apple would make differently
Holly’s concurrency retrospective begins around 33:42. The full lab has no official captions; the transcript below is local ASR.
A developer asked the panel a question polished sessions rarely invite: now that Swift 6 concurrency has been in the field long enough to watch adoption, is there anything the team would design differently today? Holly answered without hedging. Yes, certainly.
The specific regret is where a nonisolated async function runs. Two Swift Evolution proposals moved that behavior in opposite directions. The first made nonisolated async functions always hop to the global concurrent thread pool. The later one, in Swift 6.2, made them stay on whatever context called them, so a function called from the main actor stays on the main actor.1 Holly traced the reversal to evidence from people running the early concurrency-checking flags in real apps and libraries: they were passing non-Sendable types back and forth between an actor-isolated context and these nonisolated async functions, and the global-pool default produced data-race errors because the original actor still held those values while the async function ran elsewhere.1
Then the part that does not appear in any session recording. “I held on to the belief for a very long time that running on the global concurrent thread pool was the right model for the long-term benefits,” Holly said, “but I was convinced over time by issues in real-world projects” (ASR paraphrase, ~35:50).1 Doug framed the original call as a defensible whole-system bet: more available concurrency means more potential parallelism, which can mean better performance. The cost surfaced only once people used the full safety model, and it pushed too many types toward Sendable, which Doug called “not the natural way to express all of these ideas.”1 The caller-context default is more approachable because it behaves like non-concurrent code until you explicitly opt into parallelism. If you adopted Swift 6.2 and wondered why the concurrency story suddenly felt calmer, the answer is the people who designed it admitting the first default was the wrong one and shipping the fix.
Make your types non-Sendable on purpose
The lab’s most counterintuitive advice cuts against two years of migration habit. Holly said she constantly meets developers asking how to make their types Sendable, and that the better question is often the opposite: should this type be non-Sendable?1 For ephemeral types used inside a single computation, marking them explicitly non-Sendable produces a cleaner data model and a sharper line between what you intend to pass across isolation boundaries and what you do not. It also helps performance, because the cost of passing a type around is one you want to avoid paying on intermediate values that never needed to travel.1
Swift 6.4 gives the intent a real spelling. ~Sendable (SE-0518) lets you suppress the conformance directly, the way ~Copyable suppresses copyability, instead of writing an unavailable conformance.2 Holly drew the distinction precisely: an unavailable Sendable conformance declares the type and every subclass definitely not sendable and propagates that down the whole hierarchy, while ~Sendable is merely the absence of a conformance, so a subclass that adds no mutable state can still add its own Sendable conformance.21
That flexibility is exactly what Foundation needed. Tony explained the third category from Foundation’s original Sendable audit: classes where the superclass is safe but a subclass might not be. His example was NSString, which is immutable and sendable, against NSMutableString, which is a mutable subclass and is not.1 Rather than rush a wrong annotation, Foundation marked the ambiguous classes non-Sendable and waited. Now, Tony said in the lab, the team is using the Swift 6.4 annotation to re-annotate those types accurately, and he expects the standard global UserDefaults to gain a Sendable conformance.1 Treat the UserDefaults conformance and the broader Foundation re-annotation as lab-attributed: Tony stated both in the Q&A, and they are not features I can independently confirm from a published proposal. The panel’s standing warning applies here too, from Tony: do not reach for @unchecked Sendable to force Swift 6 mode, because every unchecked annotation discards the safety the compiler could have proven for you.1
Async cleanup, done so it actually runs
Corey owns the most practical correction in the lab, and it is the kind of bug you ship without noticing. Structured concurrency’s signature win is automatic cancellation propagation: cancel a task and everything spawned in service of it gets cancelled too, which is what you want when a view is dismissed or a client disconnects.1 The trap sits in cleanup. You might have a file half-written that needs flushing to a known-good state, or a database transaction to roll back, and that cleanup is itself asynchronous. As Corey put it, most Swift code refuses to execute in a cancelled context because it assumes it should unwind as fast as possible, so async cleanup running inside a cancelled task can quietly fail to do its job.1
The fix is a cancellation shield, and it pairs directly with async defer. SE-0493 lets a defer block contain await calls, landing in Swift 6.4.3 SE-0504 adds withTaskCancellationShield, also Swift 6.4, which runs a block as if cancellation has not been requested so suspending cleanup completes.4 Corey’s audit recipe is concrete: look at each async defer block and ask whether any await inside it will actually suspend. If one will, wrap it in a cancellation shield.1 He called the two “a great companion” and “a really good one-two punch for getting your resources cleaned up nicely.”1 Non-Sendable types reinforce the same discipline, as Corey noted, because a value that cannot cross concurrency domains forces your async control flow to stay linear and easy to reason about.1
The broader structured-concurrency advice from Corey rounds out the section. Lean into it assertively, because escape hatches cause the trouble. Avoid unstructured tasks (Task.detached or a bare Task) “at almost all costs” unless you are deliberately sending work elsewhere, and never in the mainline flow. Make task groups your default, fit object lifecycles to their lexical scope, and write linear async code: a recipe of step A, then B, then C, reaching for parallelism inside task groups only when the work genuinely fans out.1
Roadmap candor
The lab is also where the panel separates shipped features from optimistic ones, and the gap matters when you are deciding what to build on.
The question of storing a transferred non-Sendable value has a real answer coming. Today you transfer with the sending keyword and region-based isolation lets the compiler prove the original owner has released access, but if you need to store such a value, only the unsafe opt-outs work.1 Holly pointed to Disconnected, an active forums pitch for a type that preserves the transfer property through storage so you can stash a value and hand it off later. It is being designed and discussed right now, not implemented.51
Tuple conformances are the sharpest example of engineer optimism against formal status. Asked what remains before tuples conditionally conform to Equatable, Hashable, and Comparable, Holly explained it is an evolution of parameter packs: the language needs syntax to write an extension over a tuple whose element types are a parameter pack, with a where clause requiring each element to conform.1 She said an experimental implementation lives in the compiler repository and is “almost all the way there.”1 The formal record is more cautious. SE-0283, the original tuple-conformances proposal, was returned for revision and its 2020 implementation reverted; the general parameter-pack approach exists today only behind an experimental TupleConformances compiler flag.10 Read Holly’s “almost there” as an engineer’s honest read of the implementation, not a shipped feature.
The performance containers are further along. UniqueArray, which Tony mentioned, comes from SE-0527 (“RigidArray and UniqueArray”), now accepted in principle, introducing a new standard-library Containers module; it already ships in swift-collections 1.3 as an early form.7 Tony positioned it as the upgrade for an Array whose copy-on-write retain/release traffic shows up in an Instruments trace.1 Subprocess, the cross-platform open-source process API Tony named as his favorite, is releasing version 1.0 this year; the 1.0 milestone is announced, with the latest published tag still at 0.5, so it is releasing rather than released.61 On tooling, Holly described the SwiftPM change developers might not notice: Xcode’s package builds and the open-source toolchain’s builds now share one implementation, Swift Build, which is becoming the default build-system backend (default on main, targeting 6.4).81
Finally, the migration path Holly led with: @diagnose, the new attribute from SE-0522 (“Source-Level Control Over Compiler Warnings”), accepted.9 It gives source-level control over warnings, so you can suppress deprecation warnings in one region or opt into off-by-default warnings like strict memory safety or strict concurrency in the areas that matter most, which makes it a finer-grained tool for staged Swift 6 migration.1
Engineer guidance, collected
The lab’s value is the accumulated practitioner advice that never fits a session’s runtime. The highlights, attributed:
- Write linear async code. Corey: avoid unstructured tasks at almost all costs, keep each task a sequential recipe, and introduce parallelism only inside task groups when work genuinely fans out.1
- A MainActor migration recipe. Holly: start with leaf types and work outward, or flip on main-actor-by-default for a module that should be fully main-actor and annotate the offloaded parts explicitly. Mark methods that touch no mutable state
nonisolated, and convert astatic varthat is never actually mutated into aletso it can stay nonisolated.1 - Conformance costs are uneven. Doug: an unused
EquatableorHashableconformance keeps its witness code in the binary because a runtimeas?cast to an existential can discover it, so it costs code size;Sendableis a pure compile-time tag with no runtime representation, so an unusedSendableconformance is free.1 - The
@inlinableplus@inline(never)combo. Corey’s favorite trick:@inlinableexposes a function body across module boundaries and unlocks generic specialization and effects propagation, while@inline(never)keeps a cold, code-heavy path (a bytewise fallback copy) from being inlined so the hot path stays fast. He has used the pair “three times in the entire Swift networking portfolio,” for unusual cold-path performance problems.1 - Optimize the hottest path, not the project. Corey: “We’ve had great success introducing spans and a couple of unique arrays just along the hottest path,” which delivers almost all the performance gains for a small, compiler-supported change. Keep the new performance types isolated so adopting them never forces a giant refactor.1
- Stop collecting features. The panel’s recurring line, from a friend Corey quoted: “language features aren’t collectibles.” You get no prize for using all of them. Profile first, reach for the narrow tool the profiler points you at (non-copyable types,
UniqueArray,Span), and spend the rest of your hours on bug fixes and features.1
FAQ
Did Apple really publish the WWDC26 Swift lab without captions?
Yes. Apple posted the Swift Group Lab (session 8001) as a video with no official transcript or captions on the developer site.1 To quote it accurately, I ran the recording through a local transcription pass, so every quote in this post is a paraphrase from that local ASR with approximate timestamps, attributed by first name and team.1
What did the Swift team say they would change about concurrency?
Holly said that if Apple designed Swift concurrency today, nonisolated async functions would run in the caller’s context from the start rather than hopping to the global concurrent thread pool. She held the global-pool belief for a long time and changed her mind on real-world evidence, and Swift 6.2 made the caller-context behavior the default.1
Should I make my Swift types Sendable or non-Sendable?
The lab’s advice is to make ephemeral computation types non-Sendable on purpose. Swift 6.4 adds the ~Sendable spelling (SE-0518) for that, distinct from an unavailable conformance because subclasses can still add Sendable when they add no mutable state.2 Tony said Foundation is re-annotating its ambiguous classes with the new feature and expects the global UserDefaults to gain a Sendable conformance, both of which are lab-attributed.1
How do I make sure async cleanup runs when a task is cancelled?
Cancelled contexts cause most Swift code to skip suspending work, so async cleanup can silently fail. Corey’s pattern is to audit every async defer for await calls that actually suspend and wrap them in a cancellation shield. Async defer (SE-0493) and withTaskCancellationShield (SE-0504) both arrive in Swift 6.4.341
Are tuple conformances shipping in Swift?
Not yet. SE-0283 was returned for revision and its original implementation reverted; the general parameter-pack approach exists only behind an experimental TupleConformances flag. Holly said in the lab that an experimental implementation in the compiler is “almost all the way there,” which reflects engineer optimism rather than a shipped feature.1
The lab is the candid companion to the announcements: for the shipped features in context, read what’s new in Swift 2026, and for the migration mechanics behind the caller-context default Holly discussed, see Swift 6.2 concurrency in practice. The panel’s “profile first, adopt the narrow tool” philosophy extends to testing in Swift Testing versus XCTest. The full run of WWDC26 coverage lives in the Apple Ecosystem Series.
References
-
Apple, WWDC 2026 session 8001, Swift Group Lab. Apple published no official transcript or captions for this lab; all quotes attributed to it are paraphrases from a local transcription of the published video, with approximate timestamps. Source for the concurrency retrospective (Holly, ~33:42), the make-types-non-Sendable guidance, the Foundation re-annotation and UserDefaults Sendable conformance (both lab-attributed to Tony), the async-cleanup and cancellation-shield pattern (Corey), the structured-concurrency and MainActor migration advice (Corey and Holly), the conformance-cost explanation (Doug), the
@inlinableplus@inline(never)combo and hottest-path performance guidance (Corey), theDisconnected, tuple-conformance,UniqueArray, Subprocess, SwiftPM, and@diagnoseremarks, and the “language features aren’t collectibles” theme. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩ -
Apple / Swift Evolution, SE-0518,
~Sendablefor explicitly marking non-Sendabletypes. Status: Implemented (Swift 6.4). Source for suppressing theSendableconformance and the distinction from an unavailable conformance. ↩↩↩↩ -
Apple / Swift Evolution, SE-0493, Support
asynccalls indeferbodies. Status: Implemented (Swift 6.4). Source forawaitinsidedeferblocks. ↩↩↩ -
Apple / Swift Evolution, SE-0504, Task cancellation shields. Status: Implemented (Swift 6.4). Source for
withTaskCancellationShield. ↩↩↩ -
Swift Forums, Pitch:
Disconnectedtype for modeling disconnected values. Active forums pitch for safely storing transferred non-Sendablevalues; not implemented. ↩↩ -
Apple / Swift, Subprocess — cross-platform, open-source process API announced in 2025; version 1.0 announced as releasing this year, with the latest published tag at 0.5. Status per the lab and the project’s published releases. ↩↩
-
Apple / Swift Evolution, SE-0527, RigidArray and UniqueArray. Status: Accepted in Principle; introduces a new standard-library Containers module and ships in an early form in swift-collections 1.3. ↩↩
-
Swift Forums, SwiftPM development update: default build system change. Swift Build is becoming the default SwiftPM build-system backend (default on main, targeting 6.4). ↩↩
-
Apple / Swift Evolution, SE-0522, Source-Level Control Over Compiler Warnings. Status: Accepted. Source for the
@diagnoseattribute and region-scoped warning control. ↩ -
Apple / Swift Evolution, SE-0283, Tuples Conform to
Equatable,Comparable, andHashable. Status: Returned for revision; original implementation reverted. Source for the formal status of tuple conformances against the experimentalTupleConformancesflag. ↩