Fix: Resolve Swift 6 Equatable conformance errors for View types

Add explicit nonisolated == implementations using MainActor.assumeIsolated
for all View types with @preconcurrency Equatable conformances:

- Box
- Card
- ContainerView
- _ContainerViewCore
- Dialog
- Panel
- ProgressView
- VStack, HStack, ZStack

This fixes CI failures on macOS where the derived Equatable conformance
cannot access @MainActor-isolated properties from nonisolated context.
This commit is contained in:
phranck
2026-02-07 13:43:34 +01:00
parent fcdd9ccd75
commit f51a343adf
7 changed files with 102 additions and 10 deletions
+9 -1
View File
@@ -164,4 +164,12 @@ struct BufferView: View, Renderable {
// MARK: - Equatable Conformance
extension Box: @preconcurrency Equatable where Content: Equatable {}
extension Box: Equatable where Content: Equatable {
nonisolated public static func == (lhs: Box<Content>, rhs: Box<Content>) -> Bool {
MainActor.assumeIsolated {
lhs.content == rhs.content &&
lhs.borderStyle == rhs.borderStyle &&
lhs.borderColor == rhs.borderColor
}
}
}
+11 -1
View File
@@ -127,7 +127,17 @@ public struct Card<Content: View, Footer: View>: View {
// MARK: - Equatable Conformance
extension Card: @preconcurrency Equatable where Content: Equatable, Footer: Equatable {}
extension Card: Equatable where Content: Equatable, Footer: Equatable {
nonisolated public static func == (lhs: Card<Content, Footer>, rhs: Card<Content, Footer>) -> Bool {
MainActor.assumeIsolated {
lhs.title == rhs.title &&
lhs.content == rhs.content &&
lhs.footer == rhs.footer &&
lhs.config == rhs.config &&
lhs.backgroundColor == rhs.backgroundColor
}
}
}
// MARK: - Rendering
+24 -2
View File
@@ -246,7 +246,18 @@ struct ContainerView<Content: View, Footer: View>: View {
// MARK: - Equatable Conformance
extension ContainerView: @preconcurrency Equatable where Content: Equatable, Footer: Equatable {}
extension ContainerView: Equatable where Content: Equatable, Footer: Equatable {
nonisolated static func == (lhs: ContainerView<Content, Footer>, rhs: ContainerView<Content, Footer>) -> Bool {
MainActor.assumeIsolated {
lhs.title == rhs.title &&
lhs.titleColor == rhs.titleColor &&
lhs.content == rhs.content &&
lhs.footer == rhs.footer &&
lhs.style == rhs.style &&
lhs.padding == rhs.padding
}
}
}
// MARK: - Convenience Initializer (no footer)
@@ -463,4 +474,15 @@ private struct _ContainerViewCore<Content: View, Footer: View>: View, Renderable
// MARK: - Equatable Conformance
extension _ContainerViewCore: @preconcurrency Equatable where Content: Equatable, Footer: Equatable {}
extension _ContainerViewCore: Equatable where Content: Equatable, Footer: Equatable {
nonisolated static func == (lhs: _ContainerViewCore<Content, Footer>, rhs: _ContainerViewCore<Content, Footer>) -> Bool {
MainActor.assumeIsolated {
lhs.title == rhs.title &&
lhs.titleColor == rhs.titleColor &&
lhs.content == rhs.content &&
lhs.footer == rhs.footer &&
lhs.style == rhs.style &&
lhs.padding == rhs.padding
}
}
}
+10 -1
View File
@@ -102,7 +102,16 @@ public struct Dialog<Content: View, Footer: View>: View {
// MARK: - Equatable Conformance
extension Dialog: @preconcurrency Equatable where Content: Equatable, Footer: Equatable {}
extension Dialog: Equatable where Content: Equatable, Footer: Equatable {
nonisolated public static func == (lhs: Dialog<Content, Footer>, rhs: Dialog<Content, Footer>) -> Bool {
MainActor.assumeIsolated {
lhs.title == rhs.title &&
lhs.content == rhs.content &&
lhs.footer == rhs.footer &&
lhs.config == rhs.config
}
}
}
// MARK: - Rendering
+10 -1
View File
@@ -122,7 +122,16 @@ public struct Panel<Content: View, Footer: View>: View {
// MARK: - Equatable Conformance
extension Panel: @preconcurrency Equatable where Content: Equatable, Footer: Equatable {}
extension Panel: Equatable where Content: Equatable, Footer: Equatable {
nonisolated public static func == (lhs: Panel<Content, Footer>, rhs: Panel<Content, Footer>) -> Bool {
MainActor.assumeIsolated {
lhs.title == rhs.title &&
lhs.content == rhs.content &&
lhs.footer == rhs.footer &&
lhs.config == rhs.config
}
}
}
// MARK: - Convenience Initializer (no footer)
+10 -1
View File
@@ -227,7 +227,16 @@ extension ProgressView {
// MARK: - Equatable Conformance
extension ProgressView: @preconcurrency Equatable where Label: Equatable, CurrentValueLabel: Equatable {}
extension ProgressView: Equatable where Label: Equatable, CurrentValueLabel: Equatable {
nonisolated public static func == (lhs: ProgressView<Label, CurrentValueLabel>, rhs: ProgressView<Label, CurrentValueLabel>) -> Bool {
MainActor.assumeIsolated {
lhs.fractionCompleted == rhs.fractionCompleted &&
lhs.style == rhs.style &&
lhs.label == rhs.label &&
lhs.currentValueLabel == rhs.currentValueLabel
}
}
}
// MARK: - Rendering
+28 -3
View File
@@ -230,9 +230,34 @@ public struct Alignment: Sendable, Equatable {
// MARK: - Equatable Conformances
extension VStack: @preconcurrency Equatable where Content: Equatable {}
extension HStack: @preconcurrency Equatable where Content: Equatable {}
extension ZStack: @preconcurrency Equatable where Content: Equatable {}
extension VStack: Equatable where Content: Equatable {
nonisolated public static func == (lhs: VStack<Content>, rhs: VStack<Content>) -> Bool {
MainActor.assumeIsolated {
lhs.alignment == rhs.alignment &&
lhs.spacing == rhs.spacing &&
lhs.content == rhs.content
}
}
}
extension HStack: Equatable where Content: Equatable {
nonisolated public static func == (lhs: HStack<Content>, rhs: HStack<Content>) -> Bool {
MainActor.assumeIsolated {
lhs.alignment == rhs.alignment &&
lhs.spacing == rhs.spacing &&
lhs.content == rhs.content
}
}
}
extension ZStack: Equatable where Content: Equatable {
nonisolated public static func == (lhs: ZStack<Content>, rhs: ZStack<Content>) -> Bool {
MainActor.assumeIsolated {
lhs.alignment == rhs.alignment &&
lhs.content == rhs.content
}
}
}
// MARK: - VStack Rendering