Skip to content

Enable Swift 6 for KDS#2771

Open
stevestreza-ksr wants to merge 2 commits intomainfrom
stevestreza/kds-swift-6
Open

Enable Swift 6 for KDS#2771
stevestreza-ksr wants to merge 2 commits intomainfrom
stevestreza/kds-swift-6

Conversation

@stevestreza-ksr
Copy link
Copy Markdown
Contributor

@stevestreza-ksr stevestreza-ksr commented Feb 24, 2026

📲 What

This PR enables Swift 6 support for the KDS module.

🤔 Why

Swift 6 makes stronger guarantees about memory safety and concurrency, and can be accessed by Swift 5 modules.

🛠 How

  • Disabled the Swift 5 compatibility mode in KDS
  • Added an Atomic<Bool> for the font registration static value, which gives Swift 6 the synchronization guarantee to make it Sendable
  • Added Sendable conformance to the different Color types
  • Deleted the @retroactive Identifiable which is now a compile time error in Swift 6 mode

✅ Acceptance criteria

App should build and run. Tests should work.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the KDS SwiftPM module to build in Swift 6 mode and addresses Swift 6 concurrency/safety requirements around font registration state and color model types.

Changes:

  • Removed Swift 5 language-mode pin so KDS builds under Swift 6 defaults.
  • Replaced the font-registration global flag with an atomic to satisfy Swift 6 synchronization requirements.
  • Updated color models/extensions to align with Swift 6 rules (Sendable/Identifiable, removal of @retroactive).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
KDS/Sources/KDS/Fonts/InterFont.swift Uses Synchronization.Atomic to back isRegistered for Swift 6 safety.
KDS/Sources/KDS/Controllers/ColorsView.swift Removes @retroactive and keeps Identifiable conformances compiling in Swift 6.
KDS/Sources/KDS/Colors/SemanticColor.swift Adds Sendable to AdaptiveColor and color structs for Swift 6 concurrency checks.
KDS/Package.swift Removes Swift 5 compatibility language-mode configuration to enable Swift 6 mode.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

}
set {
registeredInterfont = newValue
_ = registeredInterfont.exchange(newValue, ordering: .acquiringAndReleasing)
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isRegistered setter uses exchange and discards the returned old value. If you only need to write the flag, prefer an atomic store operation (with an appropriate ordering) to make intent clearer and avoid the extra read/modify overhead.

Suggested change
_ = registeredInterfont.exchange(newValue, ordering: .acquiringAndReleasing)
registeredInterfont.store(newValue, ordering: .releasing)

Copilot uses AI. Check for mistakes.
}
set {
registeredInterfont = newValue
_ = registeredInterfont.exchange(newValue, ordering: .acquiringAndReleasing)
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switching the backing flag to an Atomic removes the data race on the boolean, but the overall registration flow is still not thread-safe: two callers can both observe isRegistered == false and proceed to register concurrently, potentially triggering the “calling this more than once” failure path. Consider using an atomic compare-and-swap (or another synchronization mechanism) to ensure only one thread performs registration.

Suggested change
_ = registeredInterfont.exchange(newValue, ordering: .acquiringAndReleasing)
if newValue {
var expected = false
_ = registeredInterfont.compareExchange(
expected: &expected,
desired: true,
ordering: .acquiringAndReleasing
)
} else {
registeredInterfont.store(false, ordering: .releasing)
}

Copilot uses AI. Check for mistakes.
import UIKit

public protocol AdaptiveColor {
public protocol AdaptiveColor: Sendable {
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AdaptiveColor is a public protocol; making it inherit from Sendable is a source-breaking API change for any downstream module that conforms its own types to AdaptiveColor (those types must now be Sendable too). If the goal is only to satisfy Swift 6 checks for KDS’s concrete color types, consider keeping AdaptiveColor non-Sendable and adding Sendable only to SemanticColor/LegacyColor (or introducing a separate internal/sendable protocol).

Suggested change
public protocol AdaptiveColor: Sendable {
public protocol AdaptiveColor {

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@amy-at-kickstarter amy-at-kickstarter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious about how much more effort it would take to make some (or all) of KDS live on @MainActor - since most of it probably shouldn't be used off of the UI thread. At a minimum, getting font registration on @MainActor seems valuable. I think everything else should be reasonably safe.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants