Remove blanket retroactive KeyPath: Sendable conformance - #19
Merged
Conversation
ThemeKit shipped `extension KeyPath: @retroactive @unchecked Sendable`, a global conformance on a std-lib type ThemeKit does not own. It leaks into every consumer and collides with libraries that manage key-path sendability themselves — notably TCA, which deliberately avoids such a conformance and uses scoped `_Sendable*KeyPath` existentials instead. The collision surfaces as a build failure in TCA-using code: Type 'WritableKeyPath<Root, BindingState<Value>>' does not conform to the 'Sendable' protocol The conformance only existed to let the generated ThemeShadowedStyle / ThemeShapeStyle structs (which store a KeyPath<Theme, ...> and conform to ShapeStyle: Sendable) synthesize Sendable. Make those generated structs `@unchecked Sendable` instead — sendability is asserted locally and self-contained, since the stored key path is read-only over the Sendable Theme type. Drop the now-redundant per-property `nonisolated` on the key-path storage so it builds under MainActor default isolation. Removes KeyPath+Sendable.swift and its test. The deleted test verified sendability at the std-lib layer; replace it with coverage where it now matters: generator assertions on the emitted declarations, plus compile-time Sendable and cross-actor checks against the generated styles in all four language-mode/isolation fixture targets. Co-Authored-By: Foti Dim <foti.dimanidis@numan.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #19 +/- ##
=======================================
Coverage 98.91% 98.92%
=======================================
Files 36 35 -1
Lines 2213 2229 +16
=======================================
+ Hits 2189 2205 +16
Misses 24 24 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
rozd
added a commit
that referenced
this pull request
Aug 14, 2026
Brings in the retroactive-KeyPath removal (#19) ahead of the close-out merge, so the conflicts resolve here rather than in the umbrella PR. Both changes edit the same two generator templates for different reasons — main swaps the generated styles from synthesized `Sendable` (which needed the now-deleted blanket `KeyPath: Sendable` conformance) to `@unchecked Sendable`, while this branch splits each template into Apple and Android variants. Git only flagged the Android arm, because main's single hunk matched the first of the two copies; the Apple arm merged silently and still carried the old spelling. Applied main's `@unchecked Sendable` and dropped the per-property `nonisolated` in *both* arms, and updated the two branch-side assertions that pinned the old declarations. `Sources/ThemeKit/KeyPath+Sendable.swift` is gone; nothing on this branch referenced it outside the generated styles it existed to serve. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ports BeaNuman/theme-kit#1 by @fdnmgh.
Problem
ThemeKit shipped
extension KeyPath: @retroactive @unchecked Sendable, a global conformance on a std-lib type ThemeKit does not own. Swift has no module-scoped conformances, so it becomes law for every consumer once linked — and it collides with libraries that manage key-path sendability themselves. Notably TCA deliberately avoids such a conformance and uses scoped_Sendable*KeyPathexistentials instead; the collision surfaces as a build failure in TCA-using code:Fix
The conformance only existed so the generated
ThemeShapeStyle/ThemeShadowedStylestructs — which store aKeyPath<Theme, ...>and conform toShapeStyle: Sendable— could synthesizeSendable. Those structs now declare@unchecked Sendabledirectly. The safety argument stays local and self-contained: the stored key path is read-only over theSendableThemetype.The per-property
nonisolatedon the key-path storage (added in 5bf9280) becomes redundant once the struct asserts sendability itself, and is dropped so the generated code builds under MainActor default isolation.Sources/ThemeKit/KeyPath+Sendable.swiftand its test are removed.Tests
The deleted
KeyPathSendableTestsverified sendability at the std-lib layer, which no longer exists. Coverage moves to where it now matters:ThemeFileGeneratorTests— assert the emitted declarations carry@unchecked Sendableand no longer carrynonisolatedstorage.GeneratedCodeCompilationTests— compile-timeSendablerequirement and a cross-actor hop against real generatedThemeShapeStyle/ThemeShadowedStylevalues, in all four language-mode × default-isolation fixture targets (Swift 5/6 × nonisolated/MainActor).swift buildand all 220 tests pass locally.🤖 Generated with Claude Code