Skip to content

refactor: migrate to Swift 6 language mode#10

Merged
poolcamacho merged 1 commit intomasterfrom
refactor/swift-6
Apr 20, 2026
Merged

refactor: migrate to Swift 6 language mode#10
poolcamacho merged 1 commit intomasterfrom
refactor/swift-6

Conversation

@poolcamacho
Copy link
Copy Markdown
Owner

Summary

Bumps SWIFT_VERSION from 5.0 to 6.0 on every build config (Maple, MapleTests, MapleUITests × Debug / Release) and fixes the three strict concurrency errors Swift 6 surfaces. No user-facing change; sets the foundation for writing new code against Swift 6 concurrency guarantees.

What changed

  • Maple.xcodeproj/project.pbxprojSWIFT_VERSION flipped on all six build configs.
  • DiffParser — marked nonisolated at the enum level. Parsing is pure value-to-value work; forcing it onto MainActor (via the project-wide SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor) was the source of the errors because GitService (an actor) consumes it from its own isolation domain.
  • DiffFile — same fix. flattened and the two patchText builders now live in a nonisolated struct so they're callable from the parser.
  • FileWatcher — stays MainActor-isolated (it talks to @Observable state that feeds the UI), but switches to isolated deinit so deinit can still call stop() to cancel the dispatch sources and close the watched FDs. Swift 6 no longer lets a nonisolated deinit implicitly call a MainActor method.
  • README.md — Swift badge bumped from 5 to 6.

Decisions

  • Kept SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor. The rest of the project (AppState, GitCoordinator, every View) already assumes MainActor by default. Flipping that would be a much bigger refactor and is not what Swift 6 strict mode actually needs. The three outliers above are genuinely non-UI and belong off the main actor.
  • nonisolated at type level instead of per-member. DiffParser and DiffFile are data-only — every current member (and any future one) wants to run anywhere. Less repetition, less drift.

Not in this PR

Test plan

  • xcodebuild -scheme Maple -configuration Debug builds clean
  • swiftlint --strict reports zero violations
  • Launch the app, open a repo, confirm the FileWatcher still fires refreshes on external git edits (creates a commit, switches a branch via terminal)
  • Interactive staging still works end-to-end (pick lines, Cmd+S, confirm index via terminal)

Flips SWIFT_VERSION from 5.0 to 6.0 on every build config (Maple,
MapleTests, MapleUITests × Debug / Release) and upgrades the toolchain
holistically — CI runners and README requirements — so the project
tracks Swift 6.3 idioms instead of shimming around older stable
features.

Code changes for strict concurrency:

- DiffParser: enum marked nonisolated. Parsing is pure value-to-value
  work and is consumed by GitService (an actor) from its own
  isolation domain — forcing it onto MainActor (via the project-wide
  SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor) was the source of the
  errors.
- DiffFile: struct marked nonisolated for the same reason; its
  flattened view and patch builders now run wherever the parser does.
- FileWatcher: keeps MainActor isolation (it feeds @observable state
  the UI reads) and switches to isolated deinit so deinit can still
  call stop() to cancel the dispatch sources and close the FDs. This
  is stable on Swift 6.3; the feature shipped with Xcode 26.

Tooling:

- .github/workflows/ci.yml, codeql.yml, release.yml: runs-on bumped
  from macos-15 (Xcode 16.x, Swift 6.0 where isolated deinit is still
  gated behind an experimental flag) to macos-26 (Xcode 26.x,
  Swift 6.3 stable).
- README: Swift badge 5 → 6, Requirements line updated to Xcode 26+
  with a short note explaining why.

Deployment target stays macOS 14.0; isolated deinit is a compile-time
feature and does not raise the runtime floor.

Build clean, swiftlint --strict clean.
@poolcamacho poolcamacho merged commit 71e7dd0 into master Apr 20, 2026
4 checks passed
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.

1 participant