Generate, review, or refactor Swift code using modern language features from Swift 6.0 through 6.2.3. Use when writing new Swift code, reviewing existing code for outdated patterns, migrating from Swift 5.x to 6.x, debugging concurrency warnings, or answering questions about current Swift idioms. Covers concurrency, typed throws, noncopyable types, observation, testing, and more.
100
100%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Passed
No known issues
Use this skill to ensure Swift code uses current language features and avoids deprecated or outdated patterns. It covers Swift 6.0, 6.1, and 6.2 with SE-proposal-level traceability. This skill focuses on language-level features and best practices without enforcing specific architectures.
references/SWIFT_6_0.md)@Observable + Observations for reactive state outside SwiftUI (SE-0475, see references/SWIFT_6_2.md)references/SWIFT_6_2.md)InlineArray for fixed-size collections (SE-0453, see references/SWIFT_6_2.md)references/SWIFT_6_0.md)@MainActor annotations are explicit where needed post-SE-0401references/SWIFT_6_1.md)@unchecked Sendable — compiler region analysis (SE-0414) may make them redundantreferences/MIGRATION.md for comprehensive old → new mappings with before/after code@MainActor to views using @StateObject/@ObservedObject (SE-0401)-default-isolation MainActor for UI-focused modules (SE-0466, Swift 6.2+)#expect(throws:) return values (ST-0006), exit tests (ST-0008)references/SWIFT_6_0.md, references/SWIFT_6_1.md, references/SWIFT_6_2.mdreferences/SWIFT_6_0.md for sending keyword (SE-0430)@MainActor annotations; consider nonisolated at type level (SE-0449, see references/SWIFT_6_1.md)let, isolate to @MainActor, or use nonisolated(unsafe) as last resort (SE-0412, see references/SWIFT_6_0.md)@concurrent to opt out (see references/SWIFT_6_2.md)isolated deinit (SE-0371, Swift 6.2+, see references/SWIFT_6_2.md)-default-isolation MainActor and only opt out with nonisolated or @concurrent where background work is genuinely needed (SE-0466).@Sendable conformances or @unchecked Sendable when the compiler can prove safety through region isolation (SE-0414).Mutex for shared mutable state — prefer Mutex from the Synchronization library over NSLock or os_unfair_lock. Use Atomic for simple lock-free flags and counters (SE-0433, SE-0410).nonisolated on types to opt out of inherited actor isolation at the type level rather than annotating every member (SE-0449, Swift 6.1+).Task.immediate when the task must begin executing synchronously from the caller's context before any suspension point (SE-0472, Swift 6.2+).name: parameter to Task.init(), Task.detached(), and addTask() in task groups (SE-0469, Swift 6.2+).@concurrent to opt into the old hop-off behavior (SE-0461, Swift 6.2+).isolated deinit for actor-isolated classes that need safe cleanup of non-Sendable state (SE-0371, Swift 6.2+).@MainActor Equatable (SE-0470, Swift 6.2+).throws for public library APIs to preserve flexibility (SE-0413).throws(E) enables throws(Never) inference for non-throwing closures, eliminating unnecessary do/catch.InlineArray for fixed-size collections where the count is known at compile time. Prefer [N of T] sugar syntax (SE-0483). Note: does not conform to Sequence/Collection — iterate via .indices (SE-0453, Swift 6.2+).weak let for immutable weak references, especially in Sendable types where weak var would prevent conformance (SE-0481, Swift 6.2+).~Copyable) for unique-ownership semantics. Optional and Result now support noncopyable wrapped types (SE-0427, SE-0437, Swift 6.0+).Observations for programmatic observation of @Observable changes outside SwiftUI — replaces manual KVO or Combine-based observation (SE-0475, Swift 6.2+).@DebugDescription on types with CustomDebugStringConvertible to enable custom formatting in LLDB's p command and Xcode's variables view (SE-0440, Swift 6.0+).@frozen unless the case list is genuinely complete and will never grow. This allows adding cases in minor versions without breaking consumers (SE-0487, Swift 6.2.3+).@unknown default to switches over public enums from external packages to future-proof against new cases.@retroactive when conforming external types to external protocols to acknowledge the retroactive conformance and silence the compiler warning (SE-0364, Swift 6.0+).\(optional, default: "fallback") supports cross-type defaults (SE-0477, Swift 6.2+).internal import or private import to prevent accidental API leakage (SE-0409, Swift 6.0+).MemberImportVisibility flag to require explicit imports per file (SE-0444, Swift 6.1+).@Test, #expect, #require.confirmation(expectedCount: 5...10) (ST-0005, Swift 6.1+).#expect(throws:) instead of the deprecated dual-trailing-closure form (ST-0006, Swift 6.1+).TestScoping protocol (ST-0007, Swift 6.1+).#expect(processExitsWith: .failure) for testing precondition/fatalError paths (ST-0008, Swift 6.2+).Attachment.record(value, named:) for debugging failing tests (ST-0009, Swift 6.2+).| Deprecated / Outdated | Modern Replacement | Since | SE |
|---|---|---|---|
Bare global var | let, @MainActor var, or nonisolated(unsafe) | 6.0 | SE-0412 |
@StateObject infers @MainActor | Explicit @MainActor on view required | 6.0 | SE-0401 |
| Catch-all for exhaustive error types | throws(SpecificError) eliminates catch-all | 6.0 | SE-0413 |
withTaskGroup(of: T.self) | withTaskGroup { } (type inferred) | 6.1 | SE-0442 |
Per-member nonisolated | nonisolated struct/class at type level | 6.1 | SE-0449 |
| Transitive imports leak across files | Enable MemberImportVisibility flag | 6.1 | SE-0444 |
#expect { } throws: { } (dual closure) | let error = #expect(throws: T.self) { } | 6.1 | ST-0006 |
Manual @MainActor on every type | -default-isolation MainActor per module | 6.2 | SE-0466 |
camelCase test names + @Test("...") | Raw identifiers: @Test func `readable name`() | 6.2 | SE-0451 |
| Nonisolated async hops off actor | Now stays on caller's actor; @concurrent to opt out | 6.2 | SE-0461 |
Task { } for immediate work | Task.immediate { } runs synchronously until first await | 6.2 | SE-0472 |
weak var in Sendable types | weak let enables Sendable conformance | 6.2 | SE-0481 |
Combine/KVO for @Observable changes | Observations { } AsyncSequence | 6.2 | SE-0475 |
| Tuples for fixed-size data | InlineArray<N, T> with subscript access | 6.2 | SE-0453 |
\(optional ?? "fallback") (same type only) | \(optional, default: "fallback") (cross-type) | 6.2 | SE-0477 |
Regular deinit in actor-isolated class | isolated deinit for safe cleanup | 6.2 | SE-0371 |
InlineArray<N, T> (verbose) | [N of T] sugar syntax | 6.2 | SE-0483 |
NSLock / os_unfair_lock | Mutex from Synchronization library | 6.0 | SE-0433 |
| Manual atomic operations / locks for flags | Atomic<Value> from Synchronization library | 6.0 | SE-0410 |
No LLDB summary from debugDescription | @DebugDescription macro enables p command formatting | 6.0 | SE-0440 |
| Silent retroactive conformance | @retroactive annotation required (compiler warning) | 6.0 | SE-0364 |
String(bytes:encoding:) | String(validating:as: UTF8.self) returns Optional | 6.0 | SE-0405 |
| Adding enum case = SemVer-major break | Extensible by default; @frozen to opt out | 6.2.3 | SE-0487 |
let, actor-isolated, or nonisolated(unsafe))@StateObject/@ObservedObject have explicit @MainActor@unchecked Sendable — check if region analysis handles itMutex or Atomic, not NSLock/os_unfair_lockname: parameternonisolated async behavior is intentional (caller-inheriting in 6.2+ vs hop-off in <6.2)isolated deinit used where actor-isolated class accesses non-Sendable state in cleanupInlineArray uses [N of T] sugar syntax where availableweak let used instead of weak var where immutability suffices (enables Sendable)Observations used instead of Combine/KVO for @Observable outside SwiftUIdefault: parameter for optional cross-type fallbacks@DebugDescription used on types with CustomDebugStringConvertibleString(validating:as:) used instead of String(bytes:encoding:) for safe encodingMemberImportVisibility enabled)internal import, private import)@frozen only when case list is truly fixedswitch over external enums includes @unknown default@retroactive#expect(throws:) returns error for separate validation (not dual-closure form)precondition/fatalError paths| Version | Release | Key Features |
|---|---|---|
| 6.0 | Sep 2024 | Complete concurrency by default, typed throws, Mutex/Atomics, noncopyable upgrades, RangeSet, Int128 |
| 6.1 | Spring 2025 | Trailing commas, metatype key paths, diagnostic groups, nonisolated types, import visibility |
| 6.2 | WWDC 2025 | Default MainActor isolation, raw identifiers, InlineArray + [N of T] sugar, immediate tasks, weak let, Observations |
| 6.2.3 | Late 2025 | Extensible enums for non-resilient modules (SE-0487) |
references/SWIFT_6_0.md — Concurrency defaults, Mutex/Atomics, typed throws, @DebugDescription, noncopyable upgrades, AsyncSequence generics, RangeSet, Int128, BitwiseCopyablereferences/SWIFT_6_1.md — Trailing commas, metatype key paths, TaskGroup inference, nonisolated types, import visibility, diagnostic groups, Swift Testing improvementsreferences/SWIFT_6_2.md — Default MainActor isolation, raw identifiers, InlineArray + [N of T] sugar, immediate tasks, weak let, Observations, Span/MutableSpan, method key paths, exit testsreferences/SWIFT_6_2_3.md — Extensible enums for non-resilient modules (SE-0487)references/MIGRATION.md — Comprehensive old → new pattern mappings with before/after code for all versionsThis skill focuses on language-level facts and best practices, not opinions:
307e013
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.