From 98fdeb35ff76dbcf423866337fa21e74811407f3 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Tue, 14 Jul 2026 02:04:55 -0400 Subject: [PATCH 01/90] Fix concurrency gap in UIImage's environment-dependent inits A fully clean rebuild (wiped DerivedData/module cache, not just xcodebuild clean) surfaced this among several concurrency errors the prior Swift 6 migration's verification builds never caught, since Xcode's incremental build state was stale throughout that work and silently hid real failures behind cached success. These inits/statics default to EnvironmentValues.defaultEnvironment, which is @MainActor, so they need @MainActor themselves. --- Sources/CarPlayUI/Extensions/UIImage.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Sources/CarPlayUI/Extensions/UIImage.swift b/Sources/CarPlayUI/Extensions/UIImage.swift index bc7d4a0..5cf43a2 100644 --- a/Sources/CarPlayUI/Extensions/UIImage.swift +++ b/Sources/CarPlayUI/Extensions/UIImage.swift @@ -11,6 +11,7 @@ import CarPlay internal extension UIImage { + @MainActor convenience init?( _ image: _ImageProxy, environment: EnvironmentValues = .defaultEnvironment @@ -38,6 +39,7 @@ internal extension UIImage { } } + @MainActor static func unsafe( _ image: Image, environment: EnvironmentValues = .defaultEnvironment, @@ -46,7 +48,8 @@ internal extension UIImage { ) -> UIImage { unsafe(_ImageProxy(image), environment: environment, file: file, line: line) } - + + @MainActor static func unsafe( _ image: _ImageProxy, environment: EnvironmentValues = .defaultEnvironment, From 6cbb5c613dbf4d5dc830f426caa3724a19cc7228 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Tue, 14 Jul 2026 02:05:03 -0400 Subject: [PATCH 02/90] Fix concurrency gap in _AnimationModifier's Equatable witnesses _AnimationModifier and its private ContentWrapper both conform to Equatable alongside ViewModifier/View, so their == witnesses need to be nonisolated to match Equatable's (non-isolated) requirement despite the enclosing MainActor-inferred type. Their stored properties (animation, value, lastValue) get nonisolated(unsafe) since Value is an unconstrained generic with no Sendable guarantee. --- .../CarPlayUI/TokamakCore/Animation/Animation.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Sources/CarPlayUI/TokamakCore/Animation/Animation.swift b/Sources/CarPlayUI/TokamakCore/Animation/Animation.swift index 589b5e5..8f3d107 100644 --- a/Sources/CarPlayUI/TokamakCore/Animation/Animation.swift +++ b/Sources/CarPlayUI/TokamakCore/Animation/Animation.swift @@ -143,8 +143,8 @@ public struct _AnimationProxy { public struct _AnimationModifier: ViewModifier, Equatable where Value: Equatable { - public var animation: Animation? - public var value: Value + public nonisolated(unsafe) var animation: Animation? + public nonisolated(unsafe) var value: Value @inlinable public init(animation: Animation?, value: Value) { @@ -155,10 +155,10 @@ public struct _AnimationModifier: ViewModifier, Equatable private struct ContentWrapper: View, Equatable { let content: Content let animation: Animation? - let value: Value + nonisolated(unsafe) let value: Value @State - private var lastValue: Value? + nonisolated(unsafe) private var lastValue: Value? var body: some View { content.transaction { @@ -168,7 +168,7 @@ public struct _AnimationModifier: ViewModifier, Equatable } } - static func == (lhs: Self, rhs: Self) -> Bool { + nonisolated static func == (lhs: Self, rhs: Self) -> Bool { lhs.value == rhs.value } } @@ -177,7 +177,7 @@ public struct _AnimationModifier: ViewModifier, Equatable ContentWrapper(content: content, animation: animation, value: value) } - public static func == (lhs: Self, rhs: Self) -> Bool { + public nonisolated static func == (lhs: Self, rhs: Self) -> Bool { lhs.value == rhs.value && lhs.animation == rhs.animation } From 1c9ac3f80c242e492b84b1f68a961be53e32096c Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Tue, 14 Jul 2026 02:05:13 -0400 Subject: [PATCH 03/90] Fix concurrency gap in AnyLayoutBox's animatableData requirement AnyLayoutBox is @MainActor to match Layout, but its animatableData requirement mirrors Animatable's (non-isolated) requirement, so it needs a per-requirement nonisolated override - same shape as the AnyShapeBox fix from the original migration, just missed for the Fiber layout system's equivalent type. --- .../CarPlayUI/TokamakCore/Fiber/Layout/Layout.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Sources/CarPlayUI/TokamakCore/Fiber/Layout/Layout.swift b/Sources/CarPlayUI/TokamakCore/Fiber/Layout/Layout.swift index d52da8f..b739076 100644 --- a/Sources/CarPlayUI/TokamakCore/Fiber/Layout/Layout.swift +++ b/Sources/CarPlayUI/TokamakCore/Fiber/Layout/Layout.swift @@ -286,11 +286,11 @@ protocol AnyLayoutBox: AnyObject { cache: inout Self.Cache ) -> CGFloat? - var animatableData: _AnyAnimatableData { get set } + nonisolated var animatableData: _AnyAnimatableData { get set } } final class ConcreteLayoutBox: AnyLayoutBox { - var base: L + nonisolated(unsafe) var base: L init(_ base: L) { self.base = base @@ -381,7 +381,7 @@ final class ConcreteLayoutBox: AnyLayoutBox { } } - var animatableData: _AnyAnimatableData { + nonisolated var animatableData: _AnyAnimatableData { get { .init(base.animatableData) } @@ -394,7 +394,7 @@ final class ConcreteLayoutBox: AnyLayoutBox { @frozen public struct AnyLayout: Layout { - var storage: AnyLayoutBox + nonisolated(unsafe) var storage: AnyLayoutBox public init(_ layout: L) where L: Layout { storage = ConcreteLayoutBox(layout) @@ -469,7 +469,7 @@ public struct AnyLayout: Layout { ) } - public var animatableData: _AnyAnimatableData { + public nonisolated var animatableData: _AnyAnimatableData { get { _AnyAnimatableData(storage.animatableData) } From 93f2142739dbe47688b60121feb60386c004d416 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Tue, 14 Jul 2026 02:05:19 -0400 Subject: [PATCH 04/90] Fix concurrency gap in _OpacityEffect's animatableData Marks animatableData and the opacity property it reads nonisolated, matching Animatable's non-isolated requirement despite _OpacityEffect also conforming to the MainActor-inferred ViewModifier. --- .../TokamakCore/Modifiers/Effects/OpacityEffect.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/CarPlayUI/TokamakCore/Modifiers/Effects/OpacityEffect.swift b/Sources/CarPlayUI/TokamakCore/Modifiers/Effects/OpacityEffect.swift index 382ae05..b083f21 100644 --- a/Sources/CarPlayUI/TokamakCore/Modifiers/Effects/OpacityEffect.swift +++ b/Sources/CarPlayUI/TokamakCore/Modifiers/Effects/OpacityEffect.swift @@ -16,7 +16,7 @@ // public struct _OpacityEffect: Animatable, ViewModifier, Equatable { - public var opacity: Double + public nonisolated var opacity: Double public init(opacity: Double) { self.opacity = opacity @@ -26,7 +26,7 @@ public struct _OpacityEffect: Animatable, ViewModifier, Equatable { content } - public var animatableData: Double { + public nonisolated var animatableData: Double { get { opacity } set { opacity = newValue } } From 24571a548ffd8afa79ea11f2517d65fcfb55ea54 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Tue, 14 Jul 2026 02:05:30 -0400 Subject: [PATCH 05/90] Fix concurrency gap in _RotationEffect's animatableData Same fix as _OpacityEffect: animatableData and the angle/anchor properties it reads need nonisolated(unsafe) to match Animatable's non-isolated requirement. --- .../TokamakCore/Modifiers/Effects/RotationEffect.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/CarPlayUI/TokamakCore/Modifiers/Effects/RotationEffect.swift b/Sources/CarPlayUI/TokamakCore/Modifiers/Effects/RotationEffect.swift index e9e4c4f..7017a6b 100644 --- a/Sources/CarPlayUI/TokamakCore/Modifiers/Effects/RotationEffect.swift +++ b/Sources/CarPlayUI/TokamakCore/Modifiers/Effects/RotationEffect.swift @@ -18,8 +18,8 @@ import Foundation public struct _RotationEffect: GeometryEffect { - public var angle: Angle - public var anchor: UnitPoint + public nonisolated(unsafe) var angle: Angle + public nonisolated(unsafe) var anchor: UnitPoint public init(angle: Angle, anchor: UnitPoint = .center) { self.angle = angle @@ -34,7 +34,7 @@ public struct _RotationEffect: GeometryEffect { content } - public var animatableData: AnimatablePair { + public nonisolated var animatableData: AnimatablePair { get { .init(angle.animatableData, anchor.animatableData) } From b37b01290d91088d1a1118934a1284292c5bec64 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Tue, 14 Jul 2026 02:05:47 -0400 Subject: [PATCH 06/90] Fix concurrency gap in _VariadicView_Children.Element's Identifiable Element conforms to View and Identifiable in the same declaration, so whole-type isolation inference made its id witness main-actor-isolated even though Identifiable's requirement isn't. nonisolated(unsafe) resolves it, matching the same pattern used for Text/Image's Equatable witnesses. --- .../CarPlayUI/TokamakCore/Views/Containers/VariadicView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/CarPlayUI/TokamakCore/Views/Containers/VariadicView.swift b/Sources/CarPlayUI/TokamakCore/Views/Containers/VariadicView.swift index 542511a..6cd339d 100644 --- a/Sources/CarPlayUI/TokamakCore/Views/Containers/VariadicView.swift +++ b/Sources/CarPlayUI/TokamakCore/Views/Containers/VariadicView.swift @@ -66,7 +66,7 @@ public struct _VariadicView_Children { extension _VariadicView_Children: RandomAccessCollection { public struct Element: View, Identifiable { let view: AnyView - public var id: AnyHashable + public nonisolated(unsafe) var id: AnyHashable let viewTraits: _ViewTraitStore let onTraitsUpdated: (_ViewTraitStore) -> () From c441338d5e2b53d259073c6a4a03f6fb0cbe266a Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Tue, 14 Jul 2026 02:06:06 -0400 Subject: [PATCH 07/90] Fix concurrency gap in _Button's @State isPressed Same pattern as other @State properties fixed during the original migration (TaskModifier, DisclosureGroup, etc.): the property wrapper's isolation inference can't resolve a plain mutable stored property without an explicit nonisolated(unsafe). --- Sources/CarPlayUI/TokamakCore/Views/Controls/ButtonBase.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/CarPlayUI/TokamakCore/Views/Controls/ButtonBase.swift b/Sources/CarPlayUI/TokamakCore/Views/Controls/ButtonBase.swift index 5314873..6078fc7 100644 --- a/Sources/CarPlayUI/TokamakCore/Views/Controls/ButtonBase.swift +++ b/Sources/CarPlayUI/TokamakCore/Views/Controls/ButtonBase.swift @@ -104,7 +104,7 @@ public struct _Button